首页 > 解决方案 > Flex/Bison 解析器识别“(”与“(”不同)

问题描述

我正在尝试使用 flex 和 bison 编写一个简单的玩具语言解析器,它基本上只支持变量和算术函数。

目前我面临一个奇怪的问题,其中带有左括号和下一个标记之间的空格的语句与带有左括号且下一个标记之间没有空格的语句的工作方式不同,特别是我试图识别以下程序。

var b: int
begin
b <- (4)
end

尝试这样做会在第 3 行出现语法错误,但是如果我在 4 和 ( 之间添加一个空格,则程序会被正确识别。

我的 parser.lex 文件如下。

%{
#include<stdlib.h>
#include<math.h>
#include "parser.tab.h"
%}

LETTR   [a-zA-Z]
DIGIT   [0-9]
BIN     [0-1] 
SIMB   [$|_]
WHITESPACE [ \t\r]+ 

%%
WHITESPACE  { }
"\n"    {yylineno++;}
"begin"  {return BEGN;}
"if"     {return IF;}
"ifelse" {return IFELSE;}
"while"  {return WHILE;}
"end"                           {return END;}
"var"             {return VAR;}
"read"            {return READ;}
"print"           {return PRINT;}
"int"             {return INT;}
"float"           {return FLOAT;}
"<-"                            {return ASSIGN;}
({SIMB}|{LETTR})({LETTR}|{DIGIT}|{SIMB})*  {yylval.id=(char*)malloc(strlen(yytext)+1); strcpy(yylval.id, yytext); return ID;} /* Identificador */
({DIGIT})({DIGIT})*   {return NUMINT;}   /*Entero*/
({DIGIT})*.({DIGIT})({DIGIT})*     {return NUMFLOAT;} /*Punto Flotante*/
";"                             {return SEMICOLON;}
":"               {return COLON;}
"+"                             {return PLUS;}
"-"                             {return MINUS;}
"*"                             {return MULT;}
"/"                             {return DIVIDE;}
"<"                             {return LESSTHAN;}
">"                             {return GREATTHAN;}
"="                             {return EQUALS;}
"<="                            {return LESSEQUALS;}
">="                            {return GREATEQUALS;}
"~"               {return NEGSIGN;}
"("                             {return LEFTP;}
")"                             {return RIGHTP;}
.                 { }
%%

而我的 parser.y 文件如下:

%{
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
FILE extern *yyin;
char extern *yytext;
int yylineno;
int yylex();
int yyerror(char const * s);
void addToTable(char * var);
void initTable();
void checkVar();
void printTable();


%}
%union{
  char *id;
}
%token <id > ID
%token BEGN IF IFELSE WHILE END VAR ASSIGN LEFTP RIGHTP INT FLOAT SEMICOLON COLON PLUS MINUS 
MULT DIVIDE LESSTHAN GREATTHAN EQUALS LESSEQUALS GREATEQUALS NUMINT NUMFLOAT READ PRINT NEGSIGN
%start prog


%%

prog: opt_decls BEGN opt_stmts END {printf("Valid program!\n"); printTable(); return 0;}

opt_decls: decls
          | /* empty */
;

decls : dec SEMICOLON decls
      | dec
;

dec : VAR ID COLON tipo { addToTable($2);}
;

tipo : INT 
     | FLOAT
;

stmt : ID ASSIGN expr {checkVar($1);}
     | IF LEFTP expression RIGHTP stmt
     | IFELSE LEFTP expression RIGHTP stmt stmt
     | WHILE LEFTP expression RIGHTP stmt
     | READ ID {checkVar($2);}
     | PRINT expr
     | BEGN opt_stmts END
;

opt_stmts : stmt_lst
          | /*empty*/
;

stmt_lst : stmt SEMICOLON stmt_lst
          | stmt
;

expression : expr
           | expr relop expr
;

expr : expr PLUS term
     | expr MINUS term
     | sign term
     | term  

term : term MULT factor
     | term DIVIDE factor
     | factor
; 

factor : LEFTP expr RIGHTP 
       | ID {checkVar($1);}
       | NUMINT
       | NUMFLOAT
;

relop : LESSTHAN 
      | GREATTHAN 
      | EQUALS 
      | LESSEQUALS 
      | GREATEQUALS 
;

sign : NEGSIGN
;

%%
char symbolTable [100][50];

int yyerror(char const * s) {
  fprintf(stderr, "%s at line: %d while reading %s\n", s, yylineno, yytext);
}

void printTable(){
  printf("Symbol table:\n");
  int i; 
  for (i = 0; i < 100; i++){
    if (strcmp(symbolTable[i], "") != 0){
      printf("%s\n", symbolTable[i]);
    }
  }
}

void addToTable(char *var){
  int i = 0;
  for (i = 0; i < 100; i++){
    if (strcmp(symbolTable[i], "") == 0){
      strcpy(symbolTable[i], var);
      break;    
    }
  }
}

void initTable(){
  int i;
  for (i = 0; i < 100; i++){
    strcpy(symbolTable[i], "");
  }
}

void checkVar(char * var){
  int i;
  for (i = 0; i < 100; i++){
    if (strcmp(symbolTable[i], var) == 0){
      return;
    } 
  }
  char errorMsg [255];
  sprintf(errorMsg, "Variable %s was not initialized", var);
  yyerror(errorMsg);
  exit(-1);
}

void main(int argc, char *argv[]) {

  initTable();  
  if (argc == 1)
        printf("Input file not found.\n");
        else{
            yyin = fopen(argv[1], "r");
      yyparse();
        } 

  fclose(yyin);
}

老实说,我对可能导致这种情况的原因感到困惑。

我正在使用以下命令运行程序(使用 Ubuntu 16.04)

flex parser.lex
bison -d parser.y
gcc lex.yy.c parser.tab.c -lfl
./a.out p3.txt

其中 p3.txt 是一个文本文件,其中包含要解析的程序。

标签: ccompiler-constructionbisonflex-lexer

解决方案


推荐阅读