Lex只在它们之间有空格时检测符号

时间:2013-07-26 00:24:17

标签: regex lex

我希望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);
      }
   }
}

2 个答案:

答案 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+1INT_LITERAL)。请参阅相关主题:Is it possible to set priorities for rules to avoid the "longest-earliest" matching pattern?

您可以添加一个明确的规则来匹配+作为令牌,否则听起来Lex会采取最长的匹配(+1长于+)。