コード例 #1
0
        /// <summary>
        /// Processes the rule name reference.
        /// Depending on the current parser walker context this can be:
        ///  1) new rule definition;
        ///  2) reference to an existing rule from excluded global rules list;
        ///  3) reference to an existing rule from the rule body.
        /// </summary>
        /// <param name="match">Current parse tree node</param>
        private void EnterRuleName(ITextParseTreeNode match)
        {
            var ruleName = match.GetImage();

            if (match.Parent.RuleName == ExtGrammarRules.Rule)
            {
                rules.Add(new RuleInfo {
                    Name = ruleName
                });

                output.Write("{0}Rule", ruleName);
            }
            else
            {
                referencedRules.Add(ruleName);

                if (match.Parent.RuleName == ExtGrammarRules.ExcludedGlobalRules)
                {
                    excludedGlobalRules.Add(ruleName);
                }
                else
                {
                    ruleBodyExpression.AddChild(new RuleExpression(ruleName));
                }
            }
        }
コード例 #2
0
        /// <summary>
        /// Adds alternate expression (Rule1 | Rule2) to the expression tree for the current rule.
        /// </summary>
        /// <param name="match">Current parse tree node</param>
        private void EnterAlternate(ITextParseTreeNode match)
        {
            /* Alternate expressions are parsed like this:
             *
             * Rule1 | Rule2 | Rule3
             *
             * RuleName (Rule1)
             * AlternateExpression
             * -RuleName (Rule2)
             * -AlternateExpression
             * --RuleName (Rule3)
             */

            if (ruleBodyExpression is OneOfExpression)
            {
                // Already alternating, just add to children
                base.Enter(match);
            }
            else
            {
                // Start new alternate with previous expression
                var previousExpression = ruleBodyExpression.RemoveLastChild();

                var alternateExpression = new OneOfExpression();
                alternateExpression.AddChild(previousExpression);

                ruleBodyExpression.AddChild(alternateExpression);
                ruleBodyExpression = alternateExpression;

                base.Enter(match);

                ruleBodyExpression = ruleBodyExpression.Parent;
            }
        }
コード例 #3
0
        /// <summary>
        /// Generates the contents (properties and methods) for the class that defines the parser rule.
        /// </summary>
        /// <param name="match">Current parse tree node</param>
        private void EnterRuleBody(ITextParseTreeNode match)
        {
            ruleBodyExpression = new SequenceExpression();

            output.WriteLine(" : TextProductionRule");
            output.WriteLine("{");

            WriteExcludedGlobalRules();

            WriteRuleNameProperty();

            output.WriteLine("protected override IParserRule<char> GetBody()");
            output.WriteLine("{");

            base.Enter(match);

            output.WriteLine("return");

            ruleBodyExpression.Visit(
                new CodeGenVisitor(grammarName, output));

            output.WriteLine(";");

            output.WriteLine("}");
        }
コード例 #4
0
 /// <summary>
 /// Enters the parse tree node, that represents matched rule.
 /// </summary>
 /// <param name="match">Match of the text parser rule</param>
 protected virtual void Enter(ITextParseTreeNode match)
 {
     foreach (var child in match.Children)
     {
         Enter(child);
     }
 }
コード例 #5
0
        /// <summary>
        /// Writes the rule name to the output and enters all the matched children rules.
        /// </summary>
        /// <param name="match">Match of the text parser rule</param>
        protected sealed override void Enter(ITextParseTreeNode match)
        {
            WriteMatch(match);

            ++indentLevel;
            base.Enter(match);
            --indentLevel;
        }
コード例 #6
0
        /// <summary>
        /// Adds quantifier expression (*, +) to the expression tree for the current rule.
        /// </summary>
        /// <param name="match">Current parse tree node</param>
        private void EnterQuantifier <TExpression>(ITextParseTreeNode match)
            where TExpression : ExpressionTreeNode, new()
        {
            var previousExpression = ruleBodyExpression.RemoveLastChild();

            var quantifierExpression = new TExpression();

            quantifierExpression.AddChild(previousExpression);

            ruleBodyExpression.AddChild(quantifierExpression);
        }
コード例 #7
0
        /// <summary>
        /// Adds simple expression to the expression tree for the current rule.
        /// There are some expressions that don't require any special handling
        /// and just need to be added to the expression tree at the point where
        /// they are met in the parse tree.
        /// </summary>
        /// <param name="match">Current parse tree node</param>
        private void EnterSimpleExpression <TExpression>(ITextParseTreeNode match)
            where TExpression : ExpressionTreeNode, new()
        {
            var newExpression = new TExpression();

            ruleBodyExpression.AddChild(newExpression);
            ruleBodyExpression = newExpression;

            base.Enter(match);

            ruleBodyExpression = ruleBodyExpression.Parent;
        }
コード例 #8
0
        /// <summary>
        /// Adds character range expression ('x'..'y') to the expression tree for the current rule.
        /// </summary>
        /// <param name="match">Current parse tree node</param>
        private void EnterCharacterRange(ITextParseTreeNode match)
        {
            if (match.Children.Count != 2)
            {
                throw new InvalidOperationException("Character range match is expected to have exactly two children");
            }

            ruleBodyExpression.AddChild(
                new CharacterRangeExpression(
                    match.Children[0].GetImage(),
                    match.Children[1].GetImage()));
        }
コード例 #9
0
 /// <summary>
 /// Writes rule name with additional information (like string literal or character range)
 /// to the output and enters all the matched children rules.
 /// </summary>
 /// <param name="match">Match of the text parser rule</param>
 protected override void WriteMatch(ITextParseTreeNode match)
 {
     if (match.RuleName == ExtGrammarRules.RuleName)
     {
         Write(match.RuleName + " (" + match.GetImage() + ")");
     }
     else if (match.RuleName == ExtGrammarRules.LiteralValue ||
              match.RuleName == ExtGrammarRules.CharacterRange)
     {
         Write(match.RuleName + " " + match.GetImage());
     }
     else
     {
         base.WriteMatch(match);
     }
 }
コード例 #10
0
        /// <summary>
        /// Generates rules namespace (usings block and rules classes).
        /// </summary>
        /// <param name="match">Current parse tree node</param>
        private void EnterGrammar(ITextParseTreeNode match)
        {
            output.WriteLine("namespace {0}.{1}.Rules", namespaceName, grammarName);
            output.WriteLine("{");

            output.WriteLine("using System.Collections.Generic;");
            output.WriteLine("using ExtParser.Core;");
            output.WriteLine("using ExtParser.Text;");

            base.Enter(match);

            output.WriteLine("}");

            WriteRuleNameConstants();
            WriteParser();
        }
コード例 #11
0
        /// <summary>
        /// Generates rule class stub.
        /// </summary>
        /// <param name="match">Current parse tree node</param>
        private void EnterRule(ITextParseTreeNode match)
        {
            output.Write("public partial class ");

            ruleBodyExpression  = null;
            excludedGlobalRules = null;

            base.Enter(match);

            if (ruleBodyExpression == null)
            {
                // Rules without a body treated as terminals.
                // There are basically two types of rules - production and terminal. All productions
                // can be expressed through the grammar. If there was no body defined, then most likely
                // it was meant to be a light-weight terminal rule.
                output.WriteLine(" : TerminalParserRule<char>");
                output.WriteLine("{");

                WriteRuleNameProperty();
            }

            output.WriteLine("}");
        }
コード例 #12
0
 /// <summary>
 /// Walks the parse tree over the given input.
 /// </summary>
 /// <param name="parseTree">Parse tree for the given input</param>
 public void Walk(ITextParseTreeNode parseTree)
 {
     Enter(parseTree);
 }
コード例 #13
0
        /// <summary>
        /// Dispatches the logic based on the matched rule.
        /// </summary>
        /// <param name="match">Information about the matched rule</param>
        protected override void Enter(ITextParseTreeNode match)
        {
            switch (match.RuleName)
            {
            case ExtGrammarRules.Grammar:
                EnterGrammar(match);
                break;

            case ExtGrammarRules.Rule:
                EnterRule(match);
                break;

            case ExtGrammarRules.RuleName:
                EnterRuleName(match);
                break;

            case ExtGrammarRules.IsGlobalRule:
                EnterIsGlobalRule(match);
                break;

            case ExtGrammarRules.ExcludedGlobalRules:
                EnterExcludedGlobalRules(match);
                break;

            case ExtGrammarRules.RuleBody:
                EnterRuleBody(match);
                break;

            // Body rules
            case ExtGrammarRules.ExpressionGroup:
                EnterSimpleExpression <SequenceExpression>(match);
                break;

            case ExtGrammarRules.OptionalExpression:
                EnterSimpleExpression <OptionalExpression>(match);
                break;

            case ExtGrammarRules.ZeroOrMoreTimes:
                EnterQuantifier <ZeroOrMoreTimesExpression>(match);
                break;

            case ExtGrammarRules.OneOrMoreTimes:
                EnterQuantifier <OneOrMoreTimesExpression>(match);
                break;

            case ExtGrammarRules.AlternateExpression:
                EnterAlternate(match);
                break;

            case ExtGrammarRules.LiteralValue:
                EnterLiteralValue(match);
                break;

            case ExtGrammarRules.CharacterRange:
                EnterCharacterRange(match);
                break;

            // Default
            default:
                base.Enter(match);
                break;
            }
        }
コード例 #14
0
        /// <summary>
        /// Resets the <see cref="excludedGlobalRules"/> list and visits all children elements
        /// that are expected to be excluded rule names.
        /// </summary>
        /// <param name="match">Current parse tree node</param>
        private void EnterExcludedGlobalRules(ITextParseTreeNode match)
        {
            excludedGlobalRules = new List <string>();

            base.Enter(match);
        }
コード例 #15
0
 /// <summary>
 /// Marks current rule as global.
 /// </summary>
 /// <param name="match">Current parse tree node</param>
 private void EnterIsGlobalRule(ITextParseTreeNode match)
 {
     rules[rules.Count - 1].IsGlobal = true;
 }
コード例 #16
0
 /// <summary>
 /// Writes the rule name with the current indentation level.
 /// </summary>
 /// <param name="match">Match of the text parser rule</param>
 protected virtual void WriteMatch(ITextParseTreeNode match)
 {
     Write(match.RuleName);
 }
コード例 #17
0
 /// <summary>
 /// Adds literal value expression ("abc") to the expression tree for the current rule.
 /// </summary>
 /// <param name="match">Current parse tree node</param>
 private void EnterLiteralValue(ITextParseTreeNode match)
 {
     ruleBodyExpression.AddChild(
         new LiteralExpression(match.GetImage()));
 }