diff --git a/src/main/groovy/com/codebrig/arthur/observe/structure/filter/operator/misc/ElvisOperatorFilter.groovy b/src/main/groovy/com/codebrig/arthur/observe/structure/filter/operator/misc/ElvisOperatorFilter.groovy
new file mode 100644
index 0000000..a0ee3f1
--- /dev/null
+++ b/src/main/groovy/com/codebrig/arthur/observe/structure/filter/operator/misc/ElvisOperatorFilter.groovy
@@ -0,0 +1,38 @@
+package com.codebrig.arthur.observe.structure.filter.operator.misc
+
+import com.codebrig.arthur.SourceNode
+import com.codebrig.arthur.observe.structure.StructureFilter
+import com.codebrig.arthur.observe.structure.filter.InternalRoleFilter
+import com.codebrig.arthur.observe.structure.filter.MultiFilter
+import com.codebrig.arthur.observe.structure.filter.RoleFilter
+
+/**
+ * Match by Elvis operator
+ *
+ * @version 0.4
+ * @since 0.4
+ * @author Val Pecaoco
+ */
+class ElvisOperatorFilter extends StructureFilter {
+
+ private final MultiFilter filter
+
+ ElvisOperatorFilter() {
+ filter = MultiFilter.matchAll(
+ new RoleFilter("IF"), new RoleFilter("EXPRESSION"), new RoleFilter("RIGHT")
+ )
+ }
+
+ @Override
+ boolean evaluate(SourceNode node) {
+ boolean result = filter.evaluate(node)
+ if (result) {
+ def matched = MultiFilter.matchAll(
+ new RoleFilter("THEN"),
+ new InternalRoleFilter("if")
+ ).getFilteredNodes(node.children)
+ return !matched.hasNext()
+ }
+ return result
+ }
+}
diff --git a/src/test/groovy/com/codebrig/arthur/observe/structure/filter/operator/misc/ElvisOperatorFilterTest.groovy b/src/test/groovy/com/codebrig/arthur/observe/structure/filter/operator/misc/ElvisOperatorFilterTest.groovy
new file mode 100644
index 0000000..83e7e3b
--- /dev/null
+++ b/src/test/groovy/com/codebrig/arthur/observe/structure/filter/operator/misc/ElvisOperatorFilterTest.groovy
@@ -0,0 +1,41 @@
+package com.codebrig.arthur.observe.structure.filter.operator.misc
+
+import com.codebrig.arthur.ArthurTest
+import com.codebrig.arthur.SourceLanguage
+import com.codebrig.arthur.observe.structure.filter.FunctionFilter
+import com.codebrig.arthur.observe.structure.filter.MultiFilter
+import com.codebrig.arthur.observe.structure.filter.NameFilter
+import gopkg.in.bblfsh.sdk.v1.protocol.generated.Encoding
+import org.junit.Test
+
+import static org.junit.Assert.*
+
+class ElvisOperatorFilterTest extends ArthurTest {
+
+ @Test
+ void elvisOperator_Php() {
+ assertElvisOperatorPresent(new File("src/test/resources/same/operators/Operators.php"))
+ }
+
+ private static void assertElvisOperatorPresent(File file) {
+ assertElvisOperatorPresent(file, "")
+ }
+
+ private static void assertElvisOperatorPresent(File file, String qualifiedName) {
+ def language = SourceLanguage.getSourceLanguage(file)
+ def resp = client.parse(file.name, file.text, language.key, Encoding.UTF8$.MODULE$)
+
+ def foundElvisOperator = false
+ def functionFilter = new FunctionFilter()
+ def nameFilter = new NameFilter("elvisOperator")
+ MultiFilter.matchAll(functionFilter, nameFilter).getFilteredNodes(language, resp.uast).each {
+ assertEquals(qualifiedName + "elvisOperator()", it.name)
+
+ new ElvisOperatorFilter().getFilteredNodes(it).each {
+ assertFalse(foundElvisOperator)
+ foundElvisOperator = true
+ }
+ }
+ assertTrue(foundElvisOperator)
+ }
+}
diff --git a/src/test/resources/same/operators/Operators.php b/src/test/resources/same/operators/Operators.php
index f267052..948b576 100644
--- a/src/test/resources/same/operators/Operators.php
+++ b/src/test/resources/same/operators/Operators.php
@@ -48,4 +48,10 @@ function ternaryOperator()
$b = ($a == 1) ? 20 : 30;
}
+function elvisOperator()
+{
+ $a = 20;
+ $b = $a ?: 30;
+}
+
?>
\ No newline at end of file