2010-08-21 80 views
0

我已經試過這樣的事情在我的野牛文件的printf ...麻煩與野牛規則

ReturnS: RETURN expression {printf(";")} 

...但分號被打印的下一個標記後,過去的這個規則,而不是右後表達方式。這條規則是因爲我們需要將輸入文件轉換爲類似於c的表單,並且原始語言在return語句中的表達式之後不需要分號,但是C的確如此,所以我想我會添加它用printf手動輸出到輸出。這似乎不起作用,因爲分號被添加了,但由於某種原因,當表達式規則返回到ReturnS時,它在下一個標記被解析(ReturnS規則之外)而不是正確之後被添加。

這條規則也導致同樣的結果:

loop_for: FOR var_name COLONEQUALS expression TO {printf("%s<=", $<chartype>2);} expression STEP {printf("%s+=", $<chartype>2);} expression {printf(")\n");} Code ENDFOR 

除了前兩個的printf的不工作的權利(我會發布關於另一個問題),最後的printf實際上是調用後的第一個令牌/文字「準則」 的規則已經被解析,導致像這樣的:

for (i=0; i<=5; i+=1 
a) 
=a+1; 

代替

for (i=0; i<=5; i+=1) 
a=a+1; 

任何想法我做錯了什麼?

回答

1

可能是因爲語法不得不提前一個標記來決定減少你顯示的規則。

當規則減少時,該操作被執行,並且在知道可以/應該減少先前的規則之前,語法必須讀取多一個令牌是非常典型的。

例如,如果一個表達式可以包含一個不確定的添加項的序列,那麼它必須讀取超出上一項的內容才能知道沒有另一個「+」來繼續表達式。


看到的Yacc /鬼語法和Lex/Flex的分析後,一些問題變得明顯,和其他人花了一點點整理。

  • 讓詞法分析器做大部分的打印工作意味着語法不能很好地控制什麼時候出現的內容。分析儀做得太多了。
  • 該分析儀還沒有做足夠的工作 - 使語法過程字符串和數字一次一個字符是可能的,但不必要的努力工作。
  • 如果需要保留註釋,處理註釋非常棘手。在一個普通的C編譯器中,詞法分析器拋出註釋;在這種情況下,評論必須保留。處理這個問題的規則從語法移到了詞法分析器(它導致移位/縮減,並且由於空字符串匹配註釋而減少/減少了衝突)。這可能並不總是最佳的,但在這種情況下它似乎可以正常工作。
  • 當需要一個值時,詞法分析器需要確保它爲yylval返回一個合適的值。
  • 需要在$$中傳播合適值的語法,以確保規則具有必要的信息。大部分關鍵詞不需要價值;像變量名和數字這樣的東西。
  • 語法不得不在適當的地方進行打印。

原型解決方案返回了重大的內存泄漏,因爲它使用strdup()寬鬆並沒有採用free()可言。確保泄漏是固定的 - 可能通過使用char數組而不是YYSTYPE的char指針 - 留給OP。

+0

我明白了。感謝您的迴應。不知道如何解決,但現在至少我有一個線索在哪裏看。 – 2010-08-22 06:35:54

+0

我試過了,但似乎無法解決這個問題。有關如何解決此問題的任何想法? – 2010-08-22 08:10:10

+0

@Leftos:通過電子郵件把我的代碼放下 - 查看我的個人資料。我會看看我能做些什麼。 – 2010-08-22 14:02:12

0

評論並不是一個提供代碼示例的好地方,所以我將提供一個可用的代碼示例,在喬納森(以上回答)對我的代碼做了一些工作之後。所有應有的功勞歸於他,這不是我的。

喬納森並沒有讓FLEX打印任何可識別的部分並讓BISON進行格式化,而是建議FLEX不打印任何東西,只返回到BISON,然後應該處理所有自己打印的問題。

因此,而不是像這樣...


FLEX

"FOR" {printf("for ("); return FOR;} 
"TO" {printf("; "); return TO;} 
"STEP" {printf("; "); return STEP;} 
"ENDFOR" {printf("\n"); printf("}\n"); return ENDFOR;} 
[a-zA-Z]+ {printf("%s",yytext); yylval.strV = yytext; return CHARACTERS;} 
":=" {printf("="); lisnew=0; return COLONEQUALS;} 

BISON

loop_for: FOR var_name {strcpy(myvar, $<strV>2);} COLONEQUALS expression TO {printf("%s<=", myvar);} expression STEP {printf("%s+=", myvar);} expression {printf(")\n");} Code ENDFOR 

...他提出這樣的:


FLEX

[a-zA-Z][a-zA-Z0-9]* { yylval = strdup(yytext); return VARNAME;} 
[1-9][0-9]*|0   { yylval = strdup(yytext); return NUMBER; } 

BISON

loop_for: FOR var_name COLONEQUALS NUMBER TO NUMBER STEP NUMBER 
    { printf("for (%s = %s; %s <= %s; %s += %s)\n", $2, $4, $2, $6, $2, $8); } 
var_name: VARNAME 
+0

Jonathan,如果您想將上述示例添加到您的答案中,我會很樂意刪除我的答案。 – 2010-08-26 13:02:02

+0

此外,如果有人想知道printf中的$ x's以及它們是如何工作的,請參閱SO 3539498. http://stackoverflow.com/questions/3539498/using-x-to-grab-string-from-rule – 2010-08-26 13:03:29