2015-11-26 29 views
2

我需要什麼:如何在Flex(詞法分析器)中定義數字格式?

可接受>1234 & 12.34

錯誤(不接受)>12.34.56

Scanner.L:

Input : 
1234 12.34 12.34.65 

Output : 
Number Decimal_Number  Decimal_Number Dot Number 

 ... 
%% 

[0-9]+    printf("Number "); 
[0-9]+"."[0-9]+  printf("Decimal_Number "); 
"."     printf("Dot "): 

%% 
     ... 

編譯&運行後

如何打印Error而不是Decimal_Number Dot Number(或者只是忽略它)?

是否可以在&之前將定義爲分隔符之後的數字?

+1

你真的需要嗎?無論如何,「12.34.56」(大概)會成爲語法錯誤,所以它不是一個詞法錯誤真的很重要嗎? – sepp2k

回答

2

通常認爲在您的解析器中檢測錯誤(如12.34.56)通常更好,而不是掃描儀。但是也有一種觀點認爲,通過從詞彙上檢測錯誤,你可以產生更好的錯誤信息。

如果你想這樣做,你可以使用兩種模式;第一個檢測只有正確的數字,第二個檢測到一個更大的字符串集合,包括所有錯誤的字符串(但不是任何可能合法的字符串)。這依賴於(f)lex的匹配行爲:它總是接受最長匹配,並且如果最長的標記符合兩個或更多個規則,則它使用第一個匹配規則。

例如,假設您想自己接受點爲'.',數字爲NUMBER標記,並且在具有多個點的數字字符串上產生錯誤。你可以用三條規則做到這一點:

/* If the token is just a dot, match it here */ 
\.        { return '.'; } 
    /* Match integers without decimal points */ 
[[:digit:]]+     { return INTEGER; } 
    /* If the token is a number including a decimal point, 
    * match it here. This pattern will also match just '.', 
    * but the previous rules will be preferred.) */ 
[[:digit:]]*\.[[:digit:]]*  { return FLOAT; } 
    /* This rule matches any sequence of dots and digits. 
    * That will also match single dots and correct numbers, but 
    * again, the previous rules are preferred. */ 
[.[:digit:]]+     { /* signal error */ 
           return BADNUMBER; } 

你需要非常小心的解決上述問題。例如,過去的規則將匹配.....,這可能是有效的令牌(或.令牌甚至有效序列。)

假設,例如,你的語言許可證「範圍內」這樣的表達式4 .. 17(指列表從4到17的整數,或一些這樣的)。您的用戶可能希望4..17被接受爲一個範圍的表達,但上面會產生一個BADNUMBER錯誤,即使你在一開始添加規則

".."       { return RANGE; } 

,因爲4..將在之前的點匹配BADNUMBER掃描。

爲了避免錯誤警報,我們需要修改BADNUMBER規則以避免匹配包含兩個(或多個)連續點的字符串。而且我們還需要確保4..17不會因爲4.後跟.17而變得易混淆。 (這第二個問題可以通過堅持.沒有開始沒有結束一個數字令牌,但可能會激怒一些用戶是可以避免的。)

所以,我們開始與實際點標記:

"."       { return '.'; } 
".."       { return RANGE; } 
"..."       { return ELLIPSIS; } 

爲了避免匹配一個數字後跟..,我們可以使用flex的尾隨上下文運算符。在這裏,我們認識到一個.終止僅在字符串後面跟着一個非.其他的東西了一些數字序列:

[[:digit:]]+     { return INTEGER; } 
    /* Change * to + so that we don't do numbers ending with . */ 
[[:digit:]]*(\.[[:digit:]]+)? { return FLOAT; } 
    /* Numbers which end with dot not followed by dot */ 
[[:digit:]]+\./[^.]   { return FLOAT; } 

現在我們需要修復的錯誤的規則。首先,我們將其限制爲識別每個點後跟一個數字的字符串。然後,類似於上述情況,我們做匹配,那裏是一個句點後面沒有其他點的情況下:

[[:digit:]]*(\.[[:digit:]]+)+ { return BADNUMBER; } 
[[:digit:]]*(\.[[:digit:]]+)+\./[^.] { return BADNUMBER; } 
+0

謝謝,那很有幫助。 –

+0

感謝您的詳細解釋。 –

1

這不是詞法分析器的責任,而是分析器(yacc或bison)的責任。如果定義.爲有效的符號則是毫不奇怪,

12.34.56 

標記化作爲

Decimal_Number Dot Number 

的一點是,解析器將不會接受令牌的該序列這麼一個規則該錯誤將在稍後提出。空白空間通常被忽略,因此強制數字之間的空格是沒有意義的,尤其是在可能有12.34+56.78的上下文中,由於它沒有空白空間而不會被標記爲Decimal_Number Binary_Operator Decimal_Number

+0

所以沒有辦法做我剛剛在Flex中說的話?也許刪除'''定義什麼的? –

+0

你的問題是一個XY問題,如果你真的想要你可以儘可能多地強制使用內部令牌的空格(例如'[0-9] +「。」[0-9] +「」'),但它是錯誤的並且不應該被考慮。 – Jack

+1

不,不要理會那個空白的東西。有沒有辦法返回錯誤或只是忽略Flex中的12.34.56格式? –

0

您可以檢查我的程序來處理你的問題。但是,當您嘗試使用lex時,您應該知道,只要它匹配任何情況,它就可以工作。 現在更改爲類似如下:

%% 

[0-9]+    {printf("Number ");} 
[0-9]+[.][0-9]*[.]+[0-9|.]*  {printf("error ");} 
[0-9]+[.][0-9]+  {printf("Decimal_Number ");} 
%% 

現在的程序工作,只要你想。

Input : 
1234 12.34 12.34.65 

Output : 
Number Decimal_Number  Error 
+0

這是可行的嗎?@ MMD_93 –

+0

在'[0-9 |。]'中,'|'只是另一個字符,所以它會匹配字符'|'。 – rici

+1

@Md Shibbir Hossen - 正是我想要的,非常感謝你 我加了'「。」 {printf(「Dot」);}',炒鍋沒有任何問題。 –

相關問題