![](/img/trans.png)
[英]How to recognise single new line tokens in a flex/bison based parser and ignore multiple new lines?
[英]How to skip the rest of the tokens in a line after an error in Bison
我正在為使用Flex和Bison來確定語句是否有效的作業編寫應用程序。 在語句中檢測到錯誤后,我想打印一條錯誤消息並移至下一行以查看下一條語句,但是我嘗試的所有操作均不起作用。
Bison在線研究,擁有一個內置的錯誤令牌,可用於錯誤處理。 通過使用錯誤'\\ n'{yyerrok;},我應該能夠實現所需的功能,但是它不起作用。
我的Flex代碼:
%{
#include <cstdio>
#include <iostream>
using namespace std;
#include "exp.tab.h" // to get the token types from Bison
%}
%%
--.* ;
[a-zA-Z][a-zA-Z0-9]* {yylval.print = strdup(yytext); return ID;}
;\s* {return EOL;}
[-+*/%] {yylval.print = strdup(yytext); return OP;}
= {return EQU;}
\( {return OPEN;}
\) {return CLOSE;}
[0-9] ;
\n ;
\r ;
. ;
%%
我的Bison代幣和規則:
%union{
char *print;
}
%token EQU
%token <print> ID
%token EOL
%token <print> OP
%token OPEN
%token CLOSE
%%
lines: line
| lines line
;
line: ass {cout << " VALID" << endl;}
| exp {cout << " VALID" << endl;}
| error '\n' {yyerrok;}
;
ass: id EQU {cout << " ="; } exp EOL {cout << ";";}
;
exp: term
| exp op term
;
term: id
| OPEN {cout << "(";} exp op term CLOSE {cout << ")";}
;
id: ID {cout << $1; }
op: OP {cout << $1; }
%%
我的yyerror()僅顯示“錯誤”。
我的解析輸入:
-- Good (valid) statements:
first = one1 + two2 - three3 / four4 ;
second = one1 * (two2 * three3) ;
one1 * i8766e98e + bignum
second = (one1 * two2) * three3 ;
third = ONE + twenty - three3 ;
third = old * thirty2 / b567 ;
-- Bad (invalid) statements:
first = = one1 + two2 - three3 / four4 ;
first = one1 + - two2 - three3 / four4 ;
first = one1 + two2 - three3 / four4
first = one1 + two2 ? three3 / four4 ;
second = 4 + ( one1 * two2 ) * ( three3 + four4 ;
third = one1 + 24 - three3 ;
one1 +- delta
sixty6 / min = fourth ;
我希望輸出會顯示錯誤,然后移至下一行
first =one1+two2-three3/four4; VALID
second =one1*(two2*three3); VALID
one1*i8766e98e+bignum VALID
second =(one1*two2)*three3; VALID
third =ONE+twenty-three3; VALID
third =old*thirty2/b567; VALID
first = Error
first = one1 + Error
first = one1 + two2 - three3 / four4 Error
first = one1 + two2 Error
.
.
.
但是當我運行它時,它只會在第一次錯誤打印時停止
first =one1+two2-three3/four4; VALID
second =one1*(two2*three3); VALID
one1*i8766e98e+bignum VALID
second =(one1*two2)*three3; VALID
third =ONE+twenty-three3; VALID
third =old*thirty2/b567; VALID
first = Error
任何幫助將不勝感激,但主要是我想知道為什么錯誤'\\ n'規則不起作用以及如何解決該錯誤。
由於您的詞法分析器忽略\\n
,告訴語法分析器跳過標記,直到看到換行符,才會導致其跳過文件的其余部分。
但是,您可以(幾乎)通過使詞法分析器識別換行符來實現此目的,但僅限於在錯誤恢復期間。 (簽入\\n
然后忽略該操作或將其發送。)
但這有時會產生奇怪的結果,因為產生錯誤的令牌可能在下一行,在這種情況下,在檢測到錯誤之前,換行符已被忽略。 例如,這里的問題是缺少分號:
a = 1
while (a > 0) {
…
但是,只有在讀取while
才會檢測到該錯誤。 (如果下一個標記是+
,則分析應繼續。)因此,跳到該行的末尾意味着在第三行繼續分析,從而引入了不平衡的括號。
即使這樣,這仍可能是一個有趣的開始。
使用'\\n'
無效,因為您的詞法分析器從不返回'\\n'
,因此令牌流中將永遠不會有任何'\\n'
令牌。 基本上,如果詞法分析器忽略某些字符,則不能以任何方式在解析器中使用它們,包括用於錯誤恢復。
因此,您的兩個選擇是停止忽略換行符(這可能是個壞主意,因為您必須在語法中允許換行的地方提到它們),或使用其他令牌進行錯誤恢復。 跳過所有內容直到下一個分號可能是一個不錯的選擇(盡管由於並非所有行都以分號結尾,所以仍然無法產生預期的輸出)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.