internal override GrammarExpressionTuple GenerateGrammar(GrammarType grammarType, int grammarNumber, ref int index, ref int additionalGrammarNumber, Action <GrammarPostReport> onIterate, params GrammarExpressionWithOriginal[] dependencies) { CheckDependencies(dependencies); Grammar leftExpGrammar = dependencies[0].GrammarExpression.Grammar; Grammar rightExpGrammar = dependencies[1].GrammarExpression.Grammar; NonTerminalSymbol target = new NonTerminalSymbol(new Label(new SingleLabel(Grammar._DefaultNonTerminalSymbol, index++))); Rule rule = new Rule( EnumerateHelper.Sequence( new Chain(EnumerateHelper.Sequence(leftExpGrammar.Target)), new Chain(EnumerateHelper.Sequence(rightExpGrammar.Target)) ), target); IEnumerable <Rule> newRules = leftExpGrammar.Rules.Concat(rightExpGrammar.Rules).Concat(rule); GrammarExpressionTuple grammarExpressionTuple = new GrammarExpressionTuple(this, new Grammar(newRules, target), grammarNumber); if (onIterate != null) { onIterate(new GrammarPostReport(grammarExpressionTuple, dependencies)); } return(grammarExpressionTuple); }
public Rule(NonTerminalSymbol leftSide, Symbol rightSide) { LeftSide = leftSide; RightSide = new List <Symbol> { rightSide }; }
internal override GrammarExpressionTuple GenerateGrammar(GrammarType grammarType, int grammarNumber, ref int index, ref int additionalGrammarNumber, Action <GrammarPostReport> onIterate, params GrammarExpressionWithOriginal[] dependencies) { CheckDependencies(dependencies); NonTerminalSymbol target = new NonTerminalSymbol(new Label(new SingleLabel(Grammar._DefaultNonTerminalSymbol, index++))); GrammarExpressionTuple grammarExpressionTuple = new GrammarExpressionTuple( this, new Grammar( EnumerateHelper.Sequence( new Rule(EnumerateHelper.Sequence(new Chain(Enumerable.Empty <Grammars.Symbol>())), target) ), target ), grammarNumber ); if (onIterate != null) { onIterate(new GrammarPostReport(grammarExpressionTuple, dependencies)); } return(grammarExpressionTuple); }
private Grammar MakeGrammarLeft() { IDictionary <char, TerminalSymbol> charTerminalMap = Alphabet.ToDictionary(c => c, c => new TerminalSymbol(c)); IDictionary <Label, NonTerminalSymbol> stateNonTerminalMap = States.ToDictionary(s => s, s => new NonTerminalSymbol(s)); NonTerminalSymbol target = Grammar.GetNewNonTerminal(stateNonTerminalMap.Values); ISet <Rule> rules = new HashSet <Rule>(); foreach (Transition transition in Transitions) { Chain chain = new Chain( EnumerateHelper.Sequence <Symbol>( stateNonTerminalMap[transition.CurrentState], charTerminalMap[transition.Symbol] ) ); rules.Add(new Rule(chain.AsSequence(), stateNonTerminalMap[transition.NextState])); } rules.Add(new Rule(Chain.Empty.AsSequence(), stateNonTerminalMap[InitialState])); IEnumerable <Chain> chains = FinalStates.Select(fs => new Chain(stateNonTerminalMap[fs].AsSequence())); rules.Add(new Rule(chains, target)); return(new Grammar(rules, target)); }
// generates the method header and body private string GenerateParseMethod(NonTerminalSymbol s) { string Indent2 = IndentTabs(2); string Indent3 = IndentTabs(3); StringBuilder sb = new StringBuilder(); sb.AppendLine(Indent2 + "private void Parse" + s.Name + "(ParseNode parent)" + Helper.AddComment("NonTerminalSymbol: " + s.Name)); sb.AppendLine(Indent2 + "{"); sb.AppendLine(Indent3 + "Token tok;"); sb.AppendLine(Indent3 + "ParseNode n;"); sb.AppendLine(Indent3 + "bool found;"); sb.AppendLine(Indent3 + "ParseNode node = parent.CreateNode(scanner.GetToken(TokenType." + s.Name + "), \"" + s.Name + "\");"); sb.AppendLine(Indent3 + "parent.Nodes.Add(node);"); sb.AppendLine(""); if (s.Rules.Count == 1) { sb.AppendLine(GenerateProductionRuleCode(s.Rules, 0, 3)); } else { throw new Exception("Internal error"); } sb.AppendLine(Indent3 + "parent.Token.UpdateRange(node.Token);"); sb.AppendLine(Indent2 + "}" + Helper.AddComment("NonTerminalSymbol: " + s.Name)); sb.AppendLine(); return(sb.ToString()); }
private static IEnumerable <Chain> RightChainEnumerator(Chain chain, NonTerminalSymbol target) { return(EnumerateHelper.Sequence( new Chain( chain.Concat(EnumerateHelper.Sequence(target)) ), chain )); }
public ParseTreeVisitor(ParseTreeVisitor otherVisitor) { Forest = otherVisitor.Forest; i = otherVisitor.i; j = otherVisitor.j; currentNode = otherVisitor.currentNode; parentNode = otherVisitor.parentNode; currentType = otherVisitor.currentType; }
public ParseTreeVisitor Left() { if (currentNode == null) { return(null); } parentNode = currentNode; j = parentNode.k; currentNode = Forest.P[i, j, (int)parentNode.B].list; currentType = parentNode.B; return(this); }
protected void recurse(int i, int j, NonTerminalSymbol nt, int d, Action <NonTerminalSymbol, ParseTreeNodeMatch, int, bool> act) { ParseTreeNode thisnode = Forest.P[i, j, (int)nt]; ParseTreeNodeMatch m = thisnode.list; act(nt, m, i, m == null); if (m != null) { recurse(i, m.k, m.B, d + 1, act); recurse(i + m.k + 1, j - m.k - 1, m.C, d + 1, act); } }
public ParseTreeVisitor Right() { if (currentNode == null) { return(null); } parentNode = currentNode; i = i + parentNode.k + 1; j = j - parentNode.k - 1; currentNode = Forest.P[i, j, (int)parentNode.C].list; currentType = parentNode.C; return(this); }
public ParseTreeVisitor(ParseForest treeCollection, NonTerminalSymbol whichTree) { if (whichTree == 0) { throw new Exception("Can't pass 0 to ParseTreeVisitor constructor"); } Forest = treeCollection; i = 0; j = Forest.n - 1; currentNode = Forest.P[i, j, (int)whichTree].list; parentNode = null; currentType = whichTree; }
public List <NonTerminalSymbol> SentenceTypes() { var retval = new List <NonTerminalSymbol>(); for (NonTerminalSymbol x = 0; x < NonTerminalSymbol.Length; x++) { if (P[0, n - 1, (int)x].match) { retval.Add(x); } } return(retval); }
// ExtensionMethods ///////////////////////// public static string PrintPyramid(this ParseForest tree, bool force = false) { string retval = Environment.NewLine; ParseTreeNode[, ,] P = tree.P; int n = tree.n, r = tree.r; for (int k = n - 1; k >= 0; k--) { foreach (int i in 1.to(n - k)) { retval += "\t"; //string retval = ""; foreach (int nonterminals in 1.to(r)) { NonTerminalSymbol nt = (NonTerminalSymbol)nonterminals; if (P[i, k, nonterminals].match && nt != NonTerminalSymbol.comma) { retval += (retval == "" ? "" : ",") + (nt == NonTerminalSymbol.colon ? ":" : nt.ToString()); } } retval += (retval.Length > 10 ? "*" : retval); } retval += Environment.NewLine; } foreach (int i in 1.to(n)) { retval += ("\t" + tree.a[i]); } retval += Environment.NewLine; // is valid? if (tree.Count == 0) { retval += Environment.NewLine; } else if (tree.Count == 1) { retval += "IS a member of language as a " + tree.SentenceType.ToString(); } else { retval += "is a member of language but ambiguous, with" + tree.Count + " interpretations"; } return(retval); }
public static List <Rule> ParseRules(List <string> rulesStrings, List <Symbol> possibleSymbols) { var rules = new List <Rule>(); foreach (var ruleString in rulesStrings) { var ruleStringSplit = ruleString.Split(new[] { "->" }, StringSplitOptions.RemoveEmptyEntries); var leftSideSymbol = new NonTerminalSymbol(ruleStringSplit[0]); var rightSideSymbols = SymbolParser.ParseSymbols(ruleStringSplit[1], possibleSymbols); var rule = new Rule(leftSideSymbol, rightSideSymbols); rules.Add(rule); } return(rules); }
public static void PrintPyramid(ParseForest tree) { // if (!force) return; ParseTreeNode[, ,] P = tree.P; int n = tree.n, r = tree.r; for (int k = n - 1; k >= 0; k--) { foreach (int i in 1.to(n - k)) { "\t".LogAnd(); string retval = ""; foreach (int nonterminals in 1.to(r)) { NonTerminalSymbol nt = (NonTerminalSymbol)nonterminals; if (P[i, k, nonterminals].match && nt != NonTerminalSymbol.comma) { retval += (retval == "" ? "" : ",") + (nt == NonTerminalSymbol.colon ? ":" : nt.ToString()); } } (retval.Length > 10 ? "*" : retval).LogAnd(); } "".Log(); } foreach (int i in 1.to(n)) { ("\t" + tree.a[i]).LogAnd(); } "".Log(); // is valid? if (tree.Count == 0) { "".Log(); //"is NOT a member of language".Log(); } else if (tree.Count == 1) { "IS a member of language as a ".Log(tree.SentenceType.ToString()); } else { "is a member of language but ambiguous, with".Log(tree.Count + " interpretations"); } }
// generates the method header and body private string GenerateParseMethod(NonTerminalSymbol s) { StringBuilder sb = new StringBuilder(); sb.AppendLine(" Private Sub Parse" + s.Name + "(ByVal parent As ParseNode)" + Helper.AddComment("'", "NonTerminalSymbol: " + s.Name)); sb.AppendLine(" Dim tok As Token"); sb.AppendLine(" Dim n As ParseNode"); sb.AppendLine(" Dim node As ParseNode = parent.CreateNode(m_scanner.GetToken(TokenType." + s.Name + "), \"" + s.Name + "\")"); sb.AppendLine(" parent.Nodes.Add(node)"); sb.AppendLine(""); foreach (Rule rule in s.Rules) { sb.AppendLine(GenerateProductionRuleCode(s.Rules[0], 3)); } sb.AppendLine(" parent.Token.UpdateRange(node.Token)"); sb.AppendLine(" End Sub" + Helper.AddComment("'", "NonTerminalSymbol: " + s.Name)); sb.AppendLine(); return sb.ToString(); }
// generates the method header and body private string GenerateParseMethod(NonTerminalSymbol s) { StringBuilder sb = new StringBuilder(); sb.AppendLine(" private void Parse" + s.Name + "(ParseNode parent)" + Helper.AddComment("NonTerminalSymbol: " + s.Name)); sb.AppendLine(" {"); sb.AppendLine(" Token tok;"); sb.AppendLine(" ParseNode n;"); sb.AppendLine(" ParseNode node = parent.CreateNode(scanner.GetToken(TokenType." + s.Name + "), \"" + s.Name + "\");"); sb.AppendLine(" parent.Nodes.Add(node);"); sb.AppendLine(""); foreach (Rule rule in s.Rules) { sb.AppendLine(GenerateProductionRuleCode(s.Rules[0], 3)); } sb.AppendLine(" parent.Token.UpdateRange(node.Token);"); sb.AppendLine(" }" + Helper.AddComment("NonTerminalSymbol: " + s.Name)); sb.AppendLine(); return sb.ToString(); }
// generates the method header and body private string GenerateParseMethod(NonTerminalSymbol s) { StringBuilder sb = new StringBuilder(); sb.AppendLine(" Private Sub Parse" + s.Name + "(ByVal parent As ParseNode)" + Helper.AddComment("'", "NonTerminalSymbol: " + s.Name)); sb.AppendLine(" Dim tok As Token"); sb.AppendLine(" Dim n As ParseNode"); sb.AppendLine(" Dim node As ParseNode = parent.CreateNode(m_scanner.GetToken(TokenType." + s.Name + "), \"" + s.Name + "\")"); sb.AppendLine(" parent.Nodes.Add(node)"); sb.AppendLine(""); foreach (Rule rule in s.Rules) { sb.AppendLine(GenerateProductionRuleCode(s.Rules[0], 3)); } sb.AppendLine(" parent.Token.UpdateRange(node.Token)"); sb.AppendLine(" End Sub" + Helper.AddComment("'", "NonTerminalSymbol: " + s.Name)); sb.AppendLine(); return(sb.ToString()); }
/// <summary> /// replaces $ variables with a c# statement /// the routine also implements some checks to see if $variables are matching with production symbols /// errors are added to the Error object. /// </summary> /// <param name="nts">non terminal and its production rule</param> /// <returns>a formated codeblock</returns> private string FormatCodeBlock(NonTerminalSymbol nts) { string codeblock = nts.CodeBlock; if (nts == null) { return(""); } Regex var = new Regex(@"\$(?<var>[a-zA-Z_0-9]+)(\[(?<index>[^]]+)\])?", RegexOptions.Compiled); Symbols symbols = nts.DetermineProductionSymbols(); Match match = var.Match(codeblock); while (match.Success) { Symbol s = symbols.Find(match.Groups["var"].Value); if (s == null) { //TOD: handle error situation //Errors.Add("Variable $" + match.Groups["var"].Value + " cannot be matched."); break; // error situation } string indexer = "0"; if (match.Groups["index"].Value.Length > 0) { indexer = match.Groups["index"].Value; } string replacement = "this.GetValue(tree, TokenType." + s.Name + ", " + indexer + ")"; codeblock = codeblock.Substring(0, match.Captures[0].Index) + replacement + codeblock.Substring(match.Captures[0].Index + match.Captures[0].Length); match = var.Match(codeblock); } codeblock = " " + codeblock.Replace("\n", "\r\n "); return(codeblock); }
// generates the method header and body private string GenerateParseMethod(NonTerminalSymbol s) { StringBuilder sb = new StringBuilder(); sb.AppendLine(" private void Parse" + s.Name + "(ParseNode parent)" + Helper.AddComment("NonTerminalSymbol: " + s.Name)); sb.AppendLine(" {"); sb.AppendLine(" Token tok;"); sb.AppendLine(" ParseNode n;"); sb.AppendLine(" ParseNode node = parent.CreateNode(scanner.GetToken(TokenType." + s.Name + "), \"" + s.Name + "\");"); sb.AppendLine(" parent.getNodes().add(node);"); sb.AppendLine(""); foreach (Rule rule in s.Rules) { sb.AppendLine(GenerateProductionRuleCode(s.Rules[0], 3)); } sb.AppendLine(" parent.Token.UpdateRange(node.Token);"); sb.AppendLine(" }" + Helper.AddComment("NonTerminalSymbol: " + s.Name)); sb.AppendLine(); return(sb.ToString()); }
protected void Recurse(int i, int j, NonTerminalSymbol nt, int d, visitor act) { ParseTreeNode thisnode = P[i, j, (int)nt]; if (!thisnode.match) { return; } ParseTreeNodeMatch m = thisnode.list; if (m != null) { for (; m != null; m = m.next) { act(this, d, false, nt, m.B, m.C, i, j); Recurse(i, m.k, m.B, d + 1, act); Recurse(i + m.k + 1, j - m.k - 1, m.C, d + 1, act); } } else { act(this, d, true, nt, 0, 0, i, j); } }
internal override GrammarExpressionTuple GenerateGrammar(GrammarType grammarType, int grammarNumber, ref int index, ref int additionalGrammarNumber, Action <GrammarPostReport> onIterate, params GrammarExpressionWithOriginal[] dependencies) { CheckDependencies(dependencies); Func <Chain, NonTerminalSymbol, IEnumerable <Chain> > chainEnumerator; Grammar expGrammar = dependencies[0].GrammarExpression.Grammar; switch (grammarType) { case GrammarType.Left: chainEnumerator = LeftChainEnumerator; break; case GrammarType.Right: chainEnumerator = RightChainEnumerator; break; default: throw new InvalidOperationException(UnknownGrammarMessage(grammarType)); } IReadOnlySet <Rule> terminalSymbolsOnlyRules; IReadOnlySet <Rule> otherRules; expGrammar.SplitRules(out terminalSymbolsOnlyRules, out otherRules); ISet <Rule> newRules = new HashSet <Rule>(otherRules); foreach (Rule rule in terminalSymbolsOnlyRules) { ISet <Chain> newChains = new HashSet <Chain>( rule.Chains.SelectMany(chain => chainEnumerator(chain, expGrammar.Target)) ); newRules.Add(new Rule(newChains, rule.Target)); } NonTerminalSymbol symbol = new NonTerminalSymbol(new Label(new SingleLabel(Grammar._DefaultNonTerminalSymbol, index++))); IEnumerable <Chain> chains = EnumerateHelper.Sequence(new Chain(EnumerateHelper.Sequence(expGrammar.Target))); if (!IsPositive) { chains = chains.Concat(new Chain(Enumerable.Empty <Grammars.Symbol>())); } newRules.Add(new Rule(chains, symbol)); GrammarExpressionTuple grammarExpressionTuple = new GrammarExpressionTuple( this, new Grammar(newRules, symbol), grammarNumber ); if (onIterate != null) { onIterate(new GrammarPostReport(grammarExpressionTuple, dependencies)); } return(grammarExpressionTuple); }
public Symbol(NonTerminalSymbol nonTerminalSymbol) { IsTerminal = false; NonTerminalSymbol = nonTerminalSymbol; }
public RulesListItemModel(NonTerminalSymbol rule) { Rule = rule.ToString(); First = Join(rule.First); Follow = Join(rule.Follow); }
public ParseTreeNode(bool m, int k, NonTerminalSymbol B, NonTerminalSymbol C, ParseTreeNodeMatch prev) { match = m; list = new ParseTreeNodeMatch(k, B, C, prev); }
public ParseTreeNodeMatch(int partition, NonTerminalSymbol b, NonTerminalSymbol c, ParseTreeNodeMatch item) { k = partition; B = b; C = c; next = item; }
/// <summary> /// replaces $ variables with a c# statement /// the routine also implements some checks to see if $variables are matching with production symbols /// errors are added to the Error object. /// </summary> /// <param name="nts">non terminal and its production rule</param> /// <returns>a formated codeblock</returns> private string FormatCodeBlock(NonTerminalSymbol nts) { string codeblock = nts.CodeBlock; if (nts == null) return ""; Regex var = new Regex(@"\$(?<var>[a-zA-Z_0-9]+)(\[(?<index>[^]]+)\])?", RegexOptions.Compiled); Symbols symbols = nts.DetermineProductionSymbols(); Match match = var.Match(codeblock); while (match.Success) { Symbol s = symbols.Find(match.Groups["var"].Value); if (s == null) { //TOD: handle error situation //Errors.Add("Variable $" + match.Groups["var"].Value + " cannot be matched."); break; // error situation } string indexer = "0"; if (match.Groups["index"].Value.Length > 0) { indexer = match.Groups["index"].Value; } string replacement = "this.GetValue(tree, TokenType." + s.Name + ", " + indexer + ")"; codeblock = codeblock.Substring(0, match.Captures[0].Index) + replacement + codeblock.Substring(match.Captures[0].Index + match.Captures[0].Length); match = var.Match(codeblock); } codeblock = " " + codeblock.Replace("\n", "\r\n "); return codeblock; }
public StateRule(NonTerminalSymbol leftSide, List <Symbol> rightSide, int dotIndex) : base(leftSide, rightSide) { DotIndex = dotIndex; }
public Rule(NonTerminalSymbol leftSide, List <Symbol> rightSide) { LeftSide = leftSide; RightSide = rightSide; }
/// <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> /// validates whether $ variables are corresponding to valid symbols /// errors are added to the tree Error object. /// </summary> /// <param name="nts">non terminal and its production rule</param> /// <returns>a formated codeblock</returns> private void ValidateCodeBlock(ParseTree tree, NonTerminalSymbol nts, ParseNode node) { if (nts == null) return; string codeblock = nts.CodeBlock; Regex var = new Regex(@"\$(?<var>[a-zA-Z_0-9]+)(\[(?<index>[^]]+)\])?", RegexOptions.Compiled); Symbols symbols = nts.DetermineProductionSymbols(); MatchCollection matches = var.Matches(codeblock); foreach (Match match in matches) { Symbol s = symbols.Find(match.Groups["var"].Value); if (s == null) { tree.Errors.Add(new ParseError("Variable $" + match.Groups["var"].Value + " cannot be matched.", 0x1016, node.Token.File, node.Token.StartPos + match.Groups["var"].Index, node.Token.StartPos + match.Groups["var"].Index, match.Groups["var"].Length)); break; // error situation } } }
public UnitRule(NonTerminalSymbol leftside, string rightside) { headterm = leftside; TerminalSymbol = rightside; }
public UnitRule(NonTerminalSymbol leftside, Func <string, bool> findtype) { headterm = leftside; TypeRule = findtype; }
public RewriteRule(NonTerminalSymbol leftside, NonTerminalSymbol rightSide1, NonTerminalSymbol rightSide2) { headterm = leftside; term2 = rightSide1; term3 = rightSide2; }