Exemple #1
0
        private BranchParseNode BuildNode(bool success)
        {
            StackFrame removedFrame = PopFrame();

            BranchParseNode result;

            if (success)
            {
                LastOperation = Operation.Build;
                result        = new BranchParseNode(removedFrame.Rule, removedFrame.InputIndex, removedFrame.Nodes);

                if (removedFrame.Rule is NamedRule named)
                {
                    Super.ReportSuccess(named, result.MatchedText);
                }
            }
            else
            {
                LastOperation = Operation.Cancel;
                result        = null;

                if (removedFrame.Rule is NamedRule named)
                {
                    Super.ReportFailure(named);
                }
            }

            return(result);
        }
Exemple #2
0
        internal static ISemanticNode FunctionCall(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse)
        {
            ISemanticNode @ref = recurse(branch.GetDescendant(0));

            BranchParseNode first = branch.GetDescendant(1, 0, 1, 0);

            BranchParseNode fragments = branch.GetDescendant(1, 0, 1, 1);

            if (first != null)
            {
                if (fragments != null)
                {
                    ISemanticNode args = CompositeExpression(recurse(first), fragments, recurse);
                    return(new BranchSemanticNode((int)JsNodeType.FunctionCall, @ref, args));
                }
                else
                {
                    return(new BranchSemanticNode((int)JsNodeType.FunctionCall, @ref, recurse(first)));
                }
            }
            else
            {
                return(new BranchSemanticNode((int)JsNodeType.FunctionCall, @ref));
            }
        }
Exemple #3
0
        internal static ISemanticNode And(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse)
        {
            var left  = recurse(branch.GetDescendant(0));
            var right = recurse(branch.GetDescendant(1));

            return(new BranchSemanticNode((int)EbnfNodeType.And, left, right));
        }
Exemple #4
0
        internal static ISemanticNode PropertyAssignment(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse)
        {
            ISemanticNode lvalue = recurse(branch.GetDescendant(0));
            ISemanticNode rvalue = recurse(branch.GetDescendant(2));

            return(new BranchSemanticNode((int)JsNodeType.Assignment, lvalue, rvalue));
        }
Exemple #5
0
        internal static ISemanticNode Identifier(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse)
        {
            var text       = branch.Leaf.MatchedText;
            var startIndex = branch.Leaf.StartIndex;

            return(new LeafSemanticNode((int)EbnfNodeType.Identifier, startIndex, text));
        }
Exemple #6
0
        internal static ISemanticNode Token(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse)
        {
            var name = recurse(branch.GetDescendant(0));
            var expr = recurse(branch.GetDescendant(2));

            return(new BranchSemanticNode((int)EbnfNodeType.Token, name.StartIndex, new[] { name, expr }));
        }
Exemple #7
0
        internal static ISemanticNode Or(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse)
        {
            ISemanticNode left  = recurse(branch.GetDescendant(0));
            ISemanticNode right = recurse(branch.GetDescendant(2));

            return(new BranchSemanticNode((int)EbnfNodeType.Or, left, right));
        }
Exemple #8
0
        internal static ISemanticNode CompositeExpression(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse)
        {
            ISemanticNode first = recurse(branch.GetDescendant(0));

            BranchParseNode fragments = branch.GetDescendant(1);

            return(CompositeExpression(first, fragments, recurse));
        }
Exemple #9
0
        internal static ISemanticNode Root(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse)
        {
            var elements = branch.Elements;

            var children = elements
                           .Select(recurse)
                           .ToArray();

            return(new BranchSemanticNode((int)EbnfNodeType.Root, branch.StartIndex, children));
        }
Exemple #10
0
        internal static ISemanticNode Regex(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse)
        {
            var text = branch.Leaf.MatchedText;

            text = text
                   .Substring(1, text.Length - 2)
                   .Replace(@"\\", @"\")
                   .Replace(@"\/", @"/");
            var startIndex = branch.Leaf.StartIndex;

            return(new LeafSemanticNode((int)EbnfNodeType.Regex, startIndex, text));
        }
Exemple #11
0
        internal static ISemanticNode Token(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse)
        {
            BranchParseNode identNode  = branch.GetDescendant(0);
            var             ident      = identNode.Leaf.MatchedText;
            var             startIndex = identNode.Leaf.StartIndex;

            var name = new LeafSemanticNode((int)EbnfNodeType.Identifier, startIndex, ident);

            ISemanticNode expr = recurse(branch.GetDescendant(2));

            return(new BranchSemanticNode((int)EbnfNodeType.Token, name.StartIndex, new[] { name, expr }));
        }
Exemple #12
0
        public override BranchParseNode ParseSyntax(string input)
        {
            IEnumerable <Lexeme> lexemes = Lex(input);

            BranchParseNode result = ParseSyntax(lexemes);

            if (result.MatchedText.Length != input.Length)
            {
                throw new Exception();
            }

            return(result);
        }
Exemple #13
0
        public ISemanticNode Parse(string input)
        {
            if (!IsLocked)
            {
                throw new Exception();
            }

            BranchParseNode parseTree = ParseSyntax(input);

            ISemanticNode semanticTree = ParseSemantics(parseTree);

            return(semanticTree);
        }
Exemple #14
0
        public void Ebnf()
        {
            var parserGen = new ParserGenerator();

            var grammar  = $@"
{RuleName.Equals} = ""="";
{RuleName.Pipe} = ""|"";
{RuleName.Asterisk} = ""*"";
{RuleName.QuestionMark} = ""?"";
{RuleName.ExclamationPoint} = ""!"";
{RuleName.Semicolon} = "";"";
{RuleName.LeftParenthesis} = ""("";
{RuleName.RightParenthesis} = "")"";

{RuleName.Whitespace} = /\s+/;
{RuleName.Identifier} = /\w(?:\w|\d)*/;
{RuleName.String} = /""(\\\\[^""]|\\\\""|[^""])*""/;
{RuleName.Regex} = /\/(\\\\[^\/]|\\\\\/|[^\/])+\//;
{RuleName.LineComment} = /\/\/[^{"\r\n"}]*(?=[{"\r\n"}])/;

{RuleName.And} = {RuleName.SimpleExpression} {RuleName.Expression};
{RuleName.Or} = {RuleName.SimpleExpression} {RuleName.Pipe} {RuleName.Expression};
{RuleName.Not} = {RuleName.ExclamationPoint} {RuleName.Expression};
{RuleName.Optional} = {RuleName.QuestionMark} {RuleName.Expression};
{RuleName.Repeat} = {RuleName.Asterisk} {RuleName.Expression};
{RuleName.Group} = {RuleName.LeftParenthesis} {RuleName.Expression} {RuleName.RightParenthesis};

{RuleName.Literal} = {RuleName.String} | {RuleName.Regex};
{RuleName.SimpleExpression} = {RuleName.Not} | {RuleName.Optional} | {RuleName.Repeat} | {RuleName.Group} | {RuleName.Identifier};
{RuleName.Expression} = {RuleName.Or} | {RuleName.And} | {RuleName.SimpleExpression};

{RuleName.Token} = {RuleName.Identifier} {RuleName.Equals} {RuleName.Literal} {RuleName.Semicolon};
{RuleName.Rule} = {RuleName.Identifier} {RuleName.Equals} {RuleName.Expression} {RuleName.Semicolon};

// This is a comment.
{RuleName.Root} = *({RuleName.Token} | {RuleName.Rule});
";
            var settings = new ParserSettings
            {
                Algorithm   = Parser.Algorithm.LL,
                NestingType = Parser.NestingType.Recursion,
                Unit        = Parser.Unit.Lexeme,
            };
            Parser parser = parserGen.SpawnParser(settings, grammar, RuleName.Whitespace, RuleName.LineComment);

            parser.Lock();

            BranchParseNode result = parser.ParseSyntax(grammar);

            Assert.AreEqual(grammar, result.MatchedText);
        }
Exemple #15
0
        public ISemanticNode ParseSemantics(BranchParseNode node)
        {
            if (!IsLocked)
            {
                throw new Exception();
            }

            if (node.Rule is NamedRule named)
            {
                return(named.Action(node, ParseSemantics));
            }
            else
            {
                throw new Exception();
            }
        }
Exemple #16
0
        private static List <ISemanticNode> ExpressionFragments(BranchParseNode fragments, Func <BranchParseNode, ISemanticNode> recurse)
        {
            ISemanticNode first = recurse(fragments.GetDescendant(0));

            BranchParseNode restNode = fragments.GetDescendant(1);

            if (restNode != null)
            {
                List <ISemanticNode> rest = ExpressionFragments(restNode, recurse);

                return(new[] { first }.Concat(rest).ToList());
            }
            else
            {
                return(new[] { first }.ToList());
            }
        }
Exemple #17
0
        static ISemanticNode DefaultAction(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse)
        {
            if (branch.Rule is NamedRule rule)
            {
                throw new Exception($"No action specified for named rule: {rule.Name}");
            }

            branch = branch.Unwrap();

            if (branch.Rule is NamedRule)
            {
                return(recurse(branch));
            }

            var children = branch.Elements
                           .Select(n =>
            {
                if (n.Rule is NamedRule)
                {
                    return(recurse(n));
                }
                else
                {
                    return(DefaultAction(n, recurse));
                }
            })
                           .Where(c => c != null)
                           .ToList();

            if (children.Count == 1)
            {
                return(children[0]);
            }
            else
            {
                return(new BranchSemanticNode(0, branch.StartIndex, children));
            }
        }
Exemple #18
0
 internal static ISemanticNode Group(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse) => new BranchSemanticNode((int)EbnfNodeType.Group, recurse(branch.GetDescendant(1)));
Exemple #19
0
 internal static ISemanticNode LineComment(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse)
 {
     return(null);
 }
Exemple #20
0
 internal static ISemanticNode Whitespace(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse) => null;
Exemple #21
0
        internal static ISemanticNode Constructor(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse)
        {
            ISemanticNode funCall = recurse(branch.GetDescendant(1));

            return(new BranchSemanticNode((int)JsNodeType.Constructor, funCall));
        }
Exemple #22
0
        public CommandParser(Parameters parameters)
        {
            command = new Command("", parameters);

            var grammar = $@"
equals = ""="";

shortOptions = /(?<= )-[_\w]+/;
shortOption = /(?<= )-[_\w]/;
longOption = /(?<= )--[_\w][-_\w]*/;
endOptions = /(?<= )--(?= )/;
doubleString = /""(?:\\\\""|\\\\[^""]|[^""\\\\])*""/;
singleString = /'(?:\\\\'|\\\\[^']|[^'\\\\])*'/;
identifier = /[_\w][-_\w]*/;
literal = /.+/;
ws = /\s+/;
path = /(([A-Za-z]:)?[\/\\\\])?[-_\\w.]+([\/\\\\][-_\\w.]+)*[\/\\\\]?/;

string = doubleString | singleString;
shortOptionWithValue = shortOption equals (identifier | string);
longOptionWithValue = longOption equals (identifier | string);

options = *(shortOptionWithValue | longOptionWithValue | shortOptions | longOption | identifier | string);

details = options ?(endOptions literal);

root = (string | path) ?details;
";

            var parserGen = new ParserGenerator();
            var settings  = new ParserSettings
            {
                Algorithm   = Algorithm.LL,
                NestingType = NestingType.Stack,
                Unit        = Unit.Character,
            };

            parser = parserGen.SpawnParser(settings, grammar, "ws");

            parser.AttachAction("shortOptions", (branch, recurse) =>
            {
                var startIndex = branch.Leaf.StartIndex;
                IEnumerable <BranchSemanticNode> nodes = branch.Leaf.MatchedText
                                                         .Skip(1)
                                                         .Select((c, i) =>
                {
                    return(new BranchSemanticNode((int)CommandNodeType.Argument,
                                                  new LeafSemanticNode((int)CommandNodeType.ShortOption, startIndex + 1 + i, c.ToString())));
                });

                return(new BranchSemanticNode((int)CommandNodeType.Arguments, startIndex, nodes));
            });

            parser.AttachAction("shortOption", (branch, recurse) =>
            {
                LeafParseNode nameNode = branch.Leaf;
                var startIndex         = nameNode.StartIndex;
                var name = nameNode.MatchedText[1].ToString();

                return(new BranchSemanticNode((int)CommandNodeType.Argument,
                                              new LeafSemanticNode((int)CommandNodeType.ShortOption, startIndex, name)));
            });

            parser.AttachAction("shortOptionWithValue", (branch, recurse) =>
            {
                LeafParseNode nameNode = branch.GetDescendant(0).Leaf;
                var startIndex         = nameNode.StartIndex;
                var name            = nameNode.MatchedText[1].ToString();
                ISemanticNode value = recurse(branch.GetDescendant(2));

                return(new BranchSemanticNode((int)CommandNodeType.Argument,
                                              new LeafSemanticNode((int)CommandNodeType.ShortOption, startIndex, name),
                                              value));
            });

            parser.AttachAction("longOption", (branch, recurse) =>
            {
                LeafParseNode nameNode = branch.Leaf;
                var startIndex         = nameNode.StartIndex;
                var name = nameNode.MatchedText.Substring(2);

                return(new BranchSemanticNode((int)CommandNodeType.Argument,
                                              new LeafSemanticNode((int)CommandNodeType.LongOption, startIndex, name)));
            });

            parser.AttachAction("longOptionWithValue", (branch, recurse) =>
            {
                LeafParseNode nameNode = branch.GetDescendant(0).Leaf;
                var startIndex         = nameNode.StartIndex;
                var name            = nameNode.MatchedText.Substring(2);
                ISemanticNode value = recurse(branch.GetDescendant(2));

                return(new BranchSemanticNode((int)CommandNodeType.Argument,
                                              new LeafSemanticNode((int)CommandNodeType.LongOption, startIndex, name),
                                              value));
            });

            parser.AttachAction("identifier", (branch, recurse) =>
            {
                LeafParseNode nameNode = branch.Leaf;
                var startIndex         = nameNode.StartIndex;
                var name = nameNode.MatchedText;

                return(new LeafSemanticNode((int)CommandNodeType.String, startIndex, name));
            });

            parser.AttachAction("doubleString", (branch, recurse) =>
            {
                var text = branch.Leaf.MatchedText;
                text     = text
                           .Substring(1, text.Length - 2)
                           .Replace(@"\\", @"\")
                           .Replace(@"\""", @"""");
                var startIndex = branch.Leaf.StartIndex;

                return(new LeafSemanticNode((int)CommandNodeType.String, startIndex, text));
            });

            parser.AttachAction("singleString", (branch, recurse) =>
            {
                var text = branch.Leaf.MatchedText;
                text     = text
                           .Substring(1, text.Length - 2)
                           .Replace(@"\\", @"\")
                           .Replace(@"\'", @"'");
                var startIndex = branch.Leaf.StartIndex;

                return(new LeafSemanticNode((int)CommandNodeType.String, startIndex, text));
            });

            parser.AttachAction("string", (branch, recurse) => recurse(branch.GetDescendant(0)));

            parser.AttachAction("options", (branch, recurse) =>
            {
                IEnumerable <ISemanticNode> options = branch.GetDescendant(0)
                                                      ?.Elements
                                                      ?.Select(recurse);

                return(new BranchSemanticNode((int)CommandNodeType.Options, branch.StartIndex, options ?? new ISemanticNode[0]));
            });

            parser.AttachAction("literal", (branch, recurse) =>
            {
                var value = branch.Leaf.MatchedText;

                return(new LeafSemanticNode((int)CommandNodeType.String, branch.StartIndex, value));
            });

            parser.AttachAction("details", (branch, recurse) =>
            {
                BranchParseNode optionsNode = branch.GetDescendant(0);
                BranchParseNode literalNode = branch.GetDescendant(1, 1);

                var results = new List <ISemanticNode>();

                if (optionsNode != null)
                {
                    results.Add(recurse(optionsNode));
                }
                if (literalNode != null)
                {
                    results.Add(recurse(literalNode));
                }

                return(new BranchSemanticNode((int)CommandNodeType.Details, branch.StartIndex, results));
            });

            parser.AttachAction("path", (branch, recurse) =>
            {
                var value = branch.MatchedText;

                return(new LeafSemanticNode((int)CommandNodeType.String, branch.StartIndex, value));
            });

            parser.AttachAction("root", (branch, recurse) =>
            {
                ISemanticNode path    = recurse(branch.GetDescendant(0));
                ISemanticNode details = recurse(branch.GetDescendant(1));

                return(new BranchSemanticNode((int)CommandNodeType.Root, path, details));
            });
        }
Exemple #23
0
        private static ISemanticNode CompositeExpression(ISemanticNode first, BranchParseNode fragments, Func <BranchParseNode, ISemanticNode> recurse)
        {
            List <ISemanticNode> rest = ExpressionFragments(fragments, recurse);

            return(CompositeExpression(first, rest));
        }
Exemple #24
0
 internal static ISemanticNode Unwrap(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse) => recurse(branch.GetDescendant(0));
Exemple #25
0
        internal static ISemanticNode Group(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse)
        {
            var group = recurse(branch.GetDescendant(1));

            return(new BranchSemanticNode((int)EbnfNodeType.Group, group));
        }
Exemple #26
0
        internal static ISemanticNode Not(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse)
        {
            var not = recurse(branch.GetDescendant(1));

            return(new BranchSemanticNode((int)EbnfNodeType.Not, not));
        }
Exemple #27
0
        internal static ISemanticNode Optional(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse)
        {
            var opt = recurse(branch.GetDescendant(1));

            return(new BranchSemanticNode((int)EbnfNodeType.Optional, opt));
        }
Exemple #28
0
        internal static ISemanticNode Repeat(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse)
        {
            var repeat = recurse(branch.GetDescendant(1));

            return(new BranchSemanticNode((int)EbnfNodeType.Repeat, repeat));
        }
Exemple #29
0
        public static Grammar GetGrammar()
        {
            var grammarString = $@"
varKeyword = /\b(var)\b/;               // -/
letKeyword = /\b(let)\b/;               // -/
newKeyword = /\b(new)\b/;               // -/
deleteKeyword = /\b(delete)\b/;         // X ?
instanceofKeyword = /\b(instanceof)\b/; // X ?
withKeyword = /\b(with)\b/;             // X
voidKeyword = /\b(void)\b/;             // X
typeofKeyword = /\b(typeof)\b/;         // X ?
thisKeyword = /\b(this)\b/;             // X ?
debuggerKeyword = /\b(debugger)\b/;     // X
importKeyword = /\b(import)\b/;         // X
classKeyword = /\b(class)\b/;           // X
constKeyword = /\b(const)\b/;           // X ?
extendsKeyword = /\b(extends)\b/;       // X
yieldKeyword = /\b(yield)\b/;           // X
superKeyword = /\b(super)\b/;           // X

functionKeyword = /\b(function)\b/;     // -/
tryKeyword = /\b(try)\b/;               // X ?
catchKeyword = /\b(catch)\b/;           // X ?
finallyKeyword = /\b(finally)\b/;       // X ?
throwKeyword = /\b(throw)\b/;           // X ?
returnKeyword = /\b(return)\b/;         // X ?

ifKeyword = /\b(if)\b/;                 // X ?
elseKeyword = /\b(else)\b/;             // X ?
whileKeyword = /\b(while)\b/;           // X ?
doKeyword = /\b(do)\b/;                 // X ?
forKeyword = /\b(for)\b/;               // X ?
inKeyword = /\b(in)\b/;                 // X ?
switchKeyword = /\b(switch)\b/;         // X ?
caseKeyword = /\b(case)\b/;             // X ?
defaultKeyword = /\b(default)\b/;       // X ?
breakKeyword = /\b(break)\b/;           // X ?
continueKeyword = /\b(continue)\b/;     // X ?

implementsKeyword = /\b(implements)\b/; // X
interfaceKeyword = /\b(interface)\b/;   // X
packageKeyword = /\b(package)\b/;       // X
privateKeyword = /\b(private)\b/;       // X
protectedKeyword = /\b(protected)\b/;   // X
publicKeyword = /\b(public)\b/;         // X
staticKeyword = /\b(static)\b/;         // X
awaitKeyword = /\b(await)\b/;           // X
enumKeyword = /\b(enum)\b/;             // X

leftBracket = ""{{"";
rightBracket = ""}}"";

leftParen = ""("";
rightParen = "")"";

leftSquare = ""["";
rightSquare = ""]"";

comma = "","";
dot = ""."";

equals = ""="";
colon = "":"";
semicolon = "";"";

and = ""&&"";
or = ""||"";
not = ""!"";

strictEquality = ""==="";
strictInequality = ""!=="";
equality = ""=="";
inequality = ""!="";
lessThanOrEqual = ""<="";
greaterThanOrEqual = "">="";
lessThan = ""<"";
greaterThan = "">"";

ws = /\s+/;
ident = /\b[$A-Za-z_][$A-Za-z_0-9]*\b/;
number = /\b\d+(?:\.\d+)?\b/;
doubleString = /""(?:\\\\""|\\\\[^""]|[^""\\\\])*""/;
singleString = /'(?:\\\\'|\\\\[^']|[^'\\\\])*'/;
regex = /\/(?:\\\\\/|\\\\|[^\/])+\/[A-Za-z]*/;
lineComment = /\/\/[^{"\r\n"}]*/;
blockComment = /\/\*([^*]|\*[^\/])*\*\//;

minusEquals = ""-="";
plusEquals = ""+="";
timesEquals = ""*="";
divideEquals = ""/="";
modulusEquals = ""%="";

bitAndEquals = ""&="";
bitOrEquals = ""|="";
bitXorEquals = ""^="";

minus = ""-"";
plus = ""+"";
times = ""*"";
divide = ""/"";
modulus = ""%"";

bitAnd = ""&"";
bitOr = ""|"";
bitNot = ""~"";
bitXor = ""^"";

question = ""?"";

basicKeywords = varKeyword | letKeyword | newKeyword | deleteKeyword | instanceofKeyword | withKeyword | voidKeyword | typeofKeyword | thisKeyword | debuggerKeyword | importKeyword | classKeyword | constKeyword | extendsKeyword | yieldKeyword | superKeyword;
functionLevelKeywords = functionKeyword | tryKeyword | catchKeyword | finallyKeyword | throwKeyword | returnKeyword;
controlKeywords = ifKeyword | elseKeyword | whileKeyword | doKeyword | forKeyword | inKeyword | switchKeyword | caseKeyword | defaultKeyword | breakKeyword | continueKeyword;
futureKeywords = implementsKeyword | interfaceKeyword | packageKeyword | privateKeyword | protectedKeyword | publicKeyword | staticKeyword | awaitKeyword | enumKeyword;

validIdent = im !(basicKeywords | functionLevelKeywords | controlKeywords | futureKeywords) ident;

string = doubleString | singleString;

paren = leftParen expr3 rightParen;

unaryOper = minus | plus;
unaryMath = unaryOper *unaryOper expr2;

typeof = typeofKeyword expr2;

block = leftBracket *statement rightBracket;
paramList = leftParen ?(validIdent *(comma validIdent)) rightParen;
namedFunction = functionKeyword validIdent paramList block;
anonFunction = functionKeyword paramList block;

propertyDef = (validIdent | string) colon expr3;
object = leftBracket ?(propertyDef *(comma propertyDef)) rightBracket;

dotRef = dot validIdent;
key = leftSquare expr3 rightSquare;
argList = leftParen ?(expr3 *(comma expr3)) rightParen;
expressionFragment = dotRef | key | argList;

propertyFragments = (expressionFragment propertyFragments) | dotRef | key;
functionCallFragments = (expressionFragment functionCallFragments) | argList;

constructor = newKeyword functionCall;

// == END expr0 DEFINITIONS ==

functionCall = expr0 functionCallFragments;
propertyReference = expr0 propertyFragments;

// == END expr1 definitions ==

mathOper = minus | plus | times | divide;
math = expr1 mathOper expr2;

logicOper = and | or;
logicNegation = not expr2;
logic = expr1 logicOper expr2;

bitOper = bitAnd | bitOr | bitXor;
bitNegation = bitNot expr2;
bitwise = expr1 bitOper expr2;

instanceof = expr1 instanceofKeyword expr3;
in = expr1 inKeyword expr3;

// == END expr2 DEFINITIONS ==

assignOper = equals | minusEquals | plusEquals | timesEquals | divideEquals | modulusEquals | bitAndEquals | bitOrEquals | bitXorEquals;
localAssignment = validIdent assignOper expr3;
propertyAssignment = propertyReference assignOper expr3;
assignment = localAssignment | propertyAssignment;

ternary = expr2 question expr3 colon expr3;

// == END expr3 DEFINITIONS ==

variable = localAssignment | validIdent;
variableDecl = (varKeyword | letKeyword | constKeyword) variable *(comma variable);

break = breakKeyword;
continue = continueKeyword;
return = returnKeyword ?expr3;
throw = throwKeyword ?expr3;
delete = deleteKeyword propertyReference;
catch = catchKeyword block;
finally = finallyKeyword block;
try = tryKeyword block catch *catch ?finally;

default = defaultKeyword colon *statement;
case = caseKeyword (string | number | (validIdent *dotRef)) colon *statement;
switch = switchKeyword leftBracket *case ?default *case rightBracket;

else = elseKeyword statement;
if = ifKeyword statement ?else;
while = whileKeyword paren statement;
doWhile = doKeyword statement whileKeyword paren ?semicolon;
for = forKeyword leftParen ((variableDecl | expr3) semicolon expr3 semicolon expr3) rightParen statement;

expr0 = thisKeyword | anonFunction | validIdent | number | string | paren | unaryMath | logicNegation | bitNegation | constructor | object;
expr1 = functionCall | propertyReference | expr0;
expr2 = math | logic | instanceof | in | bitwise | expr1;
expr3 = ternary | assignment | expr2;
blockStatement = if | while | doWhile | forIn | for | switch | namedFunction | block;
statement = blockStatement | ((variableDecl | break | continue | return | throw | delete | expr3) ?semicolon) | semicolon;

root = statement *statement;
";

            var parserGen = new ParserGenerator();

            Grammar grammar = parserGen.BuildGrammar(grammarString, "ws", "lineComment", "blockComment");

            grammar.AttachAction("root", (branch, recurse) =>
            {
                ISemanticNode first  = recurse(branch.GetDescendant(0));
                ISemanticNode[] rest = branch.GetDescendant(1)
                                       .Elements
                                       .Select(recurse)
                                       .ToArray();

                return(new BranchSemanticNode((int)JsNodeType.Root, first, rest));
            });

            grammar.AttachAction("statement", (branch, recurse) =>
            {
                ISemanticNode stmt = recurse(branch.GetDescendant(0));

                return(new BranchSemanticNode((int)JsNodeType.Statement, stmt));
            });

            grammar.AttachAction("variableDecl", (branch, recurse) =>
            {
                ISemanticNode first  = recurse(branch.GetDescendant(1, 0));
                ISemanticNode[] rest = branch.GetDescendant(2)
                                       .Elements
                                       .Select(n => recurse(n.GetDescendant(1, 0)))
                                       .ToArray();

                return(new BranchSemanticNode((int)JsNodeType.Variable, first, rest));
            });

            grammar.AttachAction("localAssignment", (branch, recurse) =>
            {
                ISemanticNode lvalue = recurse(branch.GetDescendant(0));
                ISemanticNode expr2  = recurse(branch.GetDescendant(2));

                return(new BranchSemanticNode((int)JsNodeType.Assignment, lvalue, expr2));
            });

            grammar.AttachAction("propertyAssignment", RuleActions.PropertyAssignment);

            grammar.AttachAction("propertyReference", RuleActions.CompositeExpression);

            grammar.AttachAction("argList", (branch, recurse) =>
            {
                BranchParseNode args = branch.GetDescendant(1);

                if (args.Elements.Count == 0)
                {
                    return(new BranchSemanticNode((int)JsNodeType.ArgumentList, branch.StartIndex, new ISemanticNode[0]));
                }

                ISemanticNode first  = recurse(args.GetDescendant(0));
                ISemanticNode[] rest = args
                                       .GetDescendant(1)
                                       .Elements
                                       .Select(n => recurse(n.GetDescendant(1)))
                                       .ToArray();

                return(new BranchSemanticNode((int)JsNodeType.ArgumentList, branch.StartIndex, new[] { first }.Concat(rest)));
            });

            grammar.AttachAction("dotRef", (branch, recurse) =>
            {
                ISemanticNode ident = recurse(branch.GetDescendant(1));

                return(new BranchSemanticNode((int)JsNodeType.DotReference, ident));
            });

            grammar.AttachAction("key", (branch, recurse) =>
            {
                ISemanticNode key = recurse(branch.GetDescendant(1));

                return(new BranchSemanticNode((int)JsNodeType.KeyReference, key));
            });

            grammar.AttachAction("functionCall", RuleActions.FunctionCall);

            grammar.AttachAction("constructor", RuleActions.Constructor);

            grammar.AttachAction("expressionFragment", RuleActions.Unwrap);

            grammar.AttachAction("object", (branch, recurse) =>
            {
                BranchParseNode firstNode = branch.GetDescendant(1, 0);

                if (firstNode == null)
                {
                    return(new BranchSemanticNode((int)JsNodeType.Object, branch.StartIndex, new ISemanticNode[0]));
                }

                ISemanticNode first  = recurse(firstNode);
                ISemanticNode[] rest = branch.GetDescendant(1, 1)
                                       .Elements
                                       .Select(n => recurse(n.GetDescendant(1)))
                                       .ToArray();

                return(new BranchSemanticNode((int)JsNodeType.Object, branch.StartIndex, first, rest));
            });

            grammar.AttachAction("propertyDef", (branch, recurse) =>
            {
                ISemanticNode ident = recurse(branch.GetDescendant(0));
                ISemanticNode value = recurse(branch.GetDescendant(2));

                return(new BranchSemanticNode((int)JsNodeType.PropertyDefinition, ident, value));
            });

            grammar.AttachAction("anonFunction", (branch, recurse) =>
            {
                ISemanticNode paramList = recurse(branch.GetDescendant(1));
                ISemanticNode body      = recurse(branch.GetDescendant(2));

                return(new BranchSemanticNode((int)JsNodeType.AnonymousFunction, paramList, body));
            });

            grammar.AttachAction("namedFunction", (branch, recurse) =>
            {
                ISemanticNode name      = recurse(branch.GetDescendant(1));
                ISemanticNode paramList = recurse(branch.GetDescendant(2));
                ISemanticNode body      = recurse(branch.GetDescendant(3));

                return(new BranchSemanticNode((int)JsNodeType.NamedFunction, paramList, body));
            });

            grammar.AttachAction("paramList", (branch, recurse) =>
            {
                ISemanticNode first  = recurse(branch.GetDescendant(1, 0));
                ISemanticNode[] rest = branch.GetDescendant(1, 1)
                                       .Elements
                                       .Select(n => recurse(n.GetDescendant(1)))
                                       .ToArray();

                return(new BranchSemanticNode((int)JsNodeType.ParameterList, first, rest));
            });

            grammar.AttachAction("block", (branch, recurse) =>
            {
                ISemanticNode[] stmts = branch.GetDescendant(1)
                                        .Elements
                                        .Select(recurse)
                                        .ToArray();

                return(new BranchSemanticNode((int)JsNodeType.Block, branch.StartIndex, stmts));
            });

            grammar.AttachAction("bitwise", (branch, recurse) =>
            {
                ISemanticNode left  = recurse(branch.GetDescendant(0));
                ISemanticNode right = recurse(branch.GetDescendant(2));

                return(new BranchSemanticNode((int)JsNodeType.Bitwise, left, right));
            });

            grammar.AttachAction("bitNegation", (branch, recurse) =>
            {
                ISemanticNode operand = recurse(branch.GetDescendant(1));

                return(new BranchSemanticNode((int)JsNodeType.BitwiseNegation, operand));
            });

            grammar.AttachAction("logic", (branch, recurse) =>
            {
                ISemanticNode left  = recurse(branch.GetDescendant(0));
                ISemanticNode right = recurse(branch.GetDescendant(2));

                return(new BranchSemanticNode((int)JsNodeType.Logic, left, right));
            });

            grammar.AttachAction("logicNegation", (branch, recurse) =>
            {
                ISemanticNode operand = recurse(branch.GetDescendant(1));

                return(new BranchSemanticNode((int)JsNodeType.LogicNegation, operand));
            });

            grammar.AttachAction("math", (branch, recurse) =>
            {
                ISemanticNode left  = recurse(branch.GetDescendant(0));
                ISemanticNode right = recurse(branch.GetDescendant(2));

                return(new BranchSemanticNode((int)JsNodeType.Math, left, right));
            });

            grammar.AttachAction("unaryMath", (branch, recurse) =>
            {
                ISemanticNode operand = recurse(branch.GetDescendant(1));

                return(new BranchSemanticNode((int)JsNodeType.UnaryMath, operand));
            });

            grammar.AttachAction("paren", (branch, recurse) =>
            {
                ISemanticNode operand = recurse(branch.GetDescendant(1));

                return(new BranchSemanticNode((int)JsNodeType.Parenthetical, operand));
            });

            grammar.AttachAction("validIdent", (branch, recurse) =>
            {
                branch = branch.GetDescendant(1);

                var ident      = branch.Leaf.MatchedText;
                var startIndex = branch.Leaf.StartIndex;

                return(new LeafSemanticNode((int)JsNodeType.Identifier, startIndex, ident));
            });

            grammar.AttachAction("doubleString", (branch, recurse) =>
            {
                var text = branch.Leaf.MatchedText;
                text     = text
                           .Substring(1, text.Length - 2)
                           .Replace(@"\\", @"\")
                           .Replace(@"\""", @"""");
                var startIndex = branch.Leaf.StartIndex;

                return(new LeafSemanticNode((int)JsNodeType.String, startIndex, text));
            });

            grammar.AttachAction("singleString", (branch, recurse) =>
            {
                var text = branch.Leaf.MatchedText;
                text     = text
                           .Substring(1, text.Length - 2)
                           .Replace(@"\\", @"\")
                           .Replace(@"\'", @"'");
                var startIndex = branch.Leaf.StartIndex;

                return(new LeafSemanticNode((int)JsNodeType.String, startIndex, text));
            });

            grammar.AttachAction("string", RuleActions.Unwrap);

            grammar.AttachAction("regex", (branch, recurse) =>
            {
                var pattern = branch.Leaf.MatchedText;
                pattern     = pattern
                              .Substring(1, pattern.Length - 2)
                              .Replace(@"\\", @"\")
                              .Replace(@"\/", @"/");
                var startIndex = branch.Leaf.StartIndex;

                return(new LeafSemanticNode((int)JsNodeType.RegularExpression, startIndex, pattern));
            });

            grammar.AttachAction("number", (branch, recurse) =>
            {
                var number     = branch.Leaf.MatchedText;
                var startIndex = branch.Leaf.StartIndex;

                return(new LeafSemanticNode((int)JsNodeType.Number, startIndex, number));
            });

            grammar.AttachAction("expr0", RuleActions.Unwrap);
            grammar.AttachAction("expr1", RuleActions.Unwrap);
            grammar.AttachAction("expr2", RuleActions.Unwrap);
            grammar.AttachAction("expr3", RuleActions.Unwrap);
            grammar.AttachAction("assignment", RuleActions.Unwrap);

            return(grammar);
        }
Exemple #30
0
 internal static ISemanticNode Whitespace(BranchParseNode node, Func <BranchParseNode, ISemanticNode> recurse)
 {
     return(null);
 }