簡體   English   中英

在Bison錯誤后如何跳過一行中的其余令牌

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM