/** * Expands the specified macro by replacing each macro usage * with the stored definition. * * @param name the name of the macro to expand (for detecting cycles) * @param definition the definition of the macro to expand * * @return the expanded definition of the macro. * * @throws MacroException when an error (such as a cyclic definition) * occurs during expansion */ private RegExp expandMacro(String name, RegExp definition) { #if DEBUG_TRACE log.WriteLine("expandMacro(String name = \"{0}\", RegExp definition = {1})", name, definition); #endif // DEBUG_TRACE // Out.print("checking macro "+name); // Out.print("definition is "+definition); switch (definition.type) { case sym.BAR: case sym.CONCAT: RegExp2 binary = (RegExp2)definition; binary.r1 = expandMacro(name, binary.r1); binary.r2 = expandMacro(name, binary.r2); return(definition); case sym.STAR: case sym.PLUS: case sym.QUESTION: case sym.BANG: case sym.TILDE: RegExp1 unary = (RegExp1)definition; unary.content = expandMacro(name, (RegExp)unary.content); return(definition); case sym.MACROUSE: String usename = (String)((RegExp1)definition).content; if (name.Equals(usename)) { throw new MacroException(ErrorMessages.get(ErrorMessages.MACRO_CYCLE, name)); } RegExp usedef = getDefinition(usename); if (usedef == null) { throw new MacroException(ErrorMessages.get(ErrorMessages.MACRO_DEF_MISSING, usename, name)); } markUsed(usename); return(expandMacro(name, usedef)); case sym.STRING: case sym.STRING_I: case sym.CHAR: case sym.CHAR_I: case sym.CCLASS: case sym.CCLASSNOT: return(definition); default: throw new MacroException("unknown expression type " + definition.type + " in macro expansion"); //$NON-NLS-1$ //$NON-NLS-2$ } }
/** * Constructs a two state NFA for char class regexps, * such that the NFA has * * exactly one start state, * exactly one end state, * no transitions leading out of the end state * no transitions leading into the start state * * Assumes that regExp.isCharClass(macros) == true * * @param regExp the regular expression to construct the * NFA for * * @return a pair of integers denoting the index of start * and end state of the NFA. */ private void insertNFA(RegExp regExp, int start, int end) { switch (regExp.type) { case sym.BAR: RegExp2 r = (RegExp2)regExp; insertNFA(r.r1, start, end); insertNFA(r.r2, start, end); return; case sym.CCLASS: insertClassNFA((ArrayList)((RegExp1)regExp).content, start, end); return; case sym.CCLASSNOT: insertNotClassNFA((ArrayList)((RegExp1)regExp).content, start, end); return; case sym.CHAR: insertLetterNFA( false, (char)((RegExp1)regExp).content, start, end); return; case sym.CHAR_I: insertLetterNFA( true, (char)((RegExp1)regExp).content, start, end); return; case sym.MACROUSE: insertNFA(macros.getDefinition((String)((RegExp1)regExp).content), start, end); return; } throw new Exception("Unknown expression type " + regExp.type + " in NFA construction"); }