protected override object EvalProduction(ParseTree tree, params object[] paramlist) { Grammar g = (Grammar)paramlist[0]; if (Nodes[2].Nodes[0].Token.Type == TokenType.STRING) { TerminalSymbol term = g.Symbols.Find(Nodes[0].Token.Text) as TerminalSymbol; if (term == null) { tree.Errors.Add(new ParseError("Symbol '" + Nodes[0].Token.Text + "' is not declared. ", 0x1040, Nodes[0])); } } else { NonTerminalSymbol nts = g.Symbols.Find(Nodes[0].Token.Text) as NonTerminalSymbol; if (nts == null) { tree.Errors.Add(new ParseError("Symbol '" + Nodes[0].Token.Text + "' is not declared. ", 0x1041, Nodes[0])); } Rule r = (Rule)Nodes[2].Eval(tree, g, nts); if (nts != null) { nts.Rules.Add(r); } if (Nodes[3].Token.Type == TokenType.CODEBLOCK) { string codeblock = Nodes[3].Token.Text; nts.CodeBlock = codeblock; ValidateCodeBlock(tree, nts, Nodes[3]); // beautify the codeblock format codeblock = codeblock.Substring(1, codeblock.Length - 3).Trim(); nts.CodeBlock = codeblock; } } return(g); }
/// <summary> /// EvalStart will first do a semantic check to see if symbols are declared correctly /// then it will also check for attributes and parse the directives /// after that it will complete the transformation to the grammar tree. /// </summary> /// <param name="tree"></param> /// <param name="paramlist"></param> /// <returns></returns> protected override object EvalStart(ParseTree tree, params object[] paramlist) { TerminalSymbol terminal = null; bool StartFound = false; Grammar g = new Grammar(); foreach (ParseNode n in Nodes) { if (n.Token.Type == TokenType.Directive) { EvalDirective(tree, new object[] { g, n }); } if (n.Token.Type == TokenType.ExtProduction) { if (n.Nodes[n.Nodes.Count - 1].Nodes[2].Nodes[0].Token.Type == TokenType.STRING) { try { terminal = new TerminalSymbol(n.Nodes[n.Nodes.Count - 1].Nodes[0].Token.Text, (string)n.Nodes[n.Nodes.Count - 1].Nodes[2].Nodes[0].Token.Text); for (int i = 0; i < n.Nodes.Count - 1; i++) { if (n.Nodes[i].Token.Type == TokenType.Attribute) { EvalAttribute(tree, new object[] { g, terminal, n.Nodes[i] }); } } } catch (Exception ex) { tree.Errors.Add(new ParseError("regular expression for '" + n.Nodes[n.Nodes.Count - 1].Nodes[0].Token.Text + "' results in error: " + ex.Message, 0x1020, n.Nodes[0])); continue; } if (terminal.Name == "Start") { tree.Errors.Add(new ParseError("'Start' symbol cannot be a regular expression.", 0x1021, n.Nodes[0])); } if (g.Symbols.Find(terminal.Name) == null) { g.Symbols.Add(terminal); } else { tree.Errors.Add(new ParseError("Terminal already declared: " + terminal.Name, 0x1022, n.Nodes[0])); } } else { NonTerminalSymbol nts = new NonTerminalSymbol(n.Nodes[n.Nodes.Count - 1].Nodes[0].Token.Text); if (g.Symbols.Find(nts.Name) == null) { g.Symbols.Add(nts); } else { tree.Errors.Add(new ParseError("Non terminal already declared: " + nts.Name, 0x1023, n.Nodes[0])); } for (int i = 0; i < n.Nodes.Count - 1; i++) { if (n.Nodes[i].Token.Type == TokenType.Attribute) { EvalAttribute(tree, new object[] { g, nts, n.Nodes[i] }); } } if (nts.Name == "Start") { StartFound = true; } } } } if (!StartFound) { tree.Errors.Add(new ParseError("The grammar requires 'Start' to be a production rule.", 0x0024)); return(g); } foreach (ParseNode n in Nodes) { if (n.Token.Type == TokenType.ExtProduction) { n.Eval(tree, g); } } return(g); }
/// <summary> /// EvalStart will first do a semantic check to see if symbols are declared correctly /// then it will also check for attributes and parse the directives /// after that it will complete the transformation to the grammar tree. /// </summary> /// <param name="tree"></param> /// <param name="paramlist"></param> /// <returns></returns> protected override object EvalStart(ParseTree tree, params object[] paramlist) { TerminalSymbol terminal = null; bool StartFound = false; Grammar g = new Grammar(); foreach (ParseNode n in Nodes) { if (n.Token.Type == TokenType.Directive) { EvalDirective(tree, new object[] { g, n }); } if (n.Token.Type == TokenType.ExtProduction) { if (n.Nodes[n.Nodes.Count - 1].Nodes[2].Nodes[0].Token.Type == TokenType.STRING) { try { terminal = new TerminalSymbol(n.Nodes[n.Nodes.Count - 1].Nodes[0].Token.Text, (string)n.Nodes[n.Nodes.Count - 1].Nodes[2].Nodes[0].Token.Text); for (int i = 0; i < n.Nodes.Count - 1; i++) { if (n.Nodes[i].Token.Type == TokenType.Attribute) EvalAttribute(tree, new object[] { g, terminal, n.Nodes[i] }); } } catch (Exception ex) { tree.Errors.Add(new ParseError("regular expression for '" + n.Nodes[n.Nodes.Count - 1].Nodes[0].Token.Text + "' results in error: " + ex.Message, 0x1020, n.Nodes[0])); continue; } if (terminal.Name == "Start") tree.Errors.Add(new ParseError("'Start' symbol cannot be a regular expression.", 0x1021, n.Nodes[0])); if (g.Symbols.Find(terminal.Name) == null) g.Symbols.Add(terminal); else tree.Errors.Add(new ParseError("Terminal already declared: " + terminal.Name, 0x1022, n.Nodes[0])); } else { NonTerminalSymbol nts = new NonTerminalSymbol(n.Nodes[n.Nodes.Count - 1].Nodes[0].Token.Text); if (g.Symbols.Find(nts.Name) == null) g.Symbols.Add(nts); else tree.Errors.Add(new ParseError("Non terminal already declared: " + nts.Name, 0x1023, n.Nodes[0])); for (int i = 0; i < n.Nodes.Count - 1; i++) { if (n.Nodes[i].Token.Type == TokenType.Attribute) EvalAttribute(tree, new object[] { g, nts, n.Nodes[i] }); } if (nts.Name == "Start") StartFound = true; } } } if (!StartFound) { tree.Errors.Add(new ParseError("The grammar requires 'Start' to be a production rule.", 0x0024)); return g; } foreach (ParseNode n in Nodes) { if (n.Token.Type == TokenType.ExtProduction) { n.Eval(tree, g); } } return g; }