public void SingleToken() { var grammar = $@" abc = ""abc""; root = abc; "; var settings = new ParserSettings { Algorithm = Parser.Algorithm.LL, NestingType = Parser.NestingType.Stack, Unit = Parser.Unit.Character, }; Parser parser = parserGen.SpawnParser(settings, grammar); parser.AttachAction("abc", (branch, recurse) => { var value = branch.Leaf.MatchedText; var startIndex = branch.Leaf.StartIndex; return(new LeafSemanticNode(0, startIndex, value)); }); parser.AttachAction("root", (branch, recurse) => { return(recurse(branch.GetDescendant(0))); }); parser.Lock(); ISemanticNode result = parser.Parse("abc"); }
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 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)); }); }