Flex词法分析器防止token分裂的方法?

问题描述 投票:0回答:1

目前正在使用 Flex 扫描定义 C 子集的语法。这是 .l 文件。

 /*definitions*/
%{
    #include <stdio.h>
    int yylex(void);
%}
/*rules*/
%%
"int"                   {printf("TYPE_INT %s\n",yytext);}
"float"                 {printf("TYPE_FLOAT %s\n",yytext);}
"char"                  {printf("TYPE_CHAR %s\n",yytext);}
"bool"                  {printf("TYPE_BOOL %s\n",yytext);}
"while"                 {printf("WHILE %s\n",yytext);}
"do"                    {printf("DO %s\n",yytext);}
"for"                   {printf("FOR %s\n",yytext);}
"printf"                {printf("PRINTF %s\n",yytext);}
"scanf"                 {printf("SCANF %s\n",yytext);}
"if"                    {printf("IF %s\n",yytext);}
"elif"                  {printf("ELIF %s\n",yytext);}
"else if"               {printf("ELSE_IF %s\n",yytext);}
"else"                  {printf("ELSE %s\n",yytext);}
"true"                  {printf("TRUE %s\n",yytext);}
"false"                 {printf("FALSE %s\n",yytext);}
"void"                  {printf("VOID %s\n",yytext);}
"main"                  {printf("MAIN %s\n",yytext);}
"return"                {printf("RETURN %s\n",yytext);}
[a-zA-Z_][a-zA-Z0-9]*   {printf("IDENTIFIER %s\n",yytext);}
[-+]?(([1-9][0-9]*)|0)  {printf("INTEGER %s\n",yytext);}
[-+]?[0-9]+\.[0-9]+      {printf("FLOAT %s\n",yytext);}
\"[^\"\n]*\"            {printf("STRING %s\n",yytext);}
","                     {printf("COMMA %s\n",yytext);}
";"                     {printf("SEMICOLON %s\n",yytext);}
"{"                     {printf("LEFT_BRACE %s\n",yytext);}
"}"                     {printf("RIGHT_BRACE %s\n",yytext);}
"("                     {printf("LEFT_PAREN %s\n",yytext);}
")"                     {printf("RIGHT_PAREN %s\n",yytext);}
"["                     {printf("LEFT_BRACKET %s\n",yytext);}
"]"                     {printf("RIGHT_BRACKET %s\n",yytext);}
"-"                     {printf("MINUS %s\n",yytext);}
"+"                     {printf("PLUS %s\n",yytext);}
"*"                     {printf("MULTIPLY %s\n",yytext);}
"/"                     {printf("DIVIDE %s\n",yytext);}
"\\"                    {printf("BACKSLASH %s\n",yytext);}
"%"                     {printf("MODULUS %s\n",yytext);}
"=="                    {printf("EQUALS %s\n",yytext);}
"!="                    {printf("NOT_EQUALS %s\n",yytext);}
"<"                     {printf("LESS_THAN %s\n",yytext);}
">"                     {printf("GREATER_THAN %s\n",yytext);}
"<="                    {printf("LESS_THAN_OR_EQUAL %s\n",yytext);}
">="                    {printf("GREATER_THAN_OR_EQUAL %s\n",yytext);}
"="                     {printf("ASSIGN %s\n",yytext);}
"&&"                    {printf("LOGICAL_AND %s\n",yytext);}
"||"                    {printf("LOGICAL_OR %s\n",yytext);}
"!"                     {printf("LOGICAL_NOT %s\n",yytext);}
[" "|\t|\n|\f|\v]       {printf("WHITESPACE\n");}
.                       {printf("UNRECOGNIZED_CHARACTER %s\n",yytext);}
%%

/*for when we use multipe input files*/
int yywrap(void){
    return 1;
}

/*main driver function that takes */
int main(int argc, char *argv[]){
    if(argc<2){
        printf("Usage: %s <input_file_name>\n",argv[0]);
        return 1;
    }
    FILE *fp = fopen(argv[1], "r");
    if(fp == NULL){
        printf("Error opening input file.\n");
        return 1;
    }
    yyin = fp;
    yylex();
    fclose(fp);
    return 0;
}

我遇到的问题是某些输入,例如

90.s3
232a3
。 flex 不是像上一条语法规则中那样得到 'UNRECOGNIZED CHARACTER',而是将它们分开。
232a3
变成

INTEGER 232
IDENTIFIER a3

90.s3
变成

INTEGER 90
UNRECOGNIZED_CHARACTER .
IDENTIFIER s3

我应该如何阻止这种情况发生?

c parsing grammar bison flex-lexer
1个回答
1
投票

我应该如何阻止这种情况发生?

有几种选择。其中,

  • 你可以使用带有尾随上下文的模式。例如,此

    INTEGER
    模式仅在紧跟文件末尾或既不是小数点也不是大写或小写字母的字符时识别整数标记:

    [-+]?(([1-9][0-9]*)|0)/([^.A-Za-z]|<<EOF>>)
    
  • 或者你可以玩有开始条件的游戏.

  • 但是你最好的选择可能是添加一个模式来匹配不需要的标记并标记错误。例子:

    [a-zA-Z_][a-zA-Z0-9]* { /* IDENTIFIER */ }
    ([1-9][0-9]*)|0       { /* INTEGER */ }
    [0-9]+[.][0-9]*       { /* FLOAT version 1 */ }
    [.][0-9]+             { /* FLOAT version 2 */ }
    
        /* Used only if it affords a longer match than any of the above: */
    [0-9.][0-9]*[a-zA-Z_.][0-9a-zA-Z_.]*  { /* ERROR */ }
    

    请注意,此示例从数字模式中省略了前导

    +
    -
    。它们将与您现有的
    +
    -
    运算符模式相匹配,这正是它们在 C 中的作用。

    还请注意,如果您支持

    .
    作为 C 中的成员选择运算符,则您需要付出更多努力——可能不止一种错误模式。

© www.soinside.com 2019 - 2024. All rights reserved.