2009-10-31 111 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 */ } 
    ;