示例#1
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));
        }
示例#2
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));
        }
示例#3
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 }));
        }
示例#4
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));
            }
        }
示例#5
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));
        }
示例#6
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));
        }
示例#7
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 }));
        }
示例#8
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());
            }
        }
示例#9
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);
        }
示例#10
0
 internal static ISemanticNode Unwrap(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse) => recurse(branch.GetDescendant(0));
示例#11
0
 internal static ISemanticNode Group(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse) => new BranchSemanticNode((int)EbnfNodeType.Group, recurse(branch.GetDescendant(1)));
示例#12
0
        internal static ISemanticNode Group(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse)
        {
            var group = recurse(branch.GetDescendant(1));

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

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

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

            return(new BranchSemanticNode((int)EbnfNodeType.Repeat, repeat));
        }
示例#16
0
        internal static ISemanticNode Constructor(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse)
        {
            ISemanticNode funCall = recurse(branch.GetDescendant(1));

            return(new BranchSemanticNode((int)JsNodeType.Constructor, funCall));
        }