]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/parser/regexp/ROp.java
Moved SCL parser generator to platform repository.
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / parser / regexp / ROp.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/parser/regexp/ROp.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/parser/regexp/ROp.java
new file mode 100644 (file)
index 0000000..5668df2
--- /dev/null
@@ -0,0 +1,98 @@
+package org.simantics.scl.compiler.parser.regexp;
+
+import org.simantics.scl.compiler.parser.regexp.automata.NFA;
+
+public class ROp extends Regexp {
+    public final Regexp exp;
+    public final char op;
+    
+    ROp(Regexp exp, char op) {
+        this.exp = exp;
+        this.op = op;
+    }
+    
+    @Override
+    public Regexp simplify() {
+        Regexp exp = this.exp.simplify();
+        if(exp instanceof ROp) {
+            ROp other = (ROp)exp;
+            if(other.op == op || other.op == '*')
+                return other;
+            else
+                return new ROp(other.exp, '*');
+        }
+        else if(exp.isNullable()) {
+            if(op == '?')
+                return exp;
+            if(op == '+')
+                return new ROp(exp, '*');
+        }
+        if(exp == this.exp)
+            return this;
+        else
+            return new ROp(exp, op);
+    }
+
+    @Override
+    protected void buildAutomaton(NFA aut, int inState, int outState) {
+        switch(op) {
+        case '?':
+            exp.buildAutomaton(aut, inState, outState);
+            aut.addEpsilonTransition(inState, outState);
+            break;
+        case '*': {
+            int state = aut.newState();
+            aut.addEpsilonTransition(inState, state);
+            exp.buildAutomaton(aut, state, state);
+            aut.addEpsilonTransition(state, outState);
+        } break;
+        case '+': {
+            int state1 = aut.newState();
+            int state2 = aut.newState();
+            aut.addEpsilonTransition(inState, state1);
+            exp.buildAutomaton(aut, state1, state2);
+            aut.addEpsilonTransition(state2, state1);
+            aut.addEpsilonTransition(state2, outState);
+        } break;
+        default:
+            throw new IllegalStateException("Invalid operation '" + op + "'.");
+        }
+    }
+    
+    @Override
+    protected void toString(StringBuilder b, int prec) {
+        exp.toString(b, 3);
+        b.append(op);
+    }
+    
+    @Override
+    public void toString(StringBuilder b, Namer grammar, int prec) {
+        exp.toString(b, grammar, 3);
+        b.append(op);
+    }
+    
+    @Override
+    protected int getTypeId() {
+        return OP;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if(obj == this)
+            return true;
+        if(obj == null || obj.getClass() != getClass())
+            return false;
+        ROp other = (ROp)obj;
+        return op == other.op && exp.equals(other.exp);
+    }
+    
+    @Override
+    public int hashCode() {
+        return 31*exp.hashCode() + op;
+    }
+
+    @Override
+    public boolean isNullable() {
+        return op != '+' || exp.isNullable();
+    }
+}