public static Surf.Set First(Bamboo.Parsing.Grammars.Grammar grammar) { Surf.Set FIRST = new Surf.Set(); foreach (string symbol in grammar.Terminals) { FIRST.Add(new Surf.Tuple(new object[] { symbol, new Surf.Set(new object[] { symbol }) })); } foreach (string symbol in grammar.Nonterminals) { FIRST.Add(new Surf.Tuple(new object[] { symbol, new Surf.Set() })); } List <Bamboo.Parsing.Grammars.Production> remaining = Copy(grammar.Productions); while (remaining.Count > 0) { for (int i = 0; i < remaining.Count; i++) { Bamboo.Parsing.Grammars.Production production = remaining[i]; if (CanResolve(production.Expression, remaining)) { First(production.Nonterminal, production.Expression, FIRST); remaining.Remove(production); break; } } } return(FIRST); }
private static void AssertDisjoint(Surf.Set PREDICT, Surf.Set nonterminals) { Dictionary <string, List <Surf.Set> > lookup = new Dictionary <string, List <Surf.Set> >(); foreach (string nonterminal in nonterminals) { lookup.Add(nonterminal, new List <Surf.Set>()); } foreach (Surf.Tuple tuple in PREDICT) { Bamboo.Parsing.Grammars.Production production = (Bamboo.Parsing.Grammars.Production)tuple[1]; Surf.Set predict = (Surf.Set)tuple[2]; lookup[production.Nonterminal].Add(predict); } foreach (List <Surf.Set> sets in lookup.Values) { for (int i = 0; i < sets.Count; i++) { for (int j = (i + 1); j < sets.Count; j++) { if (sets[i].Intersection(sets[j]).Count > 0) { System.Console.WriteLine("PREDICT"); foreach (Surf.Tuple tuple in PREDICT) { int n = (int)tuple[0]; Bamboo.Parsing.Grammars.Production production = (Bamboo.Parsing.Grammars.Production)tuple[1]; Surf.Set predict = (Surf.Set)tuple[2]; System.Console.Write(n + " "+ production.Nonterminal + " "); Surf.Printer.Print(predict, System.Console.Out); System.Console.WriteLine(); } System.Console.WriteLine(); throw new System.Exception("Ambiguous grammar. Predict-predict conflict."); } } } } }
public static void GenerateHeader(string name, string multinamespace, Bamboo.Parsing.Grammars.Grammar grammar, Surf.Set PREDICT, System.IO.TextWriter writer) { writer.WriteLine("//"); writer.WriteLine("// " + name + "Parser.h"); writer.WriteLine("//"); writer.WriteLine("// AUTOGENERATED " + System.DateTime.Now + ""); writer.WriteLine("//"); writer.WriteLine(""); writer.WriteLine("#ifndef " + name.ToUpper() + "PARSER_H"); writer.WriteLine("#define " + name.ToUpper() + "PARSER_H"); writer.WriteLine(""); writer.WriteLine("#include <istream>"); writer.WriteLine("#include <vector>"); writer.WriteLine("#include \"" + name + "Token.h\""); writer.WriteLine(""); string[] namespaces = multinamespace.Split(new string[] { "::" }, StringSplitOptions.None); foreach (string nspace in namespaces) { writer.WriteLine("namespace " + nspace + ""); writer.WriteLine("{"); } writer.WriteLine(" class "+ name + "Parser"); writer.WriteLine(" {"); writer.WriteLine(" private:"); writer.WriteLine(" int _currentState;"); writer.WriteLine(" std::vector<int> _states;"); writer.WriteLine(" public:"); writer.WriteLine(" Parser() : _currentState(0) { }"); writer.WriteLine(" virtual ~"+ name + "Parser() { }"); writer.WriteLine(""); writer.WriteLine(" void next("+ name + "Token&);"); writer.WriteLine(""); Dictionary <string, string> constructors = new Dictionary <string, string>(); foreach (string nonterminal in grammar.Nonterminals) { foreach (Surf.Tuple tuple in PREDICT) { int n = (int)tuple[0] + 1; Bamboo.Parsing.Grammars.Production production = (Bamboo.Parsing.Grammars.Production)tuple[1]; Surf.Set predict = (Surf.Set)tuple[2]; if (production.Nonterminal.Equals(nonterminal)) { foreach (string symbol in predict) { List <Bamboo.Parsing.Grammars.Expression> expressions = ToList(production.Expression); if (expressions.Count == 1 && ((Bamboo.Parsing.Grammars.Symbol)expressions[0]).Token == "EPSILON") { } else { string constructor2 = " virtual void beginParse"+ nonterminal; foreach (Bamboo.Parsing.Grammars.Symbol expression in expressions) { constructor2 += "_" + expression.Token; } constructor2 += "() = 0;"; string constructor = " virtual void endParse"+ nonterminal; foreach (Bamboo.Parsing.Grammars.Symbol expression in expressions) { constructor += "_" + expression.Token; } constructor += "() = 0;"; if (!constructors.ContainsKey(constructor)) { writer.WriteLine(constructor2); writer.WriteLine(constructor); constructors.Add(constructor, constructor); } } } } } } writer.WriteLine(""); foreach (string terminal in grammar.Terminals) { if (terminal != "EPSILON") { writer.WriteLine(" virtual void parse"+ terminal + "(" + name + "Token&) = 0;"); } } writer.WriteLine(" };"); foreach (string nspace in namespaces) { writer.WriteLine("}"); } writer.WriteLine("#endif"); }
public static void Generate(string name, string nspace, Bamboo.Parsing.Grammars.Grammar grammar, Surf.Set FIRST, Surf.Set FOLLOW, Surf.Set PREDICT, System.IO.TextWriter writer) { writer.WriteLine("//"); writer.WriteLine("// AUTOGENERATED " + System.DateTime.Now + ""); writer.WriteLine("//"); writer.WriteLine("using System;"); writer.WriteLine(""); writer.WriteLine("namespace " + nspace + ""); writer.WriteLine("{"); writer.WriteLine(" public class "+ name + "Parser"); writer.WriteLine(" {"); writer.WriteLine(" private "+ name + "Tokenizer _tokenizer = new " + name + "Tokenizer();"); //TODO use a state variable. writer.WriteLine(" private "+ name + "TextReader _reader;"); writer.WriteLine(" private "+ name + "Token _token;"); writer.WriteLine(""); writer.WriteLine(" public "+ name + "Parser(" + name + "TextReader reader)"); writer.WriteLine(" {"); writer.WriteLine(" this._reader = reader;"); writer.WriteLine(" this._token = this._tokenizer.Tokenize(this._reader);"); writer.WriteLine(" }"); writer.WriteLine(""); writer.WriteLine(" public "+ name + "Node Parse()"); writer.WriteLine(" {"); writer.WriteLine(" return Parse"+ grammar.Productions[0].Nonterminal + "();"); writer.WriteLine(" }"); writer.WriteLine(""); foreach (string nonterminal in grammar.Nonterminals) { writer.WriteLine(" private "+ name + "Node Parse" + nonterminal + "()"); writer.WriteLine(" {"); writer.WriteLine(" "+ name + "Node node = new " + name + "Node(" + name + "NodeType." + nonterminal + ");"); writer.WriteLine(""); writer.WriteLine(" switch (this._token.Type)"); writer.WriteLine(" {"); bool hasDefault = false; foreach (Surf.Tuple tuple in PREDICT) { int n = (int)tuple[0]; Bamboo.Parsing.Grammars.Production production = (Bamboo.Parsing.Grammars.Production)tuple[1]; Surf.Set predict = (Surf.Set)tuple[2]; if (production.Nonterminal.Equals(nonterminal)) { List <Bamboo.Parsing.Grammars.Expression> expressions = ToList(production.Expression); //predict.Count == 0 && if (expressions.Count == 1 && ((Bamboo.Parsing.Grammars.Symbol)expressions[0]).Token.Equals("EPSILON")) { hasDefault = true; writer.WriteLine(" default:"); writer.WriteLine(" {"); writer.WriteLine(" return node;"); writer.WriteLine(" }"); } else { if (predict.Count == 1 && predict[0].Equals("EOF")) { writer.WriteLine(" case "+ name + "TokenType._EOF_:"); writer.WriteLine(" {"); writer.WriteLine(" return node;"); writer.WriteLine(" }"); } else { foreach (string symbol in predict) { writer.WriteLine(" case "+ name + "TokenType." + symbol + ":"); } writer.WriteLine(" {"); if (!((Bamboo.Parsing.Grammars.Symbol)expressions[0]).Token.Equals("EPSILON")) { for (int i = 0; i < expressions.Count; i++) { writer.WriteLine(" node.Nodes.Add(Parse"+ ((Bamboo.Parsing.Grammars.Symbol)expressions[i]).Token + "());"); } } writer.WriteLine(" return node;"); writer.WriteLine(" }"); } } } } if (!hasDefault) { writer.WriteLine(" default:"); writer.WriteLine(" {"); writer.WriteLine(" throw new System.Exception(\"Syntax error.\");"); writer.WriteLine(" }"); } writer.WriteLine(" }"); writer.WriteLine(" }"); writer.WriteLine(""); } foreach (string terminal in grammar.Terminals) { if (!terminal.Equals("EPSILON")) { writer.WriteLine(" private "+ name + "Node Parse" + terminal + "()"); writer.WriteLine(" {"); writer.WriteLine(" "+ name + "Node node = new " + name + "Node(" + name + "NodeType." + terminal + ", this._token.Value);"); writer.WriteLine(" this._token = this._tokenizer.Tokenize(this._reader);"); writer.WriteLine(" return node;"); writer.WriteLine(" }"); writer.WriteLine(""); } } writer.WriteLine(" }"); writer.WriteLine("}"); }
public static void GenerateClass(string name, string multinamespace, Bamboo.Parsing.Grammars.Grammar grammar, Surf.Set FIRST, Surf.Set FOLLOW, Surf.Set PREDICT, System.IO.TextWriter writer) { writer.WriteLine("//"); writer.WriteLine("// " + name + "Parser.cpp"); writer.WriteLine("//"); writer.WriteLine("// AUTOGENERATED " + System.DateTime.Now + ""); writer.WriteLine("//"); writer.WriteLine(""); writer.WriteLine("#include <istream>"); writer.WriteLine("#include <sstream>"); writer.WriteLine("#include <string>"); writer.WriteLine("#include <vector>"); writer.WriteLine("#include \"" + name + "Parser.h\""); writer.WriteLine("#include \"" + name + "Token.h\""); writer.WriteLine("#include \"" + name + "TokenType.h\""); writer.WriteLine(""); string[] namespaces = multinamespace.Split(new string[] { "::" }, StringSplitOptions.None); foreach (string nspace in namespaces) { writer.WriteLine("namespace " + nspace + ""); writer.WriteLine("{"); } writer.WriteLine(" void Parser::next("+ name + "Token& token)"); writer.WriteLine(" {"); writer.WriteLine(" start:"); writer.WriteLine(" switch(_currentState)"); writer.WriteLine(" {"); Dictionary <string, int> states = new Dictionary <string, int>(); int state = 0; foreach (string nonterminal in grammar.Nonterminals) { states.Add(nonterminal, state++); } foreach (string terminal in grammar.Terminals) { if (terminal != "EPSILON") { states.Add(terminal, state++); } } foreach (string nonterminal in grammar.Nonterminals) { bool hasDefault = false; writer.WriteLine(" case "+ states[nonterminal] + ": // parse" + nonterminal); writer.WriteLine(" {"); writer.WriteLine(" switch(token.type())"); writer.WriteLine(" {"); int state2 = state; foreach (Surf.Tuple tuple in PREDICT) { int n = (int)tuple[0] + 1; Bamboo.Parsing.Grammars.Production production = (Bamboo.Parsing.Grammars.Production)tuple[1]; Surf.Set predict = (Surf.Set)tuple[2]; if (production.Nonterminal.Equals(nonterminal)) { foreach (string symbol in predict) { List <Bamboo.Parsing.Grammars.Expression> expressions = ToList(production.Expression); if (expressions.Count == 1 && ((Bamboo.Parsing.Grammars.Symbol)expressions[0]).Token == "EPSILON") { hasDefault = true; } else { writer.WriteLine(" case TokenType::"+ symbol + ":"); writer.WriteLine(" {"); writer.Write(" beginParse"+ nonterminal); foreach (Bamboo.Parsing.Grammars.Symbol expression in expressions) { writer.Write("_" + expression.Token); } writer.WriteLine("();"); writer.Write(" _states.push_back("+ state2++ + "); // endParse" + nonterminal); foreach (Bamboo.Parsing.Grammars.Symbol expression in expressions) { writer.Write("_" + expression.Token); } writer.WriteLine("();"); for (int i = (expressions.Count - 1); i >= 1; i--) { Bamboo.Parsing.Grammars.Symbol expression = (Bamboo.Parsing.Grammars.Symbol)expressions[i]; writer.WriteLine(" _states.push_back("+ states[expression.Token] + "); // parse" + expression.Token); } Bamboo.Parsing.Grammars.Symbol expression2 = (Bamboo.Parsing.Grammars.Symbol)expressions[0]; writer.WriteLine(" _currentState = "+ states[expression2.Token] + "; // parse" + expression2.Token); writer.WriteLine(" goto start;"); writer.WriteLine(" break;"); writer.WriteLine(" }"); } } } } if (states[nonterminal] == 0) { writer.WriteLine(" case "+ name + "TokenType::_EOF_:"); writer.WriteLine(" {"); writer.WriteLine(" if (_states.size() > 0)"); writer.WriteLine(" {"); writer.WriteLine(" _currentState = _states.back();"); writer.WriteLine(" _states.pop_back();"); writer.WriteLine(" goto start;"); writer.WriteLine(" }"); writer.WriteLine(" break;"); writer.WriteLine(" }"); } if (hasDefault) { writer.WriteLine(" default:"); writer.WriteLine(" {"); writer.WriteLine(" // EPSILON"); writer.WriteLine(" _currentState = _states.back();"); writer.WriteLine(" _states.pop_back();"); writer.WriteLine(" goto start;"); writer.WriteLine(" }"); } else { writer.WriteLine(" default:"); writer.WriteLine(" {"); writer.WriteLine(" std::stringstream stream;"); writer.WriteLine(" stream << __FILE__ << \" \" << __LINE__ << \" \" << \"Syntax error.\";"); writer.WriteLine(" throw stream.str();"); writer.WriteLine(" }"); } writer.WriteLine(" }"); writer.WriteLine(" break;"); writer.WriteLine(" }"); state2 = state; foreach (Surf.Tuple tuple in PREDICT) { int n = (int)tuple[0] + 1; Bamboo.Parsing.Grammars.Production production = (Bamboo.Parsing.Grammars.Production)tuple[1]; Surf.Set predict = (Surf.Set)tuple[2]; if (production.Nonterminal.Equals(nonterminal)) { foreach (string symbol in predict) { List <Bamboo.Parsing.Grammars.Expression> expressions = ToList(production.Expression); if (expressions.Count == 1 && ((Bamboo.Parsing.Grammars.Symbol)expressions[0]).Token == "EPSILON") { } else { writer.Write(" case "+ state2++ + ": // endParse" + nonterminal); foreach (Bamboo.Parsing.Grammars.Symbol expression in expressions) { writer.Write("_" + expression.Token); } writer.WriteLine("();"); writer.WriteLine(" {"); writer.Write(" "+ "endParse" + nonterminal); foreach (Bamboo.Parsing.Grammars.Symbol expression in expressions) { writer.Write("_" + expression.Token); } writer.WriteLine("();"); writer.WriteLine(" if (_states.size() == 0)"); writer.WriteLine(" {"); writer.WriteLine(" _currentState = 0;"); writer.WriteLine(" }"); writer.WriteLine(" else"); writer.WriteLine(" {"); writer.WriteLine(" _currentState = _states.back();"); writer.WriteLine(" _states.pop_back();"); writer.WriteLine(" }"); writer.WriteLine(" goto start;"); writer.WriteLine(" break;"); writer.WriteLine(" }"); } } } } state = state2; } foreach (string terminal in grammar.Terminals) { if (terminal != "EPSILON") { writer.WriteLine(" case "+ states[terminal] + ": // " + terminal); writer.WriteLine(" {"); writer.WriteLine(" parse"+ terminal + "(token);"); writer.WriteLine(" if (_states.size() == 0)"); writer.WriteLine(" {"); writer.WriteLine(" _currentState = 0;"); writer.WriteLine(" }"); writer.WriteLine(" else"); writer.WriteLine(" {"); writer.WriteLine(" _currentState = _states.back();"); writer.WriteLine(" _states.pop_back();"); writer.WriteLine(" }"); writer.WriteLine(" break;"); writer.WriteLine(" }"); } } writer.WriteLine(" default:"); writer.WriteLine(" {"); writer.WriteLine(" std::stringstream stream;"); writer.WriteLine(" stream << __FILE__ << \" \" << __LINE__ << \" \" << \"Invalid parser state.\";"); writer.WriteLine(" throw stream.str();"); writer.WriteLine(" }"); writer.WriteLine(" }"); writer.WriteLine(" }"); writer.WriteLine(""); foreach (string nspace in namespaces) { writer.WriteLine("}"); } }