Flex和Bison代码-始终存在语法错误

时间:2019-06-16 14:31:15

标签: c compiler-construction bison flex-lexer

首先,我要说我对Flex和Bison还是很陌生,我有点困惑。有一个学校项目希望我们使用Flex和Bison为某种CLIPS语言创建一个编译器。 我的代码有很多问题,但主要的问题是,无论我键入什么内容,我都会看到语法错误,而结果应该是其他错误。理想的方案是完全使用CLIPS语言。 EG,当我写“ 4”时,它得到语法错误。阅读我的代码也许会让您更好地理解这一点。如果我写“ test 3 4”,它不会显示语法错误,但是会将其视为一个未知的令牌,这又是错误的。该代码是学校的原型,我们需要进行一些更改。如果您有任何疑问,请随时提出。谢谢! 附注:不要介意这些评论,它们是希腊文。 弹性代码:

%option noyywrap


/* Kwdikas C gia orismo twn apaitoumenwn header files kai twn metablhtwn.
   Otidhpote anamesa sta %{ kai %} metaferetai autousio sto arxeio C pou
   tha dhmiourghsei to Flex. */

%{

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/* Header file pou periexei lista me ola ta tokens */
#include "token.h"

/* Orismos metrhth trexousas grammhs */
int line = 1;

%}


/* Onomata kai antistoixoi orismoi (ypo morfh kanonikhs ekfrashs).
   Meta apo auto, mporei na ginei xrhsh twn onomatwn (aristera) anti twn,
   synhthws idiaiterws makroskelwn kai dysnohtwn, kanonikwn ekfrasewn */
/*  dimiourgia KE simfona me ta orismata tis glossas */

DELIMITER       [ \t]+
INTCONST        [+-]*[1-9][0-9]*
VARIABLE    [?][A-Za-z0-9]*         
DEFINITIONS [a-zA-Z][-|_|A-Z|a-z|0-9]*
COMMENTS    ^;.*$


/* Gia kathe pattern (aristera) pou tairiazei ekteleitai o antistoixos
   kwdikas mesa sta agkistra. H entolh return epitrepei thn epistrofh
   mias arithmhtikhs timhs mesw ths synarthshs yylex() */
/*  an sinantisei diaxoristi i sxolio to agnoei, an sinantisei akeraio,metavliti i orismo ton emfanizei. se kathe alli periptosi ektiponei oti den anagnorizei to token, ti grammi pou vrisketai kai to string pou dothike */

%%

{DELIMITER}     {;}
"bind"      { return BIND;}
"test"      { return TEST;}
"read"      { return READ;}
"printout"  { return PRINTOUT;}
"deffacts"  { return DEFFACTS;}
"defrule"   { return DEFRULE;}
"->"        { return '->';}
"="     { return '=';}
"+"     { return '+';}
"-"     { return '-';}
"*"     { return '*';}
"/"     { return '/';}
"("     { return '(';}
")"     { return ')';}      
{INTCONST}      { return INTCONST; }
{VARIABLE}  { return VARIABLE; }
{DEFINITIONS}   { return DEFINITIONS; }
{COMMENTS}  {;}
\n              { line++; printf("\n"); }
.+      { printf("\tLine=%d, UNKNOWN TOKEN, value=\"%s\"\n",line, yytext);}
<<EOF>>     { printf("#END-OF-FILE#\n"); exit(0); }

%%

/* Pinakas me ola ta tokens se antistoixia me tous orismous sto token.h */

char *tname[11] = {"DELIMITER","INTCONST" , "VARIABLE", "DEFINITIONS", "COMMENTS", "BIND", "TEST", "READ", "PRINTOUT", "DEFFACTS", "DEFRULE"};

野牛码:

%{
/* Orismoi kai dhlwseis glwssas C. Otidhpote exei na kanei me orismo h arxikopoihsh
   metablhtwn & synarthsewn, arxeia header kai dhlwseis #define mpainei se auto to shmeio */
        #include <stdio.h>
    #include <stdlib.h>
        int yylex(void);
        void yyerror(char *);
%}

/* Orismos twn anagnwrisimwn lektikwn monadwn. */
%token INTCONST VARIABLE DEFINITIONS PLUS NEWLINE MINUS MULT DIV COM BIND TEST READ PRINTOUT DEFFACTS DEFRULE

%%

/* Orismos twn grammatikwn kanonwn. Kathe fora pou antistoixizetai enas grammatikos
   kanonas me ta dedomena eisodou, ekteleitai o kwdikas C pou brisketai anamesa sta
   agkistra. H anamenomenh syntaksh einai:
                onoma : kanonas { kwdikas C } */
program:
        program expr NEWLINE { printf("%d\n", $2); }
        |
        ;
expr:
        INTCONST         { $$ = $1; }
    | VARIABLE  { $$ = $1; }//prosthiki tis metavlitis
        | PLUS expr expr { $$ = $2 + $3; }//prosthiki tis prosthesis os praksi
    | MINUS expr expr { $$ = $2 - $3; } //prosthiki tis afairesis os praksi
    | MULT expr expr { $$ = $2 * $3; }//prosthiki tou pollaplasiasmou os praksi
    | DIV expr expr { $$ = $2 / $3; }//prosthiki tis diairesis os praksi
    | COM       { $$ = $1; }//prosthiki ton sxolion
    | DEFFACTS expr { $$ = $2; }//prosthiki ton gegonoton
    | DEFRULE expr  { $$ = $2; }//prosthiki ton kanonon
    | BIND expr expr    { $$ = $2;}//prosthiki tis bind
    | TEST expr expr    { $$ = $2 ;}//prosthiki tis test
    | READ expr expr    { $$ = $2 ;}//prosthiki tis read
    | PRINTOUT expr expr    { $$ = $2 ;}//prosthiki tis printout
        ;

%%



/* H synarthsh yyerror xrhsimopoieitai gia thn anafora sfalmatwn. Sygkekrimena kaleitai
   apo thn yyparse otan yparksei kapoio syntaktiko lathos. Sthn parakatw periptwsh h
   synarthsh epi ths ousias typwnei mhnyma lathous sthn othonh. */
void yyerror(char *s) {
        fprintf(stderr, "Error: %s\n", s);
}


/* H synarthsh main pou apotelei kai to shmeio ekkinhshs tou programmatos.
   Sthn sygkekrimenh periptwsh apla kalei thn synarthsh yyparse tou Bison
   gia na ksekinhsei h syntaktikh analysh. */
int main(void)  {
        yyparse();
        return 0;
}

令牌文件:

#define DELIMITER 1
#define INTCONST 2
#define VARIABLE 3
#define DEFINITIONS 4
#define COMMENTS 5
#define BIND 6
#define TEST 7
#define READ 8
#define PRINTOUT 9
#define DEFFACTS 10
#define DEFRULE 11

MAKEFILE:

all:
    bison -d simple-bison-code.y
    flex mini-clips-la.l
    gcc  simple-bison-code.tab.c lex.yy.c -o B2
    ./B2
clean:
    rm simple-bison-code.tab.c simple-bison-code.tab.h lex.yy.c B2

1 个答案:

答案 0 :(得分:3)

  1. 您的顶级规则是:

    program:
        program expr NEWLINE 
    

    ,除非解析器看到NEWLINE令牌,否则无法成功。但是它永远不会看到一个,因为您的词法扫描器永远不会发送一个。看到换行符时,它将增加行数,但不返回任何内容。

  2. 您所有的标记都被视为无效,因为您的词法扫描器使用其自己的标记值定义。你不应该那样做。解析器生成器(bison / yacc)将生成包含正确定义的头文件;也就是说,它期望看到的值。

  3. 还有其他各种问题,可能比我注意到的更多。最重要的是,您不应在exit(0)规则中调用<<EOF>>,因为这将意味着解析器永远不会成功;在传递EOF令牌之前,它不会成功。实际上,通常不应该使用<<EOF>>规则;默认操作是返回0,这是唯一有意义的操作。

  4. 此外,'->'不是正确的C文字。如果您启用了编译器警告(-Wall),即使您正在编译生成的代码,也应该始终这样做,编译器就会对此抱怨。

  5. 扫描仪的最后一个旨在触发错误令牌的模式是.+,它将匹配整行,而不仅仅是错误的字符。由于(f)lex扫描仪接受匹配时间最长的模式,因此您的其他大多数模式将永远不匹配。 (Flex通常会警告您有关不可匹配的模式。您没有收到这样的警告吗?)

    回退模式应为.|\n,但是如果您完全确定每个换行符都可以由某个规则匹配,则可以使用.。我喜欢使用%option nodefault,如果存在某些可能的输入与任何规则都不匹配的情况,则会导致flex向我发出警告。