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); }
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)); } }
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)); }
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)); }
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)); }
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 })); }
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)); }
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)); }
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)); }
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)); }
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 })); }
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); }
public ISemanticNode Parse(string input) { if (!IsLocked) { throw new Exception(); } BranchParseNode parseTree = ParseSyntax(input); ISemanticNode semanticTree = ParseSemantics(parseTree); return(semanticTree); }
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); }
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(); } }
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()); } }
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)); } }
internal static ISemanticNode Group(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse) => new BranchSemanticNode((int)EbnfNodeType.Group, recurse(branch.GetDescendant(1)));
internal static ISemanticNode LineComment(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse) { return(null); }
internal static ISemanticNode Whitespace(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse) => null;
internal static ISemanticNode Constructor(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse) { ISemanticNode funCall = recurse(branch.GetDescendant(1)); return(new BranchSemanticNode((int)JsNodeType.Constructor, funCall)); }
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)); }); }
private static ISemanticNode CompositeExpression(ISemanticNode first, BranchParseNode fragments, Func <BranchParseNode, ISemanticNode> recurse) { List <ISemanticNode> rest = ExpressionFragments(fragments, recurse); return(CompositeExpression(first, rest)); }
internal static ISemanticNode Unwrap(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse) => recurse(branch.GetDescendant(0));
internal static ISemanticNode Group(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse) { var group = recurse(branch.GetDescendant(1)); return(new BranchSemanticNode((int)EbnfNodeType.Group, group)); }
internal static ISemanticNode Not(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse) { var not = recurse(branch.GetDescendant(1)); return(new BranchSemanticNode((int)EbnfNodeType.Not, not)); }
internal static ISemanticNode Optional(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse) { var opt = recurse(branch.GetDescendant(1)); return(new BranchSemanticNode((int)EbnfNodeType.Optional, opt)); }
internal static ISemanticNode Repeat(BranchParseNode branch, Func <BranchParseNode, ISemanticNode> recurse) { var repeat = recurse(branch.GetDescendant(1)); return(new BranchSemanticNode((int)EbnfNodeType.Repeat, repeat)); }
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); }
internal static ISemanticNode Whitespace(BranchParseNode node, Func <BranchParseNode, ISemanticNode> recurse) { return(null); }