void Factor(out Graph g) { string name; int kind; Position pos; bool weak = false; g = null; switch (la.kind) { case 1: case 3: case 5: case 29: { if (la.kind == 29) { Get(); weak = true; } Sym(out name, out kind); Symbol sym = tab.FindSym(name); if (sym == null && kind == str) { sym = tab.literals[name] as Symbol; } bool undef = sym == null; if (undef) { if (kind == id) { sym = tab.NewSym(Node.nt, name, 0); // forward nt } else if (genScanner) { sym = tab.NewSym(Node.t, name, t.line); dfa.MatchLiteral(sym.name, sym); } else // undefined string in production { SemErr("undefined string in production"); sym = tab.eofSy; // dummy } } int typ = sym.typ; if (typ != Node.t && typ != Node.nt) { SemErr("this symbol kind is not allowed in a production"); } if (weak) { if (typ == Node.t) { typ = Node.wt; } else { SemErr("only terminals may be weak"); } } Node p = tab.NewNode(typ, sym, t.line); g = new Graph(p); if (la.kind == 24 || la.kind == 26) { Attribs(p); if (kind != id) { SemErr("a literal must not have attributes"); } } if (undef) { sym.attrPos = p.pos; // dummy } else if ((p.pos == null) != (sym.attrPos == null)) { SemErr("attribute mismatch between declaration and use of this symbol"); } break; } case 30: { Get(); Expression(out g); Expect(31); break; } case 32: { Get(); Expression(out g); Expect(33); tab.MakeOption(g); break; } case 34: { Get(); Expression(out g); Expect(35); tab.MakeIteration(g); break; } case 39: { SemText(out pos); Node p = tab.NewNode(Node.sem, null, 0); p.pos = pos; g = new Graph(p); break; } case 23: { Get(); Node p = tab.NewNode(Node.any, null, 0); // p.set is set in tab.SetupAnys g = new Graph(p); break; } case 36: { Get(); Node p = tab.NewNode(Node.sync, null, 0); g = new Graph(p); break; } default: SynErr(49); break; } if (g == null) // invalid start of Factor { g = new Graph(tab.NewNode(Node.eps, null, 0)); } }