예제 #1
0
        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()));
        }
예제 #2
0
 public Word(CharWord c)
 {
     Title = c.Title;
     Text  = c.Text;
 }
예제 #3
0
        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);
        }