2013-12-07 23 views
0

在其他更具體,沒有問題的,我有以下詞法規則:保持十六進制數字,而只有文本AF獨立

[a-zA-Z][a-zA-Z0-9]+ { 
    yylval.string = strdup(yytext); 
    return FILENAME; 
} 

/* 32-bit numbers */ 
[a-fA-F0-9]{1,8} { 
    std::stringstream ssh; 
    ssh << std::hex << yytext; 
    ssh >> yylval.u32.hex; 
    std::stringstream ssd; 
    ssd << std::dec << yytext; 
    ssd >> yylval.u32.dec; 
    return NUMBER; 
} 

「一把手」的規則已經是雜牌,因爲我可以在我正在執行的語法中,不區分HEX和DEC基數。十六進制數字沒有前綴,它都是基於上下文的。所以在解析器規則中,我只是從結構中選擇我知道需要的數字。

看來我需要進一步擴展它。我有一個「文件名」類型,它只是任何字母數字字符串,至少以字母字符開始,後跟任何字母數字(如上定義)。問題是,像fffff這樣的文件名導致不正確的解析。這感覺就像這是對號和文件名組合成類似ALPHANUMERIC,在那裏我會做這樣的事情,我可以照顧的唯一途徑:

/* 32-bit numbers, strings, sigh... */ 
[a-zA-Z0-9]{1,8} { 
    std::stringstream ssh; 
    ssh << std::hex << yytext; 
    ssh >> yylval.alphanumeric.hex; 
    std::stringstream ssd; 
    ssd << std::dec << yytext; 
    ssd >> yylval.alphanumeric.dec; 
    yylval.alphanumeric.string = strdup(yytext); 
    return ALPHANUMERIC; 
} 

然後,我將有一個在解析器有點聰明並檢查一個初始的alpha,並使用正確的struct字段。

這是一個常見的折衷?這感覺不對,而且越寬鬆,我肯定我會創造漏洞,我沒有測試它會在哪裏失敗或捕獲太多。我最終會將大量字符串(如「hello」)轉換爲不必要的值hexdec

+0

如果十六進制數'face'在某些情況下,這將不僅會混淆你的詞法分析器曖昧。它也會混淆你的用戶。 (另外,將文件名限制爲字母開頭的字母數字似乎是不自私的,但我想你對其他文件名有其他語法。) – rici

回答

1

的常用方法是使用不同的伸縮規則對不同類別的令牌時可能出現的,與A_OR_B令牌的事情,可能是兩個不同的東西:

[0-9]+ { 
    yylval.u32 = strtol(yytext, 0, 10); 
    return NUMBER; } 
[a-fA-F][a-fA-F0-9]* { 
    yylval.string = strdup(yytext); 
    return NUMBER_OR_NAME; } 
[a-fA-F0-9]+ { 
    yylval.u32 = strtol(yytext, 0, 16); 
    return NUMBER; } 
[a-zA-Z][a-zA-Z0-9]* { 
    yylval.string = strdup(yytext); 
    return NAME; } 

的Flex將始終嘗試匹配最長匹配,但是當多個模式匹配相同的長度時,它將匹配第一個模式。

在你的解析器,你使用像規則:

name: NAME | NUMBER_OR_NAME ; 

number: NUMBER | NUMBER_OR_NAME { $$ = strtol($1, 0, 16); free($1); } ; 
+0

謝謝,這將清理的事情。我會試一試。 –

0

我會去分辨十六進制和十六進制像十六進制和decnumber,但是純粹是基於上下文的,你將不得不定義一些像文件名一樣的約束將不得不使用至少9個字符,因爲這不會是一個有效的32位十六進制。

+0

如果我定義了語法,我需要引用字符串,十六進制數字前綴爲0x等等......但不幸的是,這不是我的語法來定義。 :) –