Ejemplo n.º 1
0
        /// <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();
        }
Ejemplo n.º 2
0
        /// <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());
        }
Ejemplo n.º 3
0
        /// <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());
        }
Ejemplo n.º 4
0
        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());
        }
Ejemplo n.º 5
0
        /// <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());
        }
Ejemplo n.º 6
0
        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());
        }
Ejemplo n.º 7
0
        /// <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();
        }
Ejemplo n.º 8
0
        /// <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();
        }
Ejemplo n.º 9
0
        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();
        }
Ejemplo n.º 10
0
        /// <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();
        }
Ejemplo n.º 11
0
        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();
        }
Ejemplo n.º 12
0
 private void GenerateCommitOrRollback(CodeStringBuilder csb, int tabs, string exstr)
 {
     csb.AppendLineFormat(tabs, "CommitOrRollback({0}, parser);", exstr);
 }
Ejemplo n.º 13
0
 private void GenerateCheckpoint(CodeStringBuilder csb, int tabs, string exstr)
 {
     csb.AppendLineFormat(tabs, "Checkpoint(parser); // {0}", exstr);
 }
Ejemplo n.º 14
0
 private void GenerateCommitOrRollback(CodeStringBuilder csb, int tabs, string exstr)
 {
     csb.AppendLineFormat(tabs, "CommitOrRollback({0}, parser);", exstr);
 }
Ejemplo n.º 15
0
 private void GenerateCheckpoint(CodeStringBuilder csb, int tabs, string exstr)
 {
     csb.AppendLineFormat(tabs, "Checkpoint(parser); // {0}", exstr);
 }
Ejemplo n.º 16
0
        /// <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());
        }