本文介绍了C# Parsing Library,即一个模仿Boost.Spirit的LL解析器库,可以在C#中模拟ENBF文法定义。
C# Parsing Library 是一个LL解析器发生结构,能够在C#中仿照ENBF文法界说。规划思路来自于Boost.Spirit,一个C++解析器结构。
一)C# Parsing Library:Parser 基本概念
a) 文法界说举例:P ::= a b C#用法:P = a + b 序列
b) 文法界说举例:P ::= a | b C#用法:P = a | b 挑选
c) 文法界说举例:P ::= a * C#用法:P = a.Star 0..n次匹配
d) 文法界说举例:P ::= a + C#用法:P = a.Plus 1..n次匹配
e) 文法界说举例:P ::= a ? C#用法:P = a.Opt 0..1次匹配
P为Parser类型,是解析器的笼统基类,它界说了一个笼统的Parse办法:
- boolParse(Scannerscanner);
Scanner类首要存储一个字符串输入,及一个光标方位,光标跟着解析的进行向前移动。
比如:一个整数解析器, 界说为一个可选的符号后边跟若干数字:
- Parsersigned=(Parser.Lit('+')|'-').Opt;
- Parserp=(signed+Parser.DigitChar.Plus).Lexeme;
- boolsuccess=p.Parse(newScanner("-123"));
其间,Lit表明常量,Lexeme表明为词法剖析,即不疏忽空格。
二)C# Parsing Library:ParserRef
一个常用的四则运算表达式文法:
- group::='('expression')'
- factor::=integer|group
- term::=factor(('*'factor)|('/'factor))*
- expression::=term(('+'term)|('-'term))*
用下面的办法是过错的:
- Parsergroup;//Parser是笼统类,无法new
- Parserfactor;
- factor=Parser.Int|group;//过错!group没有初始化!
可是运用ParserRef 就能够了:
- ParserRefgroup=newParserRef();
- ParserReffactor=newParserRef();
- factor.Parser=Parser.Int|group;
完好的界说如下:
- ParserRefgroup=newParserRef();
- ParserReffactor=newParserRef();
- ParserRefterm=newParserRef();
- ParserRefexpression=newParserRef();
- group.Parser='('+expression+')';
- factor.Parser=Parser.Int
- |group;
- term.Parser=factor+
- (('*'+factor)
- |('/'+factor)
- ).Star;
- expression.Parser=term+
- (('+'+term)
- |('-'+term)
- ).Star;
三)C# Parsing Library:Rule和语义支撑
和 spirit相同,经过对[]的重载,完成对语义的支撑。一般的parser的Action类型为Action< string>, 即 void Action(string s)。s为该parser匹配的内容。假如要支撑上下文, 就要运用Rule了. Rule带有一个模板参数T,表明特点类型。Action类型为Func< T,T,T> 即 T Action(T lhs, T rhs)。关于以下的简略规矩:
- LeftRule:=RightRule[Action(lhs,rhs)]
其语义为:LeftRule.Attribute = Action(LeftRule.Attribute, RightRule.Attribute).
上面的四则运算示例可修正如下:
- Grammar<int>grammar=newGrammar<int>();
- Rule<int>group=newRule<int>(grammar);
- Rule<int>factor=newRule<int>(grammar);
- Rule<int>term=newRule<int>(grammar);
- Rule<int>expression=newRule<int>(grammar);
- Rule<int>start=newRule<int>(grammar);
- grammar.Start=start;
- group.Parser='('+expression[(lhs,rhs)=>rhs]+')';
- factor.Parser=Parser.IntValue[v=>grammar.Ret(v)]//(#1)
- |group[(lhs,rhs)=>rhs];
- term.Parser=factor[(lhs,rhs)=>rhs]+
- (('*'+factor[(lhs,rhs)=>lhs*rhs])
- |('/'+factor[(lhs,rhs)=>lhs/rhs])
- ).Star;
- expression.Parser=term[(lhs,rhs)=>rhs]+
- (('+'+term[(lhs,rhs)=>lhs+rhs])
- |('-'+term[(lhs,rhs)=>lhs-rhs])
- ).Star;
- start.Parser=expression[(lhs,rhs)=>rhs]+Parser.End;
- intresult;
- boolsuccess=grammar.Parse("10+20+30*(40+50)",outresult);
- if(success)Console.WriteLine(result);
阐明:
关于一般的Parser,语义动作中并不能有返回值,由于它不知道特点的切当类型,要支撑特点,有必要运用 Grammar.Ret().
在我自己完成曾经,大致搜了一下,在CodeProject上有一个相似的完成,也是仿照Boost.Spirit,不过它的语义处理选用C#的事情机制,用起来极不便利。这个项目我刚刚把它发布在google code 上面,项目主页:http://code.google.com/p/csParsing/。当然它还远远不够老练。
【修改引荐】
- 简略易懂的C#.NET多线程使用
- C#注册表是怎么操作的
- C#扩展办法:对扩展进行分组办理
- Visual C# 3.0新特性的总结
- 网站安全性:C#防SQL注入代码的完成办法
知优网 » 介绍C# Parsing Library(介绍卖婬罪最新量刑标准)