public Parser ToLL1Parser(IEnumerable <Token> tokenizer = null) { var parseTable = ToLL1ParseTable(); var syms = new List <string>(); FillSymbols(syms); var nodeFlags = new int[syms.Count]; for (var i = 0; i < nodeFlags.Length; ++i) { var o = AttributeSets.GetAttribute(syms[i], "hidden", false); if (o is bool && (bool)o) { nodeFlags[i] |= 2; } o = AttributeSets.GetAttribute(syms[i], "collapsed", false); if (o is bool && (bool)o) { nodeFlags[i] |= 1; } } var attrSets = new KeyValuePair <string, object> [syms.Count][]; for (var i = 0; i < attrSets.Length; i++) { AttributeSet attrs; if (AttributeSets.TryGetValue(syms[i], out attrs)) { attrSets[i] = new KeyValuePair <string, object> [attrs.Count]; var j = 0; foreach (var attr in attrs) { attrSets[i][j] = new KeyValuePair <string, object>(attr.Key, attr.Value); ++j; } } else { attrSets[i] = null; // new KeyValuePair<string, object>[0]; } } var initCfg = new int[] { GetIdOfSymbol(StartSymbol), FillNonTerminals().Count }; return(new LL1TableParser(parseTable.ToLL1Array(syms), initCfg, syms.ToArray(), nodeFlags, attrSets, tokenizer)); }
public CfgLL1ParseTable ToLLkParseTable() { // Here we populate the outer dictionary with one non-terminal for each key // we populate each inner dictionary with the result terminals and associated // rules of the predict tables except in the case where the predict table // contains null. In that case, we use the follows to get the terminals and // the rule associated with the null predict in order to compute the inner // dictionary. The conflict resolution tables are created as needed. Basically // they are nested parse tables for additional lookahead resolution. // The parser can use these to further resolve conflicts. var predict = FillPredict(); var follows = FillFollows(); var result = new CfgLL1ParseTable(); foreach (var nt in _EnumNonTerminals()) { var d = new Dictionary <string, CfgLL1ParseTableEntry>(); foreach (var f in predict[nt]) { if (null != f.Symbol) { CfgLL1ParseTableEntry or; if (d.TryGetValue(f.Symbol, out or)) { if (null != or.ConflictTable) { } else if (null != or.Rule) { var pt = new CfgLL1ParseTable(); var dd = new Dictionary <string, CfgRule>(); throw new CfgException( string.Format( "FIRST FIRST conflict between {0} and {1} on {2}", or.Rule, f.Rule, f.Symbol)); } } else { or.ConflictTable = null; or.Rule = f.Rule; d.Add(f.Symbol, or); } } else { var ff = follows[nt]; foreach (var fe in ff) { CfgLL1ParseTableEntry or; if (d.TryGetValue(fe, out or)) { // we can override conflict handling with the followsConflict // attribute. If specified (first/last/error - error is default) it will choose // the first or last rule respectively. var fc = AttributeSets.GetAttribute(nt, "followsConflict", "error") as string; if ("error" == fc) { throw new CfgException( string.Format( "FIRST FOLLOWS conflict between {0} and {1} on {2}", or.Rule, f.Rule, fe)); } else if ("last" == fc) { d[fe] = new CfgLL1ParseTableEntry(f.Rule); } } else { d.Add(fe, new CfgLL1ParseTableEntry(f.Rule)); } } } } result.Add(nt, d); } return(result); }
public CfgLL1ParseTable ToLL1ParseTable() { // Here we populate the outer dictionary with one non-terminal for each key // we populate each inner dictionary with the result terminals and associated // rules of the predict tables except in the case where the predict table // contains null. In that case, we use the follows to get the terminals and // the rule associated with the null predict in order to compute the inner // dictionary. The conflict resolution tables are always empty for LL(1) var predict = FillPredict(); var follows = FillFollows(); var exmsgs = new List <CfgMessage>(); var result = new CfgLL1ParseTable(); foreach (var nt in _EnumNonTerminals()) { var d = new Dictionary <string, CfgLL1ParseTableEntry>(); foreach (var f in predict[nt]) { if (null != f.Symbol) { CfgLL1ParseTableEntry re; re.ConflictTable = null; re.Rule = f.Rule; CfgLL1ParseTableEntry or; if (d.TryGetValue(f.Symbol, out or)) { exmsgs.Add(new CfgMessage(CfgErrorLevel.Error, 1, string.Format( "FIRST FIRST conflict between {0} and {1} on {2}", or.Rule, f.Rule, f.Symbol))); } else { d.Add(f.Symbol, re); } } else { var ff = follows[nt]; foreach (var fe in ff) { CfgLL1ParseTableEntry or; if (d.TryGetValue(fe, out or)) { // we can override conflict handling with the followsConflict // attribute. If specified (first/last/error - error is default) it will choose // the first or last rule respectively. var fc = AttributeSets.GetAttribute(nt, "followsConflict", "error") as string; if ("error" == fc) { exmsgs.Add(new CfgMessage(CfgErrorLevel.Error, 2, string.Format( "FIRST FOLLOWS conflict between {0} and {1} on {2}", or.Rule, f.Rule, fe))); } else if ("last" == fc) { d[fe] = new CfgLL1ParseTableEntry(f.Rule); } } else { d.Add(fe, new CfgLL1ParseTableEntry(f.Rule)); } } } } result.Add(nt, d); } CfgException.ThrowIfErrors(exmsgs); return(result); }