簡體   English   中英

為什么flex / bison中的多行注釋如此回避?

[英]Why are multi-line comments in flex/bison so evasive?

我正在嘗試在我的flex(.l)文件中解析C風格的多行注釋:

%s ML_COMMENT
%%

...

<INITIAL>"/*"                   BEGIN(ML_COMMENT);
<ML_COMMENT>"*/"                BEGIN(INITIAL);  
<ML_COMMENT>[.\n]+              { }

我沒有返回任何令牌,我的語法(.y)也沒有以任何方式處理評論。

當我運行我的可執行文件時,我得到一個解析錯誤:

$ ./a.out
/*
abc 
def
Parse error: parse error
$ echo "/* foo */" | ./a.out
Parse error: parse error

(我的yyerror函數執行printf(“解析錯誤:%s \\ n”),這是冗余錯誤消息的前半部分來自)。

我可以看到為什么第二個示例失敗,因為整個輸入是注釋,並且由於語法忽略了注釋,因此沒有語句。 因此輸入不是有效的程序。 但是在我完成評論之前,第一部分拋出了一個解析錯誤。

同樣令人困惑:

$ ./a.out
/* foo */
a = b;
Parse error: parse error

在這種情況下,注釋在實際有效輸入之前關閉(沒有注釋,解析就好了)。 解析“a”后實際發生失敗,而不是在嘗試解析賦值“a = b;”之后。 如果我在自己的行上輸入“a”,它仍然會拋出錯誤。

鑒於錯誤消息是解析器錯誤而不是掃描程序錯誤,我的.y文件中是否存在一些至關重要的內容? 或者我在掃描器規則中做錯了什么傳播到解析器端?

編輯: Per @Rudi的建議,我打開調試,發現:

$ ./a.out
Starting parse
Entering state 0
Reading a token: /*
foo
Next token is 44 (IDENTIFER)
Shifting token 44 (IDENTIFER), Entering state 4
Reducing via rule 5 (line 130), IDENTIFER  -> identifier
state stack now 0
Entering state 5

我關閉了調試,發現/* foo */ = bar; 確實解析foo = bar; 我正在使用flex 2.5.4; 它沒有給我任何關於我試圖使用的有狀態規則的警告。

以這種方式解析注釋可能會導致錯誤,因為:

  • 您需要為所有lex規則添加條件
  • 如果你還想處理//評論,它會變得更加復雜
  • 你還有風險yacc / bison合並兩條評論,包括介於兩者之間的所有內容

在我的解析器中,我處理這樣的評論。 首先為注釋的開頭定義lex規則,如下所示:

\/\*     {
         if (!SkipComment())
            return(-1);
         }

\/\/     {
         if (!SkipLine())
            return(-1);
         }

然后編寫SkipComment和SkipLine函數。 他們需要消耗所有輸入,直到找到注釋的結尾(這是相當古老的代碼,所以請原諒我有些過時的結構):

bool SkipComment (void)
{
int Key;

Key=!EOF;
while (true)
   {
   if (Key==EOF)
      {
      /* yyerror("Unexpected EOF within comment."); */
      break;
      }
   switch ((char)Key)
      {
      case '*' :
         Key=input();
         if (char)Key=='/') return true;
         else               continue;
         break;
      case '\n' :
         ++LineNr;
         break;
      }
   Key=input();
   }

return false;
}

bool SkipLine (void)
{
int Key;

Key=!EOF;
while (true)
   {
   if (Key==EOF)
      return true;
   switch ((char)Key)
      {
      case '\n' :
         unput('\n');
         return true;
         break;
      }
   Key=input();
   }

return false;
}

我認為您需要將ML_COMMENT啟動條件聲明為獨占啟動條件,因此只有ML_COMMENT規則處於活動狀態。 %x ML_COMMENT而不是%s ML_COMMENT

否則,沒有開始條件的規則也是活動的。

我發現這種C語言語法的描述(實際上只是詞法分析器)非常有用。 我認為它與帕特里克的答案大致相同,但略有不同。

http://www.lysator.liu.se/c/ANSI-C-grammar-l.html

除了%x vs %s的問題,你也有問題了. [.\\n]匹配(僅)一個文字. 而不是“除了換行之外的任何其他角色” . 確實。 你想要一個像這樣的規則

<ML_COMMENT>.|"\n"     { /* do nothing */ }

代替

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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