2010-11-24 20 views
4

我想分析一些C++代碼,並以此爲指導我一直期待在這裏的C的lex/yacc的定義:http://www.lysator.liu.se/c/ANSI-C-grammar-l.htmlhttp://www.lysator.liu.se/c/ANSI-C-grammar-y.html解析C/C++源碼:在lex/yacc中如何指定標記邊界/交互?

我明白令牌本身的規範,但沒有它們如何相互作用。例如。可以讓一個運算符(如=)直接跟隨一個標識符而不介入空格(即「foo =」),但不能在數字常數後面緊跟一個標識符(即123foo)。但是,我不認爲有這樣的規則代表。

我在想什麼?...或者這個lex/yacc在接受錯誤時太自由了。

+3

你讓我在「我想解析一些C++代碼」。 – 2010-11-24 09:21:27

回答

3

詞法分析器將字符流轉換爲標記流(我認爲這就是您通過標記指定的含義)。該語法指定了哪些令牌序列可以接受。因此,你不會看到有什麼是不允許的;你只看到什麼是允許的。那有意義嗎?

編輯

如果點是讓詞法分析器從順序區分序列「123foo」「123富」的一種方法是增加一個規範「123foo」。另一種方法是將空間視爲重要的。

EDIT2

可以從詞法分析器或語法產生或編譯器的後期階段「檢測的」誤差的語法(想到的,比方說,類型錯誤,這仍然是「語法錯誤」) 。我認爲,整個編譯過程的哪一部分檢測哪個錯誤主要是設計問題(因爲它影響錯誤消息的質量)。在給定的例子中,通過一個標記到一個無效的標記來取締「123foo」可能更有意義,而不是依賴於一個數字文字後跟一個標識符的不存在的生產(至少,這是GCC)。

0

實際上,每種令牌類型的詞法規則都是貪婪的。例如,字符序列foo=不能被解釋爲單個標識符,因爲標識符不包含符號。另一方面,123abc實際上是一個數值常量,雖然格式不正確,因爲數字常量可以以一系列用於表示數字常量類型的字母字符結尾。

+0

嚴格來說,`123abc`是無效的C++ 03,但有效的C++ 0x,因爲C++ 0x具有用戶定義的文字功能(http://en.wikipedia.org/wiki/C%2B%2B0x #User-defined_literals) – SingleNegationElimination 2010-11-24 07:18:34

+0

我認爲在數字之後只允許有限的alpha,即。 [uUlL] ...你是說規範比這更普遍嗎? – Greencpp 2010-11-24 07:18:59

+0

我敢肯定,鏈接到lex規範實際上將`123foo`標記爲一個常量,後跟一個標識符,而不是單個(格式不正確)的常量。 – 2010-11-24 07:21:25

1

詞法分析器與123foo很好,並將它分成兩個標記。

  • 一個整數常數
  • 和標識符。

但試着找到允許這兩個標記並排坐在一起的語法部分。因此我敢打賭,詞法分析器在看到這兩個令牌時會產生一個錯誤。

注意詞法分析器不關心空格(除非你明確地告訴它空格)。在這種情況下,它只是拋出空白遠:

[ \t\v\n\f]  { count(); } // Throw away white space without looking. 

只是爲了檢查這是我建:

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

編輯後的文件湖L若要停止在編譯器抱怨未申報的功能:

#include "y.tab.h" 

// Add the following lines 
int yywrap(); 
void count(); 
void comment(); 
void count(); 
int check_type(); 
// Done adding lines 

%} 

創建以下文件:main.c中:

#include <stdio.h> 

extern int yylex(); 

int main() 
{ 
    int x; 
    while((x = yylex()) != 0) 
    { 
     fprintf(stdout, "Token(%d)\n", x); 
    } 
} 

構建:

$ bison -d y.y 
y.y: conflicts: 1 shift/reduce 
$ flex l.l 
$ gcc main.c lex.yy.c 
$ ./a.out 
123foo 
123Token(259) 
fooToken(258) 

是它,它一分爲二令牌。

0

您將無法使用lex和yacc解析C++,因爲它是一個模糊的語法。你需要一個更強大的方法,比如GLR或者一些在運行時修改詞法分析器的黑客解決方案(這是目前大多數C++解析器都在做的)。

看看Elsa/Elkhound。

相關問題