主题:[原创]基于.net的好用的语法分析辅助工具:GOLD Parser(3)--兼请教高手
自学就是痛苦啊,都不知道构造出的是不是抽象语法树。
首先,前面两篇给出的语法文件里有错误,不能连续进行let in end的声明。(主要是tiger的语法太怪,虎书上在第3章又没有给出完整的yacc文件,让读者自己添加。这样好处是让读者自己动手,但是后果是自己添加的很多名称以及过程与后续章节不同,会有一点麻烦。)
修改如下:
<Decs> ::= <Dec> <Decs>
| 'let' <Decs> 'in' <Stm> 'end' [color=FF0000]<Decs>[/color]
|
既在'end'后再添加<Decs>,这样便可以连续声明let in end。
Gold Parser中的语法树构造,主要是在终止符和非终止符读取时进行用户Object的构造。
private Object CreateObject(Token token)
{
if (token is TerminalToken)
return CreateObjectFromTerminal((TerminalToken)token);
else
return CreateObjectFromNonterminal((NonterminalToken)token);
}
终止符的读取主要是int和string的读取(应该还包括一切转义字符,特殊字符,我的程序里只处理了前两种),非终止符是在Reduce时处理。比如下面的代码演示了在进行Decs相关的Reduce时的处理,创建了新类Decs。
case (int)RuleConstants.RULE_DECS :
//<Decs> ::= <Dec> <Decs>
//todo: Create a new object using the stored tokens.
return new Decs((Dec)token.Tokens[0].UserObject,(Decs)token.Tokens[1].UserObject);
case (int)RuleConstants.RULE_DECS_LET_IN_END :
//<Decs> ::= let <Decs> in <Stm> end <Decs>
//todo: Create a new object using the stored tokens.
return new Decs((Decs)token.Tokens[1].UserObject, (Statement)token.Tokens[3].UserObject,(Decs)token.Tokens[5].UserObject);
所以写个编译器真的是比较麻烦。至少每个非终止符都要进行处理。
C++代码中用enum及union比较方便,可惜C#中没有union,只有用类代替了。比如Dec类代码如下:
public class Dec
{
public VarDec vardec;
public Dec(VarDec vardec)
{
this.vardec=vardec;
}
public FunctionDec functiondec;
public Dec(FunctionDec functiondec)
{
this.functiondec=functiondec;
}
public FieldDec fielddec;
public Dec(FieldDec fielddec)
{
this.fielddec=fielddec;
}
public TypeDec typedec;
public Dec(TypeDec typedec)
{
this.typedec=typedec;
}
};
怎么查看生成的抽象语法树呢?我是在<Start> ::= <nl Opt> <Decs>这一句时,返回Decs,也不知道对不对。下面来对比下具体语法树和抽象语法树的区别。
在Gold Parser中输入如下tiger代码(很简单,但是足以后续进行构造符号表和进行类型、范围检查。我实在是懒得实现tiger的所有语法了。:()
let
var N := 8
in try(0)
end
let
var M := 80
in try(1)
end
GoldParser的语法测试功能显示的树结构如下:
[IMG]http://bbs.pediy.com/upload/2006/4/image/1.jpg_816.jpg[/IMG]
而在VS2005中通过调试功能显示的树状结构如下(其中很多值为null的结点是浪费的,但是没折,没有union。)
[IMG]http://bbs.pediy.com/upload/2006/4/image/2.jpg_554.jpg[/IMG]
两者最主要的区别:前者在节点中包含“let”“int”“end”“var”“:=”等符号,但是它们对最终运算是无用的。抽象语法树的叶节点只包含非终止符,将其它的所有信息包含在了内部节点中。
现在感觉难度越来越大了,下一章会构造符号表,并进行最简单的类型检查。代码就不上传了,会误导人的。(btw:非常希望得到熟悉编译原理的朋友给我指点!)
首先,前面两篇给出的语法文件里有错误,不能连续进行let in end的声明。(主要是tiger的语法太怪,虎书上在第3章又没有给出完整的yacc文件,让读者自己添加。这样好处是让读者自己动手,但是后果是自己添加的很多名称以及过程与后续章节不同,会有一点麻烦。)
修改如下:
<Decs> ::= <Dec> <Decs>
| 'let' <Decs> 'in' <Stm> 'end' [color=FF0000]<Decs>[/color]
|
既在'end'后再添加<Decs>,这样便可以连续声明let in end。
Gold Parser中的语法树构造,主要是在终止符和非终止符读取时进行用户Object的构造。
private Object CreateObject(Token token)
{
if (token is TerminalToken)
return CreateObjectFromTerminal((TerminalToken)token);
else
return CreateObjectFromNonterminal((NonterminalToken)token);
}
终止符的读取主要是int和string的读取(应该还包括一切转义字符,特殊字符,我的程序里只处理了前两种),非终止符是在Reduce时处理。比如下面的代码演示了在进行Decs相关的Reduce时的处理,创建了新类Decs。
case (int)RuleConstants.RULE_DECS :
//<Decs> ::= <Dec> <Decs>
//todo: Create a new object using the stored tokens.
return new Decs((Dec)token.Tokens[0].UserObject,(Decs)token.Tokens[1].UserObject);
case (int)RuleConstants.RULE_DECS_LET_IN_END :
//<Decs> ::= let <Decs> in <Stm> end <Decs>
//todo: Create a new object using the stored tokens.
return new Decs((Decs)token.Tokens[1].UserObject, (Statement)token.Tokens[3].UserObject,(Decs)token.Tokens[5].UserObject);
所以写个编译器真的是比较麻烦。至少每个非终止符都要进行处理。
C++代码中用enum及union比较方便,可惜C#中没有union,只有用类代替了。比如Dec类代码如下:
public class Dec
{
public VarDec vardec;
public Dec(VarDec vardec)
{
this.vardec=vardec;
}
public FunctionDec functiondec;
public Dec(FunctionDec functiondec)
{
this.functiondec=functiondec;
}
public FieldDec fielddec;
public Dec(FieldDec fielddec)
{
this.fielddec=fielddec;
}
public TypeDec typedec;
public Dec(TypeDec typedec)
{
this.typedec=typedec;
}
};
怎么查看生成的抽象语法树呢?我是在<Start> ::= <nl Opt> <Decs>这一句时,返回Decs,也不知道对不对。下面来对比下具体语法树和抽象语法树的区别。
在Gold Parser中输入如下tiger代码(很简单,但是足以后续进行构造符号表和进行类型、范围检查。我实在是懒得实现tiger的所有语法了。:()
let
var N := 8
in try(0)
end
let
var M := 80
in try(1)
end
GoldParser的语法测试功能显示的树结构如下:
[IMG]http://bbs.pediy.com/upload/2006/4/image/1.jpg_816.jpg[/IMG]
而在VS2005中通过调试功能显示的树状结构如下(其中很多值为null的结点是浪费的,但是没折,没有union。)
[IMG]http://bbs.pediy.com/upload/2006/4/image/2.jpg_554.jpg[/IMG]
两者最主要的区别:前者在节点中包含“let”“int”“end”“var”“:=”等符号,但是它们对最终运算是无用的。抽象语法树的叶节点只包含非终止符,将其它的所有信息包含在了内部节点中。
现在感觉难度越来越大了,下一章会构造符号表,并进行最简单的类型检查。代码就不上传了,会误导人的。(btw:非常希望得到熟悉编译原理的朋友给我指点!)