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(); } }