2017-04-19 93 views
-1

我正在嘗試爲我自己的迷你語言構建一個解析器,然後由YACC自己將它翻譯成C++。LEX + YACC在下一行取得令牌

問題是,YACC正在讀取輸入的第一行以及輸入的第二行中的第一個標記,並將其與相應的規則進行匹配,而它應該只讀取第一行輸入中的標記以及與相應的規則匹配它

我的輸入文件是:

print "hello" 
a = 10 
print a 

萊克斯文件:

%{ 
    #include <stdio.h> 
    #include "y.tab.h" 
%} 

alpha [a-zA-Z] 
digit [0-9] 

%% 
[ \t]       ; 
[ \n]       { yylineno = yylineno + 1;} 
print       {yylval = strdup(yytext); return PRINT;} 
{alpha}({alpha}|{digit})*  {yylval = strdup(yytext); return ID;} 
{digit}+      {yylval = strdup(yytext); return INTEGER;} 
\".*\"       {yylval = strdup(yytext); return STRING;} 
"="        return ASSIGN; 
%% 

YACC文件是:

%{ 
    #include <stdio.h> 
    #include <string.h> 
    #include <stdlib.h> 
    extern int yylineno; 
    extern FILE *yyin; 
    extern FILE *yyout; 
    extern char *yytext; 
%} 

%token PRINT INPUT INTO ASSIGN INTEGER DECIMAL BOOLVAL CHARACTER 

%nonassoc STRING 
%nonassoc ID 

%% 
entry: entry action {fprintf(yyout, "\t%s", $2); } 
    | action   {fprintf(yyout, "\t%s", $1); } 
    ; 

action : print   {$$ = $1;} 
    | assign   {$$ = $1;} 
    ; 

print : PRINT ID { 
      printf("rule: PRINT ID"); 
      char* id = strdup($2); 
      strcpy($$, ""); 
      strcat($$,"cout<<"); 
      strcat($$,id); 
      strcat($$,"<<endl;\n"); 
     } 
    | PRINT STRING { 
      printf("rule: PRINT STRING\n"); 
      char* str = strdup($2); 
      strcpy($$, ""); 
      strcat($$,"cout<<"); 
      strcat($$,str); 
      strcat($$,"<<endl;\n"); 
     } 
    | PRINT STRING ID { 
      printf("rule: PRINT STRING ID\n"); 
      char* str = strdup($2); 
      char* id = strdup($3); 
      strcpy($$, ""); 
      strcat($$,"cout<<"); 
      strcat($$,str); 
      strcat($$,"<<"); 
      strcat($$,id); 
      strcat($$,"<<endl;\n"); 
     } 
    ; 

assign: ID ASSIGN INTEGER { 
      char* id = strdup($1); 
      char* val = strdup($3); 
      strcpy($$,""); 
      strcat($$,"int "); 
      strcat($$,id); 
      strcat($$," = "); 
      strcat($$,val); 
      strcat($$,";\n"); 
     } 
    ; 
%% 

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

    yyin = fopen(argv[1], "r"); 
    yyout = fopen("out.txt","w"); 

    if(!yyparse()) 
     printf("\nParsing complete\n"); 
    else 
     printf("\nParsing failed\n"); 

    //fclose(yyin); 
    fclose(yyout); 
    return 0; 
} 

yyerror(char *s) { 
    printf("\n \nLine: %d, Message: %s, Cause: %s\n", yylineno, s, yytext); 
} 

yywrap() 
{ 
    return 1; 
} 

預期輸出是:

cout<<"hello"<<endl; 
int a = 10; 
cout<<a<<endl; 

但是解析失敗,以部分輸出爲:

cout<<"hello"<<a<<endl; 

和錯誤消息:

Line: 2, Message: syntax error, Cause: = 

用於規則減少應該是(相同的ord ER):

PRINT STRING 
ID ASSIGN INTEGER 
PRINT ID 

但是,第一個規則被用於降低是:

PRINT STRING ID 

和分析失敗

ID是下一行,PRINT STRING後,卻依然規則使用的是PRINT STRING ID

我從輕優先於STRING超過ID(我想這就是下面的代碼是什麼意思)

%nonassoc STRING 
%nonassoc ID 

是什麼問題?

我無法理解發生了什麼。我錯過了什麼嗎?

回答

2

您的一個有效的打印操作是

PRINT STRING ID 

您的輸入匹配這個動作,但馬上此輸入下面是一個等號(=),其中解析器無法比擬的任何其他行動的開始。

看起來你想用新行來劃定你的行爲。因此,您需要明確創建操作結束標記,更新語法以便您的操作以該標記結束,並讓詞法分析器在看到換行符時生成標記。

+0

您的意思是,返回一個標記,對每個\ n說NEWLINE並使用像PRINT STRING NEWLINE和ID ASSIGN INTEGER NEWLINE這樣的規則? –

+0

@Abhilashk - 確實如此 – antlersoft