2013-04-15 59 views
5

我在編譯器構建過程中,我目前的任務是爲我們正在實現的語言編寫詞法分析器。我無法弄清楚如何滿足詞法分析器必須識別串聯令牌的要求。也就是說,令牌不會被空格分開。例如:字符串39if應該被識別爲數字39和關鍵字if。同時,詞法分析器遇到無效輸入時也必須使用exit(1)如何讓lex/flex識別不被空格分隔的令牌?

代碼的簡化版本我有:

%{ 
#include <stdio.h> 
%} 

%option main warn debug 

%% 

if  | 
then | 
else printf("keyword: %s\n", yytext); 

[[:digit:]]+ printf("number: %s\n", yytext); 

[[:alpha:]][[:alnum:]]*  printf("identifier: %s\n", yytext); 

[[:space:]]+ // skip whitespace 
[[:^space:]]+ { printf("ERROR: %s\n", yytext); exit(1); } 

%% 

當我運行這個(或我的完整版),並通過它的輸入39if,錯誤匹配規則時,輸出爲ERROR: 39if,當我想它是:

number: 39 
keyword: if 

(即相同的,如果我進入39 if作爲輸入。)

Going by the manual,我有一個預感,原因是錯誤規則匹配比數字和關鍵字規則更長的可能輸入,flex會更喜歡它。這就是說,我不知道如何解決這種情況。編寫一個明確的正則表達式似乎是不可行的,它將拒絕所有非錯誤輸入,並且我不知道爲了處理詞法分析器錯誤還需要編寫一個「全部抓取」規則。

更新:我想我可以只作包羅萬象的規則是. { exit(1); },但我想獲得一些更好的調試輸出比「我糊塗了第1行」。

+0

a)您是否運行過簡化版本? b)它做了什麼是錯誤的? –

+0

@IraBaxter對不起,似乎我忘了在最後一段中的猜測中迷失了我的測試用例。答案是** a)**是;和** b)**報告詞法分析器錯誤,而不是兩個標記。 (我也將它們添加到問題中。) – millimoose

+1

啊。好的,是的,你的「^空間」規則會吃掉任何非空間序列,從而消耗「39if」。祕密:避免正則表達式重疊的規則,除非較長的規則首先安全。在你的情況下,我會用(我不是一個lex-pert)替換:^ space:那是「不是數字,不是字母,也不是空格」。 ... –

回答

4

你很對,你應該只匹配一個「任何」字符作爲後備。獲得解析所在行信息的「標準」方式是使用--bison-bridge選項,但這可能有點痛苦,特別是如果您不使用bison。還有一堆其他的方式 - 看手冊指定自己的I/O功能的方式,例如, - 但各地恕我直言,最簡單的方法是使用一個啓動條件:

%x LEXING_ERROR 
%% 
// all your rules; the following *must* be at the end 
.     { BEGIN(LEXING_ERROR); yyless(1); } 
<LEXING_ERROR>.+ { fprintf(stderr, 
          "Invalid character '%c' found at line %d," 
          " just before '%s'\n", 
          *yytext, yylineno, yytext+1); 
        exit(1); 
        } 

注意:確保你已經忽略了規則中的空格。模式.+匹配任何數字,但至少包含一個非換行符,或者換句話說,直到當前行的末尾(它將強制flex讀取那麼遠,這應該不成問題)。 yyless(n)通過n字符備份讀指針,因此在.規則匹配後,它將重新生成該字符(希望)生成一個半合理的錯誤消息。 (如果你的輸入是多字節,或者有奇怪的控制字符,那麼你就可以寫更仔細的代碼,這對你來說並不合理,如果錯誤在行尾,那也可能是不合理的。你可能也需要寫一個更仔細的正則表達式它獲取更多的情況下,甚至可能在這裏限制的前鋒字符讀的選項很多數。)

查找start conditions在Flex手冊,瞭解更多信息關於%xBEGIN

+0

我讀到了開始條件,但不能真正把這些碎片放在一起,謝謝! – millimoose

+0

將yytext [0]返回到解析器中更簡單很多。規則,並讓解析器的錯誤恢復處理它。不需要啓動狀態。這也消除了單個特殊字符的所有規則。 – EJP

+0

@EJP:OP明確指出,其中一個要求是詞法分析器遇到無效輸入時必須「退出(1)」。沒有任何跡象表明存在解析器,有或沒有錯誤恢復。 – rici