那么今天要说的就是如何用C#q行高效的全文分析。我们知道全用LALR的话不仅隑ּ发而且代码难调试难试难修改,因此q了。最好调试的代码是什么呢Q显然是递归下降法写出来的。其实代码本来没多少层,所以递归下降最多也递归十几层,也不?x)太多,ȝ来说性能q是可以接受的。但是每来一个语aq一ơ递归下降q是很惨的。好?net自带C#~译器,我们可以使用parser combinator来生成。关于什么是combinatorQ可以参?a style="TEXT-DECORATION: underline" href="http://www.shnenglu.com/vczh/archive/2010/09/02/125621.html" target=_blank>q里。至于什么是parser combinatorQ我曄用C++实现了一?/a>?br>
Parser combinator的好处是我们可以在C#里面把文法直接表辑և来,然后变成一个语法分析器。不q直接执行combinatorQ性能?x)受到很大媄响。怎么h能把性能降低到跟手写的差不多呢?.NETl了我们三种武器Q分别是CodeDom、Emit和Linq Expression。我比较們于CodeDomQCodeDom可以让我们写C#来拼Z颗巨大的代表一个C#E序的语法树(wi)Q然后用自带?net~译器去~译成dll或者cs文g。因此这个C#的parser combinator的目的就是要让我们用最妙的语法来拼出目标语言的文法,最后根据文发来产生一份C#语法分析器的代码。我们可以每ơ运行的时候都~译Z个内存的dllQ或者直接生一个cs文g然后拖进我们的工E?br>
我目前可能会(x)采取前一U方法:(x)也就是用parser combinator来生文法树(wi)Q然后我提供一个函数来把它转换成一份对应的C#递归下降语法分析器的代码Q跟yacc很像哈,虽然他用的是LALRQ,最后编译它。因此只需要在IDEW一ơ打开某个语言的代码文件的时候编译出q个语法分析器,在IDEx之前都可以用了?br>
那语法分析器要生什么语法树(wi)呢?q个q是要我们自己来解决的。不q我采取了一U比较偷懒的Ҏ(gu)。我先写了一个语法树(wi)的基c(vlpp.codeplex.com后Candidate\CodeBoxControl\CodeBoxControl\CodeProvider\*.csQ,然后只要你给我一个这样子的虚c:(x)
1 public abstract class ExpressionNode : CodeNode
2 {
3 }
4
5 public abstract class NumberNode : ExpressionNode
6 {
7 public int Number { get; set; }
8 }
9
10 public abstract class AddNode : ExpressionNode
11 {
12 public abstract ExpressionNode Left { get; set; }
13 public abstract ExpressionNode Right { get; set; }
14 }
那么你就可以用CodeNode.Create<AddNode>()或者CodeNode.Create<NumberNode>()来获得相应的实现了。至于CodeNode的声明是q样的:(x)
1 public abstract class CodeNode
2 {
3 public virtual TextPosition Start { get; protected internal set; }
4 public virtual TextPosition End { get; protected internal set; }
5 public virtual CodeNode ParentNode { get; protected internal set; }
6 public virtual CodeNodeCollection Nodes { get; private set; }
7 public virtual ICodeScope OwningScope;
8 public virtual ICodeScope Scope;
9
10 public CodeNode();
11
12 public static T Create<T>()
13 where T : CodeNode;
14 }
因此当你往AddNode.Left赋值的时候,也就是等于在写CodeNode.Nodes["Left"]Q这是Create<T>所提供的实C。当然写q去了之后ParentNode和Scope属性就?x)立L效了。这U方法还是可以剩下你不少旉的?br>
今天p到这里了Q然后我得d发那个C#的parser combinatorq且惛_一个单元测试的对策Q这也是一U练?fn)哈Q,然后再l写博客了。不q中U节那一整个星期都要回家办点事情所以估计会(x)暂停?

]]>