【问题标题】:Flex/Bison - My regular expression is not matching occurrences of two or more X's, example XXY-1 or XXY-1Flex/Bison - 我的正则表达式不匹配出现的两个或多个 X,例如 XXY-1 或 XXY-1
【发布时间】:2017-11-25 23:16:02
【问题描述】:

我正在使用 flex 和 bison 为一种虚构的编程语言创建解析器。会有有效和无效的变量名。

XXXX XY-1 // valid
XXXXX Z // valid
XXX Y // valid
XXX 5Aet // invalid
XXXX XXAB-Y // invalid

开头的 x 只是指定变量的大小。变量5Aet无效,因为它以数字开头。我已经设法为此匹配一个正则表达式

[\_\-0-9][a-zA-Z][a-zA-Z0-9\-\_]* yylval.string = strdup(yytext);return TERM_INVALID_VARIABLE_NAME;

变量XXAB-Y 无效,因为变量名不能以两个或更多x 字符开头。

我试图为此匹配一个正则表达式,但我没有成功。我尝试了以下表达式的各种组合,但都没有奏效。变量不断匹配为有效。

[X]{2,}[A-Z0-9\-]* yylval.string = strdup(yytext);return TERM_INVALID_VARIABLE_NAME;

[X]{2,0}[\_\-0-9][a-zA-Z][a-zA-Z0-9\-\_]* yylval.string = strdup(yytext);return TERM_INVALID_VARIABLE_NAME;

lexer.l sn-p

[\t ]+ // ignore whitespaces

\n // Ignore new line

[\"][^"]*[\"] yylval.string = strdup(yytext); return TERM_STR;

";" return TERM_SEPARATOR;

"." return TERM_FULLSTOP;

[0-9]+ yylval.integer = atoi(yytext); return TERM_INT;

XX[A-Z0-9-]* yylval.string = strdup(yytext);return TERM_INVALID_VARIABLE_NAME;

[\_\-0-9]+[a-zA-Z][a-zA-Z0-9\-\_]* yylval.string = strdup(yytext);return TERM_INVALID_VARIABLE_NAME;

[A-Z][A-Z0-9\-]* yylval.string = strdup(yytext); return TERM_VARIABLE_NAME;

[X]+ yylval.integer = yyleng; return TERM_SIZE;

. return TERM_INVALID_TOKEN;

parser.y sn-p

program:
    /* empty */ | 
    begin middle_declarations body grammar_s end {
        printf("\nParsing complete\n");
        exit(0);
    };

begin:
    TERM_BEGINING TERM_FULLSTOP;

body:
    TERM_BODY TERM_FULLSTOP;

end:
    TERM_END TERM_FULLSTOP;

middle_declarations:
    /* empty */ |
    //Left recursive to allow for many declearations
    middle_declarations declaration TERM_FULLSTOP;

declaration:
    TERM_SIZE TERM_VARIABLE_NAME {
        createVar($1, $2);
    }
    |
    TERM_SIZE TERM_INVALID_VARIABLE_NAME {
        printInvalidVarName($2);
    };

grammar_s:
    /* empty */ |
    grammar_s grammar TERM_FULLSTOP;

grammar:
    add | move | print | input;

add:
    TERM_ADD TERM_INT TERM_TO TERM_VARIABLE_NAME {
        addIntToVar($2, $4);
    }
    |
    TERM_ADD TERM_VARIABLE_NAME TERM_TO TERM_VARIABLE_NAME {
        addVarToVar($2, $4);
    }

    ;

move:
    TERM_MOVE TERM_VARIABLE_NAME TERM_TO TERM_VARIABLE_NAME {
        moveVarToVar($2, $4);
    }
    |
    TERM_MOVE TERM_INT TERM_TO TERM_VARIABLE_NAME {
        moveIntToVar($2, $4);
    }

    ;

print:
    /* empty */ |
    TERM_PRINT rest_of_print {
        printf("\n");
    };

rest_of_print:
    /* empty */ |
    rest_of_print other_print;

other_print:

    TERM_VARIABLE_NAME {
        printVarValue($1);
    }
    |
    TERM_SEPARATOR {
        // do nothing
    }
    |
    TERM_STR {
        printf("%s", $1);
    }

    ;

input:
    // Fullstop declares grammar
    TERM_INPUT other_input;

other_input:

    /* empty */ |
    // Input var1
    TERM_VARIABLE_NAME {
        inputValues($1);
    }
    |
    // Can be input var1; var2;...varN
    other_input TERM_SEPARATOR TERM_VARIABLE_NAME {
        inputValues($2);
    }
    ;

调试输出:

Starting parse
Entering state 0
Reading a token: Next token is token TERM_BEGINING (1.1: )
Shifting token TERM_BEGINING (1.1: )
Entering state 1
Reading a token: Next token is token TERM_FULLSTOP (1.1: )
Shifting token TERM_FULLSTOP (1.1: )
Entering state 4
Reducing stack by rule 3 (line 123):
   $1 = token TERM_BEGINING (1.1: )
   $2 = token TERM_FULLSTOP (1.1: )
-> $$ = nterm begin (1.1: )
Stack now 0
Entering state 3
Reducing stack by rule 6 (line 131):
-> $$ = nterm middle_declarations (1.1: )
Stack now 0 3
Entering state 6
Reading a token: Next token is token TERM_SIZE (1.1: )
Shifting token TERM_SIZE (1.1: )
Entering state 8
Reading a token: Next token is token TERM_VARIABLE_NAME (1.1: )
Shifting token TERM_VARIABLE_NAME (1.1: )
Entering state 13
Reducing stack by rule 8 (line 137):
   $1 = token TERM_SIZE (1.1: )
   $2 = token TERM_VARIABLE_NAME (1.1: )
-> $$ = nterm declaration (1.1: )
Stack now 0 3 6
Entering state 10
Reading a token: Next token is token TERM_FULLSTOP (1.1: )
Shifting token TERM_FULLSTOP (1.1: )
Entering state 15
Reducing stack by rule 7 (line 134):
   $1 = nterm middle_declarations (1.1: )
   $2 = nterm declaration (1.1: )
   $3 = token TERM_FULLSTOP (1.1: )
-> $$ = nterm middle_declarations (1.1: )
Stack now 0 3
Entering state 6
Reading a token: Next token is token TERM_SIZE (1.1: )
Shifting token TERM_SIZE (1.1: )
Entering state 8
Reading a token: Next token is token TERM_VARIABLE_NAME (1.1: )
Shifting token TERM_VARIABLE_NAME (1.1: )
Entering state 13
Reducing stack by rule 8 (line 137):
   $1 = token TERM_SIZE (1.1: )
   $2 = token TERM_VARIABLE_NAME (1.1: )
-> $$ = nterm declaration (1.1: )
Stack now 0 3 6
Entering state 10
Reading a token: Next token is token TERM_FULLSTOP (1.1: )
Shifting token TERM_FULLSTOP (1.1: )
Entering state 15
Reducing stack by rule 7 (line 134):
   $1 = nterm middle_declarations (1.1: )
   $2 = nterm declaration (1.1: )
   $3 = token TERM_FULLSTOP (1.1: )
-> $$ = nterm middle_declarations (1.1: )
Stack now 0 3
Entering state 6
Reading a token: Next token is token TERM_SIZE (1.1: )
Shifting token TERM_SIZE (1.1: )
Entering state 8
Reading a token: Next token is token TERM_VARIABLE_NAME (1.1: )
Shifting token TERM_VARIABLE_NAME (1.1: )
Entering state 13
Reducing stack by rule 8 (line 137):
   $1 = token TERM_SIZE (1.1: )
   $2 = token TERM_VARIABLE_NAME (1.1: )
-> $$ = nterm declaration (1.1: )
Stack now 0 3 6
Entering state 10
Reading a token: Next token is token TERM_FULLSTOP (1.1: )
Shifting token TERM_FULLSTOP (1.1: )
Entering state 15
Reducing stack by rule 7 (line 134):
   $1 = nterm middle_declarations (1.1: )
   $2 = nterm declaration (1.1: )
   $3 = token TERM_FULLSTOP (1.1: )
-> $$ = nterm middle_declarations (1.1: )
Stack now 0 3
Entering state 6
Reading a token: Next token is token TERM_BODY (1.1: )
Shifting token TERM_BODY (1.1: )
Entering state 7
Reading a token: Next token is token TERM_FULLSTOP (1.1: )
Shifting token TERM_FULLSTOP (1.1: )
Entering state 11
Reducing stack by rule 4 (line 126):
   $1 = token TERM_BODY (1.1: )
   $2 = token TERM_FULLSTOP (1.1: )
-> $$ = nterm body (1.1: )
Stack now 0 3 6
Entering state 9
Reducing stack by rule 10 (line 145):
-> $$ = nterm grammar_s (1.1: )
Stack now 0 3 6 9
Entering state 14
Reading a token: Next token is token TERM_PRINT (1.1: )
Shifting token TERM_PRINT (1.1: )
Entering state 20
Reducing stack by rule 22 (line 180):
-> $$ = nterm rest_of_print (1.1: )
Stack now 0 3 6 9 14 20
Entering state 34
Reading a token: Next token is token TERM_STR (1.1: )
Shifting token TERM_STR (1.1: )
Entering state 41
Reducing stack by rule 26 (line 194):
   $1 = token TERM_STR (1.1: )
-> $$ = nterm other_print (1.1: )
Stack now 0 3 6 9 14 20 34
Entering state 44
Reducing stack by rule 23 (line 182):
   $1 = nterm rest_of_print (1.1: )
   $2 = nterm other_print (1.1: )
-> $$ = nterm rest_of_print (1.1: )
Stack now 0 3 6 9 14 20
Entering state 34
Reading a token: Next token is token TERM_FULLSTOP (1.1: )
Reducing stack by rule 21 (line 176):
   $1 = token TERM_PRINT (1.1: )
   $2 = nterm rest_of_print (1.1: )
"hEllo"
-> $$ = nterm print (1.1: )
Stack now 0 3 6 9 14
Entering state 25
Reducing stack by rule 14 (line 150):
   $1 = nterm print (1.1: )
-> $$ = nterm grammar (1.1: )
Stack now 0 3 6 9 14
Entering state 22
Next token is token TERM_FULLSTOP (1.1: )
Shifting token TERM_FULLSTOP (1.1: )
Entering state 35
Reducing stack by rule 11 (line 147):
   $1 = nterm grammar_s (1.1: )
   $2 = nterm grammar (1.1: )
   $3 = token TERM_FULLSTOP (1.1: )
-> $$ = nterm grammar_s (1.1: )
Stack now 0 3 6 9
Entering state 14
Reading a token: Next token is token TERM_END (1.1: )
Shifting token TERM_END (1.1: )
Entering state 16
Reading a token: Next token is token TERM_FULLSTOP (1.1: )
Shifting token TERM_FULLSTOP (1.1: )
Entering state 27
Reducing stack by rule 5 (line 129):
   $1 = token TERM_END (1.1: )
   $2 = token TERM_FULLSTOP (1.1: )
-> $$ = nterm end (1.1: )
Stack now 0 3 6 9 14
Entering state 21
Reducing stack by rule 2 (line 113):
   $1 = nterm begin (1.1: )
   $2 = nterm middle_declarations (1.1: )
   $3 = nterm body (1.1: )
   $4 = nterm grammar_s (1.1: )
   $5 = nterm end (1.1: )

示例输入:

BeGiNInG.

X XXAB-.
XX XXX7.
XX XXXY.

BoDY.

print "hEllo".

EnD.

【问题讨论】:

  • 请按顺序显示所有规则。
  • @rici 你好 :)。我添加了对问题的更改。
  • [X]{2,0} 无效,但 [X]{2,} 按预期工作。你没有从那个文件的 flex 中得到错误“错误的迭代值”吗?
  • 另外,我看到您仍然接受 | 作为空白字符 :-)
  • @rici 不,我没有收到“错误的迭代值”错误。我应该得到它吗?我删除了|。 :)

标签: regex bison flex-lexer yacc lex


【解决方案1】:
[X]{2,}[A-Z0-9\-]* yylval.string = strdup(yytext);return TERM_INVALID_VARIABLE_NAME;

应该可以正常工作,而且对我来说确实可以正常工作。但是,它可以简化为:

XX[A-Z0-9-]* yylval.string = strdup(yytext);return TERM_INVALID_VARIABLE_NAME;

因为任何进一步的 X 字符将匹配 [A-Z0-9-] 字符类。 (请注意,不必在字符类中写入\-- 可以,只要它是字符类中的第一件事或最后一件事。)

那个模式(和你的一样)也只匹配 XX,但 [X]+ 模式会胜出,因为它在 flex 输入文件中出现得更早。

{2,0} 不是有效的区间表达式,因为 0 小于 2。要指定“2 个或更多 X”,请编写 X{2,}(或 [X]{2,},如果您愿意。"X"{2,} 也可以。)这应该会从 flex 产生一条错误消息,结果不会产生词法扫描器。 (但是,旧的可能仍然存在,这可能会造成混乱。)

【讨论】:

  • 我试过XX[A-Z0-9-]* yylval.string = strdup(yytext);return TERM_INVALID_VARIABLE_NAME; 但还是不行,我不知道为什么它没有被接收。我已经更新了问题,现在它包括调试输出和示例输入。如果需要,我也可以给出完整的代码。
  • @cod3min3:我怀疑您实际上并没有重新生成扫描仪。 Flex 肯定会为X{2,0} 产生错误;此外,您的最新编辑(将 [X]+ 移至文件末尾)将永远不会返回 TERM_SIZE 令牌。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-31
  • 2015-11-14
  • 1970-01-01
  • 2021-06-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多