2017-04-19 3 views
-1

私は自分自身のミニ言語用のパーサーを構築しようとしています。それはYACC自身によってC++に翻訳されています。LEX + YACCはルールの次の行にトークンを取っています

問題は、YACCは入力の第2行から最初のトークンだけでなく第1行も読み取っていて、それを対応するルールと照合していますが、入力の最初の行でトークンのみを読み取る必要があります。対応するルールでそれを一致

私の入力ファイルは次のとおりです。

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 

と解析はPRINT STRING後、

ID

は、次の行にある失敗したが、それでもルール:

PRINT STRING 
ID ASSIGN INTEGER 
PRINT ID 

しかし、最初のルールを軽減するために使用されているです使用されるのはPRINT STRING IDです。

私は

%nonassoc STRING 
%nonassoc ID 

が問題ということです(私は以下のコードが何を意味するのかを推測)IDSTRINGに低い優先度を与えてくれましたか?

私は何が起こっているのか理解できません。何か不足していますか?

答えて

2

あなたの有効な印刷のアクションの一つは

PRINT STRING ID 

であるあなたの入力は、このアクションを一致しますが、すぐにこの入力に従うことパーサは他のアクションの開始と一致することはできません=記号、です。

あなたの行為を区切る改行が必要なようです。したがって、アクショントークンの終了を明示的に作成し、アクションがそのトークンで終わるように文法を更新し、改行文字が見えるときにトークンを生成させる必要があります。

+0

あなたはトークンを返すこと、つまり\ nごとにNEWLINEと言って、PRINT STRING NEWLINEやID ASSIGN INTEGER NEWLINEのようなルールを使用しますか? –

+0

@Abhilashk - はい、正確 – antlersoft

関連する問題