Код Flex и Bison - синтаксическая ошибка всегда - PullRequest
1 голос
/ 16 июня 2019

Прежде всего, я должен сказать, что я новичок в Flex и Bison, и я немного растерялся.Есть школьный проект, который хочет, чтобы мы создали компилятор, используя Flex и Bison для какого-то языка CLIPS.В моем коде много проблем, но главная заключается в том, что, что бы я ни печатал, я вижу синтаксическую ошибку, а результатом должно быть что-то другое.Идеальным сценарием будет полная работа для языка CLIPS.Например, когда я пишу «4», он получает синтаксическую ошибку.Чтение моего кода, возможно, поможет вам лучше понять это.Если я напишу «test 3 4», он не показывает синтаксическую ошибку, но считает ее неизвестным токеном, и это снова неправильно .. Я полностью потерян.код является прототипом школы, и нам нужно внести некоторые изменения.Если у вас есть какие-либо вопросы, не стесняйтесь спрашивать.Благодарю вас!PS: не возражайте против комментариев, они на греческом языке.КОД ФЛЕКСА:

%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 Ответ

3 голосов
/ 16 июня 2019
  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 предупредить меня, если есть какой-то возможный ввод, не соответствующий ни одному правилу.

...