2016-04-15 36 views
1

大家好,我正在尝试学习野牛。我在github发现了一个简单的工作表达式分析器,其可以执行以下操作:不能让工作多重任务在野牛/ flex

  • 分配(如= 34; B = A)

  • 印刷(如打印)

  • 退出(键入exit,它将终止)

我想了解的基本规则是如何工作的。所以我试图修改这些规则以使得可以执行多个任务(比如这个:a = b = c = 5;)。

要做到这一点,我添加了一个新行规则是这样的:

line : assegn ';'  {;} 
      | exit_command ';'  {exit(EXIT_SUCCESS);} 
      | print exp ';'   {printf("Printing %d\n", $2);} 
      | line assignment ';' {;} 
      | line print exp ';' {printf("Printing %d\n", $3);} 
      | line exit_command ';' {exit(EXIT_SUCCESS);} 
      ; 

然后我增加了以下新规则

assegn : assignment {;} 
     | identifiers {;} 
      ; 

identifiers : assignment {$$=$1;} 
     | identifier '=' identifiers {updateSymbolVal($1,$3);} 
      ; 

和分配是这样的

assignment : identifier '=' exp {$$=$3; updateSymbolVal($1,$3); } 
       ; 

最后,我能够编译由bison和flex生成的文件,但是当我尝试制作多个任务nt它返回我的语法错误。

有人可以解释我,我犯了一个错误,请吗?这是我从最初的例子开始的。 https://github.com/jengelsma/yacc-tutorial.git

这是我的野牛文件的代码:

%{ 
void yyerror (char *s); 
#include <stdio.h>  /* C declarations used in actions */ 
#include <stdlib.h> 
int symbols[52]; 
int symbolVal(char symbol); 
void updateSymbolVal(char symbol, int val); 
int val; 
%} 

%union {int num; char id;}   /* Yacc definitions */ 
%start line 
%token print 
%token exit_command 
%token <num> number 
%token <id> identifier 
%type <num> line exp term 
%type <id> assignment 
%type <num> identifiers 

%% 
/*the original line was line : assignment ';' {;}*/ 
line : assegn ';'  {;} 
     | exit_command ';'  {exit(EXIT_SUCCESS);} 
     | print exp ';'   {printf("Printing %d\n", $2);} 
     | line assignment ';' {;} 
     | line print exp ';' {printf("Printing %d\n", $3);} 
     | line exit_command ';' {exit(EXIT_SUCCESS);} 
     ; 

assegn : assignment {;} 
     | identifiers {;} 
      ; 

identifiers : assignment {$$=$1;} 
     | identifier '=' identifiers {updateSymbolVal($1,$3);} 
      ; 


assignment : identifier '=' exp {$$=$3; updateSymbolVal($1,$3); } 
      ; 
exp  : term     {$$ = $1;} 
     | exp '+' term   {$$ = $1 + $3;} 
     | exp '-' term   {$$ = $1 - $3;} 
     ; 
term : number    {$$ = $1;} 
     | identifier   {$$ = symbolVal($1);} 
     ; 

%%      /* C code */ 

int computeSymbolIndex(char token) 
{ 
    int idx = -1; 
    if(islower(token)) { 
     idx = token - 'a' + 26; 
    } else if(isupper(token)) { 
     idx = token - 'A'; 
    } 
    return idx; 
} 

/* returns the value of a given symbol */ 
int symbolVal(char symbol) 
{ 
    int bucket = computeSymbolIndex(symbol); 
    return symbols[bucket]; 
} 

/* updates the value of a given symbol */ 
void updateSymbolVal(char symbol, int val) 
{ 
    int bucket = computeSymbolIndex(symbol); 
    symbols[bucket] = val; 
} 

int main (void) { 
    /* init symbol table */ 
    int i; 
    for(i=0; i<52; i++) { 
     symbols[i] = 0; 
    } 

    return yyparse (); 
} 

void yyerror (char *s) {fprintf (stderr, "%s\n", s);} 

这是我的Flex文件:

%{ 
#include "exppars.tab.h" 
%} 
%% 
"print"       {return print;} 
"exit"        {return exit_command;} 
[a-zA-Z]       {yylval.id = yytext[0]; return identifier;} 
[0-9]+     {yylval.num = atoi(yytext); return number;} 
[ \t\n]    ; 
[-+=;]      {return yytext[0];} 
.      {ECHO; yyerror ("unexpected character");} 

%% 
int yywrap (void) {return 1;} 
+0

您能指定您尝试解析的确切字符串,它会返回您不期望的解析错误吗? – Ctx

+0

这一个例如c = d = z = s = 5; –

回答

0

好了,它看起来像我已经找到了这样回答的。

  • 我注意到,只有当我试图在第一输入后做的 多重分配出现的语法错误。

解决这个问题我添加了一条新规则。现在规则块看起来是这样的:

line : assegn ';'  {;} 
    | exit_command ';'  {exit(EXIT_SUCCESS);} 
    | print exp ';'   {printf("Printing %d\n", $2);} 
    | line assegn ';' {;} 
    | line print exp ';' {printf("Printing %d\n", $3);} 
    | line exit_command ';' {exit(EXIT_SUCCESS);} 
    ; 
  • ,当我试图做多长的分配下一个问题出现了,像这样的,例如:A = B = C = d = 5 ;.我只是把值分配给c和d,而不是分配给其他值。 好像代码{$$ = $ 1}没有按我的预期工作。所以我添加一个新的int变量来存储上次赋值的值。生产规则现在这个样子:

    identifiers : assignment { val = $1;} 
        | identifier '=' identifiers {updateSymbolVal($1,val);} 
        ; 
    assignment : identifier '=' exp {$$=$3; updateSymbolVal($1,$3);} 
        ; 
    exp  : term     { $$ = $1; @1;} 
        | exp '+' term   { $$ = $1 + $3; } 
        | exp '-' term   { $$ = $1 - $3; } 
        ; 
    term : number    {$$ = $1;} 
        | identifier   {$$ = symbolVal($1);} 
        ; 
    

现在,它的工作。