/// <summary> /// Generates code to match Must and May constructs /// </summary> /// <param name="tabs"></param> /// <param name="exp"></param> /// <param name="must"></param> /// <param name="resstr"></param> /// <returns></returns> private string GenerateAlternativesMatch(int tabs, GrammarInfo grammar, MethodCallExpression exp, bool must, string resstr) { string exstr = String.Format("a{0}", ++excount); CodeStringBuilder code = new CodeStringBuilder(); code.AppendLineFormat(tabs, "if ({0})", resstr); // code.AppendLineFormat(tabs, "{{ // alternatives {0} {1}", exstr, must ? "must" : "may"); code.AppendLineFormat(tabs + 1, "bool {0} = false;", exstr); var args = ((NewArrayExpression)exp.Arguments[0]).Expressions; foreach (var a in args) { code.AppendLineFormat(tabs + 1, "if (!{0})", exstr); code.Append(GenerateProductionMatch(tabs + 1, grammar, a, exstr)); } if (must) { code.AppendLineFormat(tabs + 1, "{0} &= {1};", resstr, exstr); } else { code.AppendLineFormat(tabs + 1, "{0} |= {1};", resstr, exstr); } code.AppendLine(); code.AppendLineFormat(tabs, "}} // end alternatives {0}", exstr); code.AppendLine(); return code.ToString(); }
/// <summary> /// Generates code to match Must and May constructs /// </summary> /// <param name="tabs"></param> /// <param name="exp"></param> /// <param name="must"></param> /// <param name="resstr"></param> /// <returns></returns> private string GenerateAlternativesMatch(int tabs, GrammarInfo grammar, MethodCallExpression exp, bool must, string resstr) { string exstr = String.Format("a{0}", ++excount); CodeStringBuilder code = new CodeStringBuilder(); code.AppendLineFormat(tabs, "if ({0})", resstr); // code.AppendLineFormat(tabs, "{{ // alternatives {0} {1}", exstr, must ? "must" : "may"); code.AppendLineFormat(tabs + 1, "bool {0} = false;", exstr); var args = ((NewArrayExpression)exp.Arguments[0]).Expressions; foreach (var a in args) { code.AppendLineFormat(tabs + 1, "if (!{0})", exstr); code.Append(GenerateProductionMatch(tabs + 1, grammar, a, exstr)); } if (must) { code.AppendLineFormat(tabs + 1, "{0} &= {1};", resstr, exstr); } else { code.AppendLineFormat(tabs + 1, "{0} |= {1};", resstr, exstr); } code.AppendLine(); code.AppendLineFormat(tabs, "}} // end alternatives {0}", exstr); code.AppendLine(); return(code.ToString()); }
/// <summary> /// Generate a single rule class /// </summary> /// <param name="f"></param> /// <returns></returns> private string GenerateRuleClass(GrammarInfo grammar, string name) { int tabs = 3; var resstr = "res"; var g = grammar.FindProductionGrammar(name, false); var exp = g.Rules[name].GetValue(null) as LambdaExpression; if (exp == null) { // **** TODO throw new ParserGeneratorException(String.Format("Rule '{0}' must be a lambda expression.", name)); } CodeStringBuilder code = new CodeStringBuilder(); code.AppendLine(tabs, "bool res = true;"); code.AppendLine(); code.Append(GenerateProductionMatch(tabs, grammar, exp.Body, resstr)); code.AppendLine(tabs, "return res;"); // Figure out whether this rule is inherited or not string inherited; g = grammar.FindProductionBaseGrammar(name); if (g == grammar) { inherited = String.Format("{0}.Node", typeof(Token).Namespace); } else { inherited = String.Format("{0}.{1}", g.Attributes.Namespace, name); //inheritedRules.Add(name); } var template = new StringBuilder(Templates.Rule); template.Replace("[$InheritedType]", inherited); template.Replace("[$LibNamespace]", typeof(Token).Namespace); template.Replace("[$Name]", name); template.Replace("[$Code]", code.ToString()); return(template.ToString()); }
private string GenerateMayMatch(int tabs, GrammarInfo grammar, MethodCallExpression exp, string resstr) { string exstr = String.Format("a{0}", ++excount); CodeStringBuilder code = new CodeStringBuilder(); var arg = exp.Arguments[0]; code.AppendLineFormat(tabs, "if ({0})", resstr); code.AppendLineFormat(tabs, "{{ // may {0}", exstr); code.AppendLineFormat(tabs + 1, "bool {0} = false;", exstr); code.Append(GenerateProductionMatch(tabs + 1, grammar, arg, exstr)); code.AppendLineFormat(tabs + 1, "{0} |= {1};", resstr, exstr); code.AppendLineFormat(tabs, "}} // end may {0}", exstr); code.AppendLine(); return(code.ToString()); }
/// <summary> /// Generates code that matches a sequence, or alternatively anything else. /// </summary> /// <param name="tabs"></param> /// <param name="exp"></param> /// <param name="resstr"></param> /// <returns></returns> /// <remarks> /// If the matched rule is not a sequence it gets wrapped into a virtual sequence. /// </remarks> private string GenerateProductionMatch(int tabs, GrammarInfo grammar, Expression exp, string resstr) { var code = new CodeStringBuilder(); if (exp.NodeType == ExpressionType.Call && ((MethodCallExpression)exp).Method.Name == "Sequence") { // If it's a sequence extract arguments code.Append(GenerateSequenceMatch(tabs, grammar, (MethodCallExpression)exp, resstr)); } else { // If it's not a sequence, wrap it in a list code.Append(GenerateListMatch(tabs, grammar, new Expression[] { exp }, resstr)); } return(code.ToString()); }
private string GenerateKeywordList(GrammarInfo grammar) { var csb = new CodeStringBuilder(); int q = 0; string line = ""; foreach (var keyword in grammar.Keywords.OrderBy(i => i)) { q++; if (q % 10 == 0) { csb.AppendLine(3, line); line = ""; } line += String.Format("\"{0}\", ", keyword); } csb.AppendLine(3, line); return(csb.ToString()); }
/// <summary> /// Generate a single rule class /// </summary> /// <param name="f"></param> /// <returns></returns> private string GenerateRuleClass(GrammarInfo grammar, string name) { int tabs = 3; var resstr = "res"; var g = grammar.FindProductionGrammar(name, false); var exp = g.Rules[name].GetValue(null) as LambdaExpression; if (exp == null) { // **** TODO throw new ParserGeneratorException(String.Format("Rule '{0}' must be a lambda expression.", name)); } CodeStringBuilder code = new CodeStringBuilder(); code.AppendLine(tabs, "bool res = true;"); code.AppendLine(); code.Append(GenerateProductionMatch(tabs, grammar, exp.Body, resstr)); code.AppendLine(tabs, "return res;"); // Figure out whether this rule is inherited or not string inherited; g = grammar.FindProductionBaseGrammar(name); if (g == grammar) { inherited = String.Format("{0}.Node", typeof(Token).Namespace); } else { inherited = String.Format("{0}.{1}", g.Attributes.Namespace, name); //inheritedRules.Add(name); } var template = new StringBuilder(Templates.Rule); template.Replace("[$InheritedType]", inherited); template.Replace("[$LibNamespace]", typeof(Token).Namespace); template.Replace("[$Name]", name); template.Replace("[$Code]", code.ToString()); return template.ToString(); }
/// <summary> /// Generates code that matches a sequence, or alternatively anything else. /// </summary> /// <param name="tabs"></param> /// <param name="exp"></param> /// <param name="resstr"></param> /// <returns></returns> /// <remarks> /// If the matched rule is not a sequence it gets wrapped into a virtual sequence. /// </remarks> private string GenerateProductionMatch(int tabs, GrammarInfo grammar, Expression exp, string resstr) { var code = new CodeStringBuilder(); if (exp.NodeType == ExpressionType.Call && ((MethodCallExpression)exp).Method.Name == "Sequence") { // If it's a sequence extract arguments code.Append(GenerateSequenceMatch(tabs, grammar, (MethodCallExpression)exp, resstr)); } else { // If it's not a sequence, wrap it in a list code.Append(GenerateListMatch(tabs, grammar, new Expression[] { exp }, resstr)); } return code.ToString(); }
private string GenerateMayMatch(int tabs, GrammarInfo grammar, MethodCallExpression exp, string resstr) { string exstr = String.Format("a{0}", ++excount); CodeStringBuilder code = new CodeStringBuilder(); var arg = exp.Arguments[0]; code.AppendLineFormat(tabs, "if ({0})", resstr); code.AppendLineFormat(tabs, "{{ // may {0}", exstr); code.AppendLineFormat(tabs + 1, "bool {0} = false;", exstr); code.Append(GenerateProductionMatch(tabs + 1, grammar, arg, exstr)); code.AppendLineFormat(tabs + 1, "{0} |= {1};", resstr, exstr); code.AppendLineFormat(tabs, "}} // end may {0}", exstr); code.AppendLine(); return code.ToString(); }
/// <summary> /// Generates code to match a list of rules /// </summary> /// <param name="tabs"></param> /// <param name="exp"></param> /// <param name="resstr"></param> /// <returns></returns> /// <remarks> /// This is used by the GenerateSequenceMatch and GenerateProductionMatch function /// to generate the inner part of the code matching sequences or any token wrapped /// into a virtual sequence. /// </remarks> private string GenerateListMatch(int tabs, GrammarInfo grammar, IEnumerable<Expression> exp, string resstr) { CodeStringBuilder code = new CodeStringBuilder(); string exstr = String.Format("r{0}", ++excount); code.AppendLine(tabs, "{"); GenerateCheckpoint(code, tabs + 1, exstr); code.AppendLine(); code.AppendLineFormat(tabs + 1, "bool {0} = true;", exstr); foreach (var arg in exp) { switch (arg.NodeType) { case ExpressionType.MemberAccess: var m = (MemberExpression)arg; if (m.Type == typeof(Expression<Grammar.Symbol>) || m.Type == typeof(Expression<Grammar.Terminal>) || m.Type == typeof(Expression<Grammar.Whitespace>) || m.Type == typeof(Expression<Grammar.Comment>) || m.Type == typeof(Expression<Grammar.Rule>)) { code.AppendLineFormat(tabs + 1, "{0} = {0} && {1};", exstr, GenerateRuleMatch(grammar, m.Member.Name)); } else { throw new InvalidOperationException(); //*** TODO } break; case ExpressionType.Call: var c = (MethodCallExpression)arg; switch (c.Method.Name) { case "Sequence": code.AppendLineFormat(tabs + 1, "if ({0})", exstr); code.Append(GenerateSequenceMatch(tabs + 1, grammar, c, exstr)); break; case "Must": code.Append(GenerateAlternativesMatch(tabs + 1, grammar, c, true, exstr)); break; case "May": code.Append(GenerateMayMatch(tabs + 1, grammar, c, exstr)); break; case "Keyword": code.AppendLineFormat(tabs + 1, "{0} = {0} && {1};", exstr, GenerateKeywordMatch(c)); break; default: throw new InvalidOperationException(); //*** TODO } break; default: throw new InvalidOperationException(); //*** TODO } } GenerateCommitOrRollback(code, tabs + 1, exstr); code.AppendLineFormat(tabs + 1, "{0} = {1};", resstr, exstr); code.AppendLine(tabs, "}"); code.AppendLine(); return code.ToString(); }
private string GenerateKeywordList(GrammarInfo grammar) { var csb = new CodeStringBuilder(); int q = 0; string line = ""; foreach (var keyword in grammar.Keywords.OrderBy(i => i)) { q++; if (q % 10 == 0) { csb.AppendLine(3, line); line = ""; } line += String.Format("\"{0}\", ", keyword); } csb.AppendLine(3, line); return csb.ToString(); }
private void GenerateCommitOrRollback(CodeStringBuilder csb, int tabs, string exstr) { csb.AppendLineFormat(tabs, "CommitOrRollback({0}, parser);", exstr); }
private void GenerateCheckpoint(CodeStringBuilder csb, int tabs, string exstr) { csb.AppendLineFormat(tabs, "Checkpoint(parser); // {0}", exstr); }
/// <summary> /// Generates code to match a list of rules /// </summary> /// <param name="tabs"></param> /// <param name="exp"></param> /// <param name="resstr"></param> /// <returns></returns> /// <remarks> /// This is used by the GenerateSequenceMatch and GenerateProductionMatch function /// to generate the inner part of the code matching sequences or any token wrapped /// into a virtual sequence. /// </remarks> private string GenerateListMatch(int tabs, GrammarInfo grammar, IEnumerable <Expression> exp, string resstr) { CodeStringBuilder code = new CodeStringBuilder(); string exstr = String.Format("r{0}", ++excount); code.AppendLine(tabs, "{"); GenerateCheckpoint(code, tabs + 1, exstr); code.AppendLine(); code.AppendLineFormat(tabs + 1, "bool {0} = true;", exstr); foreach (var arg in exp) { switch (arg.NodeType) { case ExpressionType.MemberAccess: var m = (MemberExpression)arg; if (m.Type == typeof(Expression <Grammar.Symbol>) || m.Type == typeof(Expression <Grammar.Terminal>) || m.Type == typeof(Expression <Grammar.Whitespace>) || m.Type == typeof(Expression <Grammar.Comment>) || m.Type == typeof(Expression <Grammar.Rule>)) { code.AppendLineFormat(tabs + 1, "{0} = {0} && {1};", exstr, GenerateRuleMatch(grammar, m.Member.Name)); } else { throw new InvalidOperationException(); //*** TODO } break; case ExpressionType.Call: var c = (MethodCallExpression)arg; switch (c.Method.Name) { case "Sequence": code.AppendLineFormat(tabs + 1, "if ({0})", exstr); code.Append(GenerateSequenceMatch(tabs + 1, grammar, c, exstr)); break; case "Must": code.Append(GenerateAlternativesMatch(tabs + 1, grammar, c, true, exstr)); break; case "May": code.Append(GenerateMayMatch(tabs + 1, grammar, c, exstr)); break; case "Keyword": code.AppendLineFormat(tabs + 1, "{0} = {0} && {1};", exstr, GenerateKeywordMatch(c)); break; default: throw new InvalidOperationException(); //*** TODO } break; default: throw new InvalidOperationException(); //*** TODO } } GenerateCommitOrRollback(code, tabs + 1, exstr); code.AppendLineFormat(tabs + 1, "{0} = {1};", resstr, exstr); code.AppendLine(tabs, "}"); code.AppendLine(); return(code.ToString()); }