Lex中的连锁令牌

时间:2015-10-14 05:13:17

标签: lex

我正在为其他C语法中的C预处理器编写词法分析器。作为其中的一部分,我必须在#include中识别文件名。我遇到的问题是识别文件名。文件名包含两部分:basename和extension。可以使用" IDENTIFIER"来识别基本名称。词法的正则表达式;所以可以"。"将它们分开。

" IDENTIFIER"有一个单独的正则表达式。而对于"。"。对于文件名,我正在考虑编写另一个正则表达式,它基本上是" IDENTIFIER","和#34;的串联。和" h"。我的问题是,如果像我所描述的那样为文件名写一个正则表达式;它将如何处理。考虑到已有一个单独的令牌规则;将不是识别文件名,而是识别3个令牌(IDENTIFIER,DOT和IDENTIFIER),还是识别文件名?

1 个答案:

答案 0 :(得分: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);
                         }  
相关问题