ID的Flex模式给出了“分段错误”

时间:2015-06-07 18:19:06

标签: c regex

我在C中有一个程序将表达式转换为RPN(反向波兰表示法)。 我需要做的就是用Flex替换用C编写的lexer代码。我已经做了一些工作,但我遇到了模式问题 - 单词或变量id是具体的。是的,这是课堂练习。

这就是我所拥有的:

%{
    #include "global.h"
    int lineno = 1;
    int tokenval = NONE;
%}

%option noyywrap

WS             " "
NEW_LINE       "\n"
DIGIT          [0-9]
LETTER         [a-zA-Z] 
NUMBER         {DIGIT}+
ID             {LETTER}({LETTER}|{DIGIT})*

%%

{WS}+           {}
{NEW_LINE}      { ++lineno; }
{NUMBER}        { sscanf (yytext, "%d", &tokenval); return(NUM); }
{ID}            { sscanf (yytext, "%s", &tokenval); return(ID); }
.               { return *yytext;}
<<EOF>>         { return (DONE); }

%%

并在global.h

中定义
#define BSIZE 128
#define NONE -1
#define EOS '\0'
#define NUM 256
#define DIV 257
#define MOD 258
#define ID  259
#define DONE 260

当我使用数字,括号和运算符时,所有工作都有效,但当我输入例如a+b时,它会给我Segmentation fault(并且输出应为ab+)。 请不要问我解析器代码(如果真的需要我可以共享) - 要求只使用Flex实现词法分析器。

2 个答案:

答案 0 :(得分:2)

问题是程序正在使用字符串格式(sscanf)对%s进行整数地址(&tokenval)。您应该将其更改为char数组,例如

%{
    #include "global.h"
    int lineno = 1;
    int tokenval = NONE;
    char tokenbuf[132];
%}

{ID}            { sscanf (yytext, "%s", tokenbuf); return(ID); }

(虽然strcpy是比sscanf更好的选择,但这只是一个起点。)

答案 1 :(得分:1)

当flex扫描令牌匹配模式ID时,关联的操作会尝试将令牌复制到位置&tokenval的字符数组中。但是tokenval的类型为int,所以

  1. 代码具有未定义的行为
  2. 如果ID的长度等于或超过int的大小,则您无法将其所有字节(包括字符串终止符)放在int占用的空间中。一个可能的结果是你试图写出它的结尾,这可能会导致段错误。