2009-10-31 118 views
0

我正在为着色引擎编写一个编译器,并且每一次都正常工作,直到我到达语句解析部分。使用野牛解析元素列表

我使用的类定义的抽象语法树做所有工作(为了简化类型检查和中间代码生成)..所以我有一个祖先类ASTNode和所有降序类,如ASTFloatASTExpressionASTIdentifier等上..

.y文件,我能够建立在共同的方式AST:

nexp: 
T_LPAR nexp T_RPAR { $$ = $2; } 
| nexp OP_PLUS nexp { $$ = new ASTBExpression('+', (ASTExpression*)$1, (ASTExpression*)$3); } 
| nexp OP_MINUS nexp { $$ = new ASTBExpression('-', (ASTExpression*)$1, (ASTExpression*)$3); } 
| nexp OP_TIMES nexp { $$ = new ASTBExpression('*', (ASTExpression*)$1, (ASTExpression*)$3); } 

和它的作品相当不错,但后来我试着生成报表Ø f范围(例如如果声明的主体):我已经使用了一个ASTStatements类,它有一个ASTNode*的列表,必须由解析器填充每个遇到的语句。

因此,办法是与此类似:

statements: 
statement { if ($$ == null) $$ = new ASTStatements(); ((ASTStatements*)$$)->addStatement($1); } statements { $$->generateASM(); } 
; 

的问题是,该项目应每个语句块只初始化一次,但我不知道该怎么做。使用if ($$ == null)是我尝试过的一种黑客攻击,但它不起作用,因为yylval可以包含任何到此为止的内容。

哪个是使用Bison处理这种情况的正常/最好的方法?

+0

你有%type statement_if etc etc? – 2009-11-01 16:26:20

+0

当然,我必须解决将ASTStatements *转化为具有左部分(ASTStatement *)和右部分(ASTStatements *)的类的问题。我其实把名单变成了退化的树.. – Jack 2009-11-01 23:21:39

回答

1

我通过产生不是语句列表,但退化的树来解决这个问题。所以涉及到的类对象是:

ASTStatements 
{ 
    ASTStatements *m_next; 
    ASTStatement *m_statement; 

    .... 

    public: 
     ASTStatements(ASTStatement *statement) // used for last one 
     ASTStatements(ASTStatement *stat, ASTStatements *next) // used with a next one 
} 

使用规则.y通过以下方式:

statements: /* empty */ { $$ = null; } 
| statements statement { if ($1 == null) $$ = new ASTStatements($2); else $$ = new ASTStatements($2, (ASTStatements*)$1); } 

事实上这是左递归,使报表中不弄乱尽快降低叠加。我遵循同样的方法来处理与我的语言有关的任何其他种类的“符号列表”。

+0

我真的很喜欢退化的树的想法。 – Vortico 2014-11-11 03:17:30

1

尝试增强语法如下所示:

statements: statement { $$ = new ASTStatements(); 
         ((ASTStatements*)$$)->addStatement($1); }  
| statements statement { ((ASTStatements*)$$)->addStatement($2); } 

不知道这会有所帮助。

1

对于yacc更喜欢左递归规则有多种原因,因为您可以尽可能早地减少输入中的一件事。

在任何情况下,当你这样做,你就可以使用这样的模式:

statements:    { $$ = new ... } 
    | statements statement { /* now $1 and $2 do just what you want */ } 
    ;