2016-04-14 8 views
1

Program kodunu alan ve int ve double değişken türlerinin ve işlevlerin sayılarını döndüren basit bir Yacc programı yazıyorum.Yacc - eşleşen bir kural olduğunda bir satır bir sözdizimi hatası döndürüyor

Bir programın satır için bir eşleme kuralı olduğunda bir sözdizimi hatası vermesi tuhaf bir soruna rastladım, ancak satır farklı bir kural seçti.

yacc kodu

%{ 
#define YYDEBUG 1 
#include <stdio.h> 
#include <stdlib.h> 
int func_count=0; 
int int_count=0; 
int char_count=0; 
int double_count=0; 
int float_count=0; 
int pointer_count=0; 
int array_count=0; 
int condition_count=0; 
int for_count=0; 
int return_count=0; 
int numeric_count=0; 
%} 

%token INT_KEYWORD DOUBLE_KEYWORD CHAR_KEYWORD RETURN_KEYWORD FLOAT_KEYWORD IF_KEYWORD VARIABLE OPERATOR COMPARE DIGIT FOR_KEYWORD POINTER_VARIABLE 
%start program 
%% 

program: 
    program statement '\n' 
    | 
    ; 

statement: 
    declaration_statement | 
    function_declaration_statement {func_count++;} 

    ; 

function_declaration_statement: 
    datatype VARIABLE '(' datatype VARIABLE ')' '{' 
    ; 

declaration_statement: 
    int_declaration_statement | 
    double_declaration_statement 
    ; 

int_declaration_statement: 
    INT_KEYWORD VARIABLE '[' DIGIT ']' ';'{array_count++;} 
    | 
    INT_KEYWORD VARIABLE ';' {int_count++;} 
    | 
    INT_KEYWORD VARIABLE '=' DIGIT ';' {int_count++;} 


double_declaration_statement: 
    DOUBLE_KEYWORD VARIABLE '[' DIGIT ']' ';' {array_count++;} 
    | 
    DOUBLE_KEYWORD VARIABLE ';' {double_count++;} 
    | 
    DOUBLE_KEYWORD VARIABLE '=' DIGIT ';' {double_count++;} 


datatype: 
    INT_KEYWORD 
    | 
    DOUBLE_KEYWORD 
    | 
    CHAR_KEYWORD 
    | 
    FLOAT_KEYWORD 
    ; 
%% 

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

int main (void){ 
    yydebug=1; 
    yyparse(); 
    printf("#int variable=%d, #double variable=%d",int_count,double_count); 
    printf("#array=%d\n",array_count); 
    printf("#function=%d\n",func_count); 


} 

Lex

%{ 
#include <stdio.h> 
#include <stdlib.h> 
#include "y.tab.h" 
void yyerror(char *); 
%} 

%% 
"int"   {return INT_KEYWORD;} 
"double"  {return DOUBLE_KEYWORD;} 
"char"   {return CHAR_KEYWORD;} 
"float"   {return FLOAT_KEYWORD;} 
"if"   {return IF_KEYWORD;} 
"for"   {return FOR_KEYWORD;} 
"return"  {return RETURN_KEYWORD;} 
"=="   {return COMPARE;} 
">"   {return COMPARE;} 
"<"   {return COMPARE;} 
">="   {return COMPARE;} 
"<="   {return COMPARE;} 
"+"   {return OPERATOR;} 
"-"   {return OPERATOR;} 
"/"   {return OPERATOR;} 
"*"   {return OPERATOR;} 
"%"   {return OPERATOR;} 
[0-9]+   {return DIGIT;} 
[a-z]+   {return VARIABLE;} 
"*"" "?[a-zA-Z]+ {return POINTER_VARIABLE;} 
"["   {return *yytext;} 
"="   {return *yytext;} 
"]"   {return *yytext;} 
[;\n(){}]  {return *yytext;} 
[ \t]   ; 
.   {printf("%s\n",yytext); yyerror("invalid charactor");} 
%% 

int yywrap(void){ 
return 1; 
} 
(kullanılmayan değişkenleri görürseniz ben bu hata alakasız diğer bölümlerini silindi çünkü, işte): Ben bu hatayı gösteren kod bileşenleri getirdi

Test dosyası:

int a; 
int a[3]; 
int a(int a) { 

Beklenen çıkış

#int variable=1, #double variable=0 #array=1 
#function=1 

Ama bunun yerine üçüncü satırda başarısız, int bir (int a) programı int değişken bildirimi kuralı seçmek gibiydi ve bir yazım hatası üreten token '(' gördüğünde başarısız çünkü.

ayıklama hata mesajı diyor ...

.... 
Reading a token: Next token is token INT_KEYWORD() 
Shifting token INT_KEYWORD() 
Entering state 3 
Reading a token: Next token is token VARIABLE() 
Shifting token VARIABLE() 
Entering state 13 
Reading a token: Next token is token '('() 
syntax error 
.... 

kimse ne yanlış işaret eder misiniz? Teşekkürler.

+2

Çatışma/kargaşayı azaltma ve işe yaramaz bir üretim hakkında bir uyarı almıyor musunuz? Onları tamir etmelisin. – rici

cevap

1

Dilbilginizde iki kaydırma/azaltma çakışma var.

İşte
State 3 

    8 int_declaration_statement: INT_KEYWORD . VARIABLE '[' DIGIT ']' ';' 
    9       | INT_KEYWORD . VARIABLE ';' 
10       | INT_KEYWORD . VARIABLE '=' DIGIT ';' 
14 datatype: INT_KEYWORD . 

    VARIABLE shift, and go to state 13 

    VARIABLE [reduce using rule 14 (datatype)] 

State 4 

11 double_declaration_statement: DOUBLE_KEYWORD . VARIABLE '[' DIGIT ']' ';' 
12        | DOUBLE_KEYWORD . VARIABLE ';' 
13        | DOUBLE_KEYWORD . VARIABLE '=' DIGIT ';' 
15 datatype: DOUBLE_KEYWORD . 

    VARIABLE shift, and go to state 14 

    VARIABLE [reduce using rule 15 (datatype)] 

, ne zaman bir INT_KEYWORD veya DOUBLE_KEYWORD karşılaşacak yacc o ise yani o bilmez (o vardiya veya azaltmak için ihtiyacı olup olmadığını bilmiyor,: yacc tarafından oluşturulan çıktı dosyasında nerede görebilirsiniz bir beyan veya sadece bir veri türü). Varsayılan olarak yacc değişecektir.

Ayrıca, function_declaration_statement numaralı telefon numaranızda, önce bir datatype: yacc ürününü azaltabilirsiniz (çünkü bunun tek üretim kuralıdır). Sonra INT_KEYWORD VARIABLE (veya DOUBLE_KEYWORD) gibi bir şey olacak, bu yüzden bir int_declaration_statement olduğunu düşünecek ... Sözdizimi hatası yacc bir '(' karşılaşma olduğunda olur.

Bunu çözmek için, function_declaration_statement'u kaldırabilir ve int_declaration_statement (ve çift) öğesine bir çizgi ekleyebilirsiniz. Örneğin,/sen vardiya kaldırmak çatışmaları önlemeye ve istediğiniz sonucu verecektir

statement: int_declaration_statement 
     | double_declaration_statement 
     ; 

int_declaration_statement: INT_KEYWORD VARIABLE '[' DIGIT ']' ';'{array_count++;} 
         | INT_KEYWORD VARIABLE ';' {int_count++;} 
         | INT_KEYWORD VARIABLE '=' DIGIT ';' {int_count++;} 
         | INT_KEYWORD VARIABLE '(' datatype VARIABLE ')' '{' {func_count++;} 
         ; 

: Böyle bir şey

--- ~ » ./a.out 
int a; 
int a[3]; 
int a(int a) { 
#int variable=1, #double variable=0#array=1 
#function=1 

yardımcı olur Umut.

İlgili konular