【问题标题】:Flex and Bison code - syntax error alwaysFlex 和 Bison 代码 - 总是有语法错误
【发布时间】:2019-06-16 14:31:15
【问题描述】:

首先我需要说我对 Flex 和 Bison 很陌生,我有点困惑。有一个学校项目希望我们为某种 CLIPS 语言创建一个使用 Flex 和 Bison 的编译器。 我的代码有很多问题,但主要问题是无论我输入什么,我都会看到语法错误,而结果应该是别的东西。理想的情况是完全适用于语言 CLIPS。例如,当我写“4”时,它会出现语法错误。阅读我的代码可能会让你更好地理解这一点。如果我写“test 3 4”,它不会显示语法错误,但它会将其视为未知标记,这又是错误的......我完全迷失了。该代码是学校的原型,我们需要做一些更改。如果您有任何问题,请不要犹豫。谢谢你! PS:不要介意cmets,它们是希腊语。 灵活代码:

%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

制作文件:

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

【问题讨论】:

  • 有趣的语言!你打算怎么给号码0? :D
  • 另外,我从来没有见过这样用拉丁字母写的希腊语——看起来很糟糕:D
  • @antti:我认为这很常见。稍加练习,就很容易解码。
  • @AnttiHaapala 在哪里给出数字 0? :P 实际上它的希腊语与英语相结合。所谓的“希腊语”,是的,我同意他们很糟糕!
  • 他的意思是你的整数模式不能识别整数0。这可能不是你想要的。

标签: c compiler-construction bison flex-lexer


【解决方案1】:
  1. 您的顶级规则是:

    program:
        program expr NEWLINE 
    

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

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

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

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

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

    回退模式应该是.|\n,但如果您绝对确定每个换行符都会被某个规则匹配,您可以使用.。我喜欢使用%option nodefault,如果有一些可能的输入不符合任何规则,这将导致 flex 警告我。

【讨论】:

  • 正如我之前所说,我是新手,如果我需要进一步的解释和帮助,请原谅!关于(1)我明白你在说什么。但是我怎样才能编辑代码使其运行良好?我应该以某种方式编辑代码以更改它在换行符之后的作用吗? (2) 你的意思是我必须在 flex 文件中删除我的令牌?他们不需要吗?实际上,我首先将 flex 文件作为独立文件制作,这就是为什么会有.. 谢谢你的回答
  • @miltos: (1) return NEWLINE;。如果这不明显,您应该(重新)阅读 flex 手册。 (2)你需要包含yacc/bison生成的头文件,而不是你自己的错误定义。
  • 对于(2),我删除了我写的 %token ..... 东西,我在 yyac 文件中包含了在包含 下生成的头文件flex 文件也是.. 但现在我得到错误,令牌已使用但未定义并且它们没有规则
  • @Miltos,我不是这么说的。您需要 %token 声明;我从来没有说过你应该删除它们。而且您不会将野牛生成的标头包含在野牛源中,因为它已经包含在野牛生成的代码中。
  • 好的,我明白了并修复了。我写了返回 NEWLINE。但是当我键入任何内容时,仍然会出现语法错误。在我试图写评论(以;开头)的原始代码中,它没有说语法错误或任何东西,它只是忽略了它们。现在它说语法错误。我很困惑
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多