public static Parser GetParser() { // XML chars var charLt = Char['<']; var charGt = Char['>']; var charSlash = Char['/']; // int expr chars var charPlus = Char['+']; var charMinus = Char['-']; var charMult = Char['*']; var charDiv = Char['/']; var charLPar = Char['(']; var charRPar = Char[')']; var charDigit = Char['0', '9']; var charAddtOper = CharSet[charPlus + charMinus]; var charMultOper = CharSet[charMult + charDiv]; var charOper = CharSet[charAddtOper + charMultOper]; // int operator priorities int priorityInfixAddt = 10; int priorityInfixMult = 20; int priorityPrefixAddt = 30; // token: number var exprNum = new Token(IdNum, charDigit.Repeat() & !LookAhead[SkipWs & (charDigit | charLPar)]) { new Rule <int> { Capture(value => int.Parse(value)) } }; // token: plus (infix or prefix) var exprPlus = new Token(IdExpr, charPlus & !LookAhead[SkipWs & (charOper | charRPar | charLt)]) { new PrefixRule <int, int>( priority: priorityPrefixAddt, select: t => (t.IsFirst || t.LookBehind().First().Is(IdExprLPar)) && t.LookAhead().First().Is(IdNum, IdExprLPar)) { Create((int x) => + x) }, new InfixRule <int, int, int>(priority: priorityInfixAddt) { Create((int x, int y) => x + y) } }; // token: minus (infix or prefix) var exprMinus = new Token(IdExpr, charMinus & !LookAhead[SkipWs & (charOper | charRPar | charLt)]) { new PrefixRule <int, int>( priority: priorityPrefixAddt, select: t => (t.IsFirst || t.LookBehind().First().Is(IdExprLPar)) && t.LookAhead().First().Is(IdNum, IdExprLPar)) { Create((int x) => - x) }, new InfixRule <int, int, int>(priority: priorityInfixAddt) { Create((int x, int y) => x - y) } }; // token: multiplication var exprMult = new Token(IdExpr, charMult & !LookAhead[SkipWs & (charOper | charRPar | charLt)]) { new InfixRule <int, int, int>(priority: priorityInfixMult) { Create((int x, int y) => x * y) } }; // token: division var exprDiv = new Token(IdExpr, charDiv & !LookAhead[SkipWs & (charOper | charRPar | charLt)]) { new InfixRule <int, int, int>(priority: priorityInfixMult) { Create((int x, int y) => x / y) } }; // token: left parenthesis var exprLPar = new Token(IdExprLPar, charLPar & !LookAhead[SkipWs & (charRPar | charLt)]) { new LeftDelimiterRule <string>() { Capture(value => value) } }; // token: right parenthesis var exprRPar = new Token(IdExpr, charRPar & !LookAhead[SkipWs & (charDigit | charLPar)]) { new RightDelimiterRule <string, int, int> { Create((string lPar, int n) => n) } }; // int expression var numExpr = (exprNum | exprPlus | exprMinus | exprMult | exprDiv | exprLPar | exprRPar).Repeat(); // token: tag value containing int expression var tagValue = new Token(IdTagValue, SkipWs_Disable, LookAhead[SkipWs & CharSet[~(CharSpace + charLt)]] & numExpr & LookAhead[charLt]) { new Rule <string> { Create(IdNum, (int expr) => "=" + expr.ToString()), Create(IdExpr, (int expr) => "=" + expr.ToString()) } }; // token: tag open (only tag name, no attribs) var tagBegin = new Token(IdTagBegin, charLt & new Token(IdTagName, CharWord.Repeat()) & charGt) { new LeftDelimiterRule <string> { Create(IdTagName, (string tagName) => tagName) } }; // token: tag close var tagEnd = new Token(IdTag, charLt & charSlash & new Token(IdTagName, CharWord.Repeat()) & LookAhead[charGt]) { new RightDelimiterRule <string, string, string> { Create(IdTagName, (string name) => name), Error( (string tag, string tagName) => tagName != tag, (tag, tagName) => string.Format("Expected {0}, found {1}", tagName, tag)), Create( (string tag, string value) => value.StartsWith("="), (tag, value) => tag + value), Create( (string tag, string value) => !value.StartsWith("="), (tag, value) => tag + ":{" + value + "}") } }; // token: tag sequence var tagConcat = new Token(IdTag, charGt & LookAhead[SkipWs & charLt & ~charSlash]) { new InfixRule <string, string, string>( pre: t => t.LeftOperand.Is(IdTag) && t.RightOperand.Is(IdTag)) { Create((string leftTag, string rightTag) => leftTag + "," + rightTag) } }; // XML containing int expressions var xmlInt = StartOfLine & (tagBegin | tagValue | tagEnd & (tagConcat | charGt)).Repeat() & SkipWs & EndOfFile; // generate RegExpr parser return(xmlInt.Render(CharSpace.Repeat())); }
public Word(CharWord c) { Title = c.Title; Text = c.Text; }
bool Initialize() { var charEsc = Char['\\']; var charQuot = Char['\"']; var stmtBegin = new Token("//#"); var codeBegin = new Token("=>"); var stmtType = new Token(TokenId.StatementType, CharWord.Repeat(atLeast: 1)); var quotedArgValue = new Token(TokenId.StatementArgValue, SkipWs_Disable, (charEsc & charQuot | CharSet[~(charQuot + CharCr + CharLf)]).Repeat(atLeast: 1)); var quotedArg = new Token(TokenId.StatementArg, charQuot & quotedArgValue & charQuot.Optional()) { new Rule <string> { Create(TokenId.StatementArgValue, (string value) => value) } }; var unquotedArg = new Token(TokenId.StatementArg, !LookAhead[charQuot] & CharSet[~CharSpace].Repeat(atLeast: 1)); var stmtArg = !LookAhead[codeBegin] & (quotedArg | unquotedArg); var stmtCodeValue = new Token(TokenId.StatementCodeValue, CharSet[~(CharCr + CharLf)].Repeat()); var stmtCode = new Token(TokenId.StatementCode, codeBegin & stmtCodeValue) { new Rule <string> { Create(TokenId.StatementCodeValue, (string value) => value) } }; var stmtLine = StartOfLine & new Token(TokenId.Statement, SkipWs_Disable, // '//#' <type> [ <arg>... ] [ '=>' <code> ] stmtBegin & stmtType & stmtArg.Repeat() & stmtCode.Optional()) { new Rule <Statement> { Capture(value => new Statement { Args = new List <string>() }), Update(TokenId.StatementType, (Statement s, string typeStr) => { StatementType type; if (Enum.TryParse(typeStr, ignoreCase: true, result: out type)) { s.Type = type; } else { s.Type = StatementType.Unknown; } }), Update(TokenId.StatementArg, (Statement s, string arg) => s.Args.Add(arg)), Update(TokenId.StatementCode, (Statement s, string code) => s.Code = code) } } & SkipWs& (LineBreak | EndOfFile); var codeLine = StartOfLine & new Token(TokenId.Code, SkipWs_Disable, !LookAhead[stmtBegin & stmtType] & CharSet[~(CharCr + CharLf)].Repeat()) { new Rule <CodeLine> { Capture((string value) => new CodeLine(value)) } } &(LineBreak | EndOfFile); TokenMacro = new Token(TokenId.Macro, SkipWs_Disable, (stmtLine | codeLine).Repeat() & EndOfFile) { new Rule <MacroLines> { Update(TokenId.Statement, (MacroLines m, Statement s) => m.Add(s)), Update(TokenId.Code, (MacroLines m, CodeLine l) => m.Add(l)) } }; var parser = TokenMacro.Render(defaultTokenWs: CharHorizSpace.Repeat()); if (parser == null) { return(false); } MacroTextParser = parser; return(true); }