]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 package org.simantics.scl.compiler.parser.regexp;
2
3 import org.simantics.scl.compiler.parser.regexp.automata.NFA;
4
5 public class ROp extends Regexp {
6     public final Regexp exp;
7     public final char op;
8     
9     ROp(Regexp exp, char op) {
10         this.exp = exp;
11         this.op = op;
12     }
13     
14     @Override
15     public Regexp simplify() {
16         Regexp exp = this.exp.simplify();
17         if(exp instanceof ROp) {
18             ROp other = (ROp)exp;
19             if(other.op == op || other.op == '*')
20                 return other;
21             else
22                 return new ROp(other.exp, '*');
23         }
24         else if(exp.isNullable()) {
25             if(op == '?')
26                 return exp;
27             if(op == '+')
28                 return new ROp(exp, '*');
29         }
30         if(exp == this.exp)
31             return this;
32         else
33             return new ROp(exp, op);
34     }
35
36     @Override
37     protected void buildAutomaton(NFA aut, int inState, int outState) {
38         switch(op) {
39         case '?':
40             exp.buildAutomaton(aut, inState, outState);
41             aut.addEpsilonTransition(inState, outState);
42             break;
43         case '*': {
44             int state = aut.newState();
45             aut.addEpsilonTransition(inState, state);
46             exp.buildAutomaton(aut, state, state);
47             aut.addEpsilonTransition(state, outState);
48         } break;
49         case '+': {
50             int state1 = aut.newState();
51             int state2 = aut.newState();
52             aut.addEpsilonTransition(inState, state1);
53             exp.buildAutomaton(aut, state1, state2);
54             aut.addEpsilonTransition(state2, state1);
55             aut.addEpsilonTransition(state2, outState);
56         } break;
57         default:
58             throw new IllegalStateException("Invalid operation '" + op + "'.");
59         }
60     }
61     
62     @Override
63     protected void toString(StringBuilder b, int prec) {
64         exp.toString(b, 3);
65         b.append(op);
66     }
67     
68     @Override
69     public void toString(StringBuilder b, Namer grammar, int prec) {
70         exp.toString(b, grammar, 3);
71         b.append(op);
72     }
73     
74     @Override
75     protected int getTypeId() {
76         return OP;
77     }
78     
79     @Override
80     public boolean equals(Object obj) {
81         if(obj == this)
82             return true;
83         if(obj == null || obj.getClass() != getClass())
84             return false;
85         ROp other = (ROp)obj;
86         return op == other.op && exp.equals(other.exp);
87     }
88     
89     @Override
90     public int hashCode() {
91         return 31*exp.hashCode() + op;
92     }
93
94     @Override
95     public boolean isNullable() {
96         return op != '+' || exp.isNullable();
97     }
98 }