/** Visit the specified nonterminal. */ public void visit(NonTerminal nt) { Production p; try { p = analyzer.lookup(nt); } catch (IllegalArgumentException x) { // Too many productions. We assume the worst. isLexical = false; return; } if (null == p) { // No such production. We assume the worst. isLexical = false; } else if (analyzer.isProcessed(p.qName)) { // If the corresponding production has already been processed, // make sure it is lexical. if (!p.getBooleanProperty(Properties.LEXICAL)) { isLexical = false; } } else if (!analyzer.isBeingWorkedOn(p.qName)) { // The production has not been processed and is not yet under // consideration. If is text-only, accept it. If it is void, // check it out. if (p.getBooleanProperty(Properties.TEXT_ONLY)) { // Nothing to do. } else if (AST.isVoid(p.type)) { dispatch(p); } else { isLexical = false; } } }
/** Visit the specified grammar. */ public Object visit(Module m) { // Recognize lexical syntax first. new Tester(runtime, analyzer).dispatch(m); // Initialize the per-grammar state. analyzer.register(this); analyzer.init(m); // Make sure that all lexical and void productions are tested for // whether they consume the input. for (Production p : m.productions) { if (p.getBooleanProperty(Properties.LEXICAL) || AST.isVoid(p.type)) { analyzer.notWorkingOnAny(); analyzer.consumesInput(p.qName); } } // Determine which productions to process. List<Production> todo; if (m.hasProperty(Properties.ROOT)) { todo = new ArrayList<Production>(1); todo.add(analyzer.lookup((NonTerminal) m.getProperty(Properties.ROOT))); } else { todo = m.productions; } // Process the productions. for (Production p : todo) { // Skip processed or non-public productions. if (analyzer.isProcessed(p.qName) || (!p.hasAttribute(Constants.ATT_PUBLIC))) { continue; } // Mark production as processed to avoid recursive processing. analyzer.processed(p.qName); if (p.getBooleanProperty(Properties.LEXICAL)) { // We have reached a lexical production. If it consumes the // input, we mark it as token-level. analyzer.notWorkingOnAny(); if (analyzer.consumesInput(p.qName)) { markToken(p, runtime.test("optionVerbose")); } } else { // Recurse into the production. analyzer.process(p); } } // Done. return null; }
/** Visit the specified grammar. */ public void visit(Module m) { // Initialize the per-grammar state. analyzer.register(this); analyzer.init(m); // Process the productions. for (Production p : m.productions) { // Make sure that the production has not been processed // already and that it returns a string. if (analyzer.isProcessed(p.qName)) { continue; } else if (p.getBooleanProperty(Properties.TEXT_ONLY)) { mark(p); analyzer.processed(p.qName); continue; } else if (!AST.isVoid(p.type)) { analyzer.processed(p.qName); continue; } // Clear the per-production state. isLexical = true; // Process the production. analyzer.process(p); // Tabulate the results. if (isLexical) { // All visited productions are guaranteed to be lexical. for (NonTerminal nt : analyzer.working()) { // This lookup is guaranteed to work, as the production's // fully qualified name was added by visit(Production). Production p2 = analyzer.lookup(nt); mark(p2); analyzer.processed(p2.qName); } } else { // We only know that the current production is not lexical. analyzer.processed(p.qName); } } }