2015-10-14 80 views
0

我正在爲其他C語法中的C預處理器編寫一個詞法分析器。作爲其中的一部分,我必須在#include中標識文件名。我遇到的問題是識別文件名。文件名包含兩部分:基本名稱和擴展名。可以使用詞法分析器的「IDENTIFIER」正則表達式來識別基本名稱;所以可以是「。」將它們分開。Lex中的級聯令牌

有一個「IDENTIFIER」和「。」單獨的正則表達式。對於文件名,我正在考慮編寫另一個基本上是「IDENTIFIER」,「。」的串聯的正則表達式。和「h」。我的問題是,如果我正如我所描述的那樣爲文件名寫一個正則表達式;它將如何被處理。考慮到已經有單獨的令牌的規則的事實;而不是識別文件名稱,它將識別3個令牌(IDENTIFIER,DOT和IDENTIFIER),還是會識別文件名?

回答

1

就我所見,沒有任何理由讓預處理器詞法分析器在include指令中查看文件名作爲除了不透明序列的字符以外的其他任何文件。確切的名稱與預處理器無關;它可能不包含任何擴展名或多個.(前提是操作系統允許這樣做,現在這些操作系統最多);它可能包含特殊字符,如斜槓;它可能是一個數字;等等。

此外,角括號和引號的處理在include指令的參數內是特異的。因此,處理include指令的常用方法是使用上下文敏感模式,例如使用(f)lex start conditions

由於換行符在所有的預處理指令中也被特別處理,您通常也需要一個上下文相關的模式。

使用flex語法的粗略草圖。很多細節被遺漏。

%x PP_DIRECT PP_ARG PP_INCLUDE 
%% 

^[[:blank:]]*"#" { BEGIN(PP_DIRECT); } 
<PP_DIRECT>include { BEGIN(PP_INCLUDE); return T_INCLUDE; } 
    /* You might want to recognize other include directives as 
    * specific keyword tokens. In particular, the scanner needs 
    * to be aware of conditionals, since it might have to put itself 
    * into a mode where it skips to the matching #endif 
    */ 
<PP_DIRECT>[[:alpha:]]+ { BEGIN(PP_ARG); /* ... */ } 
    /* Normally newlines are not returned to the parser, but here we do. */ 
<PP_ARG>\n   { BEGIN(INITIAL); return '\n'; } 
    /* This should actually be done in a previous step */ 
<PP_ARG>\\\n  /* IGNORE */ 
<PP_INCLUDE>["][^"]*["] { yytext[yyleng-1] = 0; 
          do_include(yytext+1); 
          /* Really, should check that only whitespace follows */ 
          BEGIN(PP_ARG); 
         } 
<PP_INCLUDE>[<][^>]*[>] { yytext[yyleng-1] = 0; 
          do_system_include(yytext+1); 
          BEGIN(PP_ARG); 
         } 
+0

謝謝。我不知道上下文敏感的語法,以前的在線搜索是徒勞的。非常感謝 – Sharad

+0

@sharad:您可能還想查看[多個緩衝區上的flex手冊部分](http://flex.sourceforge.net/manual/Multiple-Input-Buffers.html#Multiple-Input-Buffers),其中有使用緩衝區堆棧實現「包含」功能的示例代碼。 – rici