我希望Lex在输入“foo + 1”时首先返回标识符“foo”,然后返回字符“+”,然后返回整数1.如果我lex“foo + 1”,这是有效的,但由于某种原因,我有语法,如果省略空格,它就不起作用,它跳过'+',只返回“foo”然后1.我无法找出原因。这里有什么东西似乎有问题吗?
%{
#include "expression.h"
#include "picoScanner.h"
static int block_comment_num = 0;
static char to_char(char *str);
int yylineno = 0;
%}
%option nodefault yyclass="FlexScanner" noyywrap c++
%x LINE_COMMENT
%x BLOCK_COMMENT
%%
Any { return pico::BisonParser::token::ANY; }
Int { return pico::BisonParser::token::INT; }
Float { return pico::BisonParser::token::FLOAT; }
Char { return pico::BisonParser::token::CHAR; }
List { return pico::BisonParser::token::LIST; }
Array { return pico::BisonParser::token::ARRAY; }
Table { return pico::BisonParser::token::TABLE; }
alg { return pico::BisonParser::token::ALG; }
if { return pico::BisonParser::token::IF; }
then { return pico::BisonParser::token::THEN; }
else { return pico::BisonParser::token::ELSE; }
is { return pico::BisonParser::token::IS; }
or { return pico::BisonParser::token::OR; }
and { return pico::BisonParser::token::AND; }
not { return pico::BisonParser::token::NOT; }
when { return pico::BisonParser::token::WHEN; }
[A-Z][a-zA-Z0-9_]* { yylval->strval = new std::string(yytext);
return pico::BisonParser::token::TYPENAME; }
[a-z_][a-zA-Z0-9_]* { printf("saw '%s'\n", yytext); yylval->strval = new std::string(yytext);
return pico::BisonParser::token::ID; }
"==" { return pico::BisonParser::token::EQ; }
"<=" { return pico::BisonParser::token::LEQ; }
">=" { return pico::BisonParser::token::GEQ; }
"!=" { return pico::BisonParser::token::NEQ; }
"->" { return pico::BisonParser::token::RETURN; }
[\+\-\*/%] { return yytext[0]; }
[-+]?[0-9]+ { yylval->ival = atoi(yytext);
return pico::BisonParser::token::INT_LITERAL; }
([0-9]+|([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?) { yylval->fval = atof(yytext);
return pico::BisonParser::token::FLOAT_LITERAL; }
\"(\\.|[^\\"])*\" { yylval->strval = new std::string(strndup(yytext+1, strlen(yytext) - 2));
return pico::BisonParser::token::STRING_LITERAL; }
\'(\\.|[^\\'])*\' { yylval->cval = to_char(yytext+1);
return pico::BisonParser::token::CHAR_LITERAL; }
[ \t\r]+ { /* ignore */ }
\n { yylineno++; }
. { printf("~~~~~~~~~~munched %s\n", yytext); return yytext[0]; }
%%
static char to_char(char *str) {
if (strlen(str) <= 1) {
fprintf(stderr, "Error: empty character constant (line %d)\n", yylineno);
exit(1);
} else if (str[0] != '\\') {
return str[0];
} else {
if (strlen(str) == 1) {
fprintf(stderr, "Error: somehow we got a single slash character\n");
exit(1);
}
switch (str[1]) {
case 'n': return '\n';
case 'r': return '\r';
case 't': return '\t';
case 'a': return '\a';
case 'b': return '\b';
case 'f': return '\f';
case 'v': return '\v';
case '\'': return '\'';
case '"': return '"';
case '\\': return '\\';
case '?': return '\?';
case 'x':
fprintf(stderr, "Error: unicode not yet supported (line %d)\n", yylineno);
exit(1);
default:
fprintf(stderr, "Error: unrecognized escape sequence '\\%c' (line %d)\n",
str[1], yylineno);
exit(1);
}
}
}
答案 0 :(得分:2)
我对lex并不熟悉,但我很确定以下内容会导致错误:
[-+]?[0-9]+ { yylval->ival = atoi(yytext);
return pico::BisonParser::token::INT_LITERAL; }
foo
被解析为标识符,然后&#34; + 0&#34;被解析为int
字面值(由于atoi
转换,符号被丢弃)。
在 lexer 级别只考虑无符号数字文字,并在解析器级别处理符号(处理+
和-
可能是个好主意。令牌不同取决于他们的背景)。
这不仅可以解决模糊性问题,而且还可以使您正确地解决问题。 (从某种意义上说,它们在C,C ++,Java等中是合法的)解析整数文字,例如- 5
而不是-5
。
此外:算术运算符规则中的逃避反斜杠真的有必要吗? Afaik,在字符类中唯一具有特殊含义的字符是-
,^
和]
(但我可能错了)。
答案 1 :(得分:1)
我认为它匹配foo+1
foo
和+1
(INT_LITERAL
)。请参阅相关主题:Is it possible to set priorities for rules to avoid the "longest-earliest" matching pattern?
您可以添加一个明确的规则来匹配+
作为令牌,否则听起来Lex会采取最长的匹配(+1
长于+
)。