Синтаксическая ошибка в компиляторе с использованием flex и bison - PullRequest
0 голосов
/ 25 января 2020

Прежде всего, я очень новичок в flex и bison, и я действительно не могу решить эту проблему.

Я создал файлы flex и bison, и компиляция работает нормально. и мои файлы flex и bison

(ps комментарии на французском) Flex:

%{
// Définitions en language C
#include"minilang.tab.h"
extern int yylval;
extern int nbrligne;
%}

    // les définitions des expressions régulières

    /*
    Définitions de la partie 
    "Liste Declarations" du language MiniLang
    qui inclut les déclarations du language Minilang
    */

chiffre [0-9]
vide [ \t]+|" "+
saut_ligne [\n]+

    // les Nombres (valeurs)
integer [- | +]?([1-9][0-9]*|0)
float [- | +]?([1-9][0-9]*|0)\.[0-9]*[1-9]
bool ("true"|"false"|"TRUE"|"FALSE")
constant integer|float

    // Définitions
varint "INT"|"int"
varfloat "FLOAT"|"float"
varbool "bool"|"BOOL"
const "CONST"|"const"
comment "{"[^}]*"}"

    // Déclarations des éléments du language

    // IDF à revoir
idf ([A-Z]([_]?[a-z0-9])*){1,11}
affectation "="
semicolon ";"
vg ","
plus "++"
minus "--"
beginmc "begin"|"BEGIN"
end "end"|"END"

    /*
    Définitions de la partie 
    "List Instructions" du language MiniLang
    qui inclut les instructions du language Minilang
    */

    // Affectation
op "+"|"-"|"*"|"/"|"&&"|"||"

    // Condition if
if "if"|"IF"|"If"
comp "=="|"<"|"<="|"<>"|">"|">="

    // For loop
for "for"|"FOR"

    // Common
paropen "("
parclose ")"
curlopen "{"
curlclose "}"

%%
    // Expression Régulière { Action C}
{chiffre} {return token_chiffre;}
{vide}
{saut_ligne} {nbrligne++;}
{integer} { yylval = atoi(yytext); return token_integer;}
{float} { yylval = atof(yytext); return token_float;}
{bool} {return token_bool;}
{varint} {return token_varint;}
{varfloat} {return token_varfloat;}
{varbool} {return token_varbool;}
{const} {return token_const;}
{comment} {return token_comment;}

{idf} {return token_idf;}

{affectation} {return token_affectation;}
{semicolon} {return token_semicolon;}
{vg} {return token_vg;}
{plus} {return token_plus;}
{minus} {return token_minus;}
{beginmc} {return token_begin;}
{end} {return token_end;}
{op} {return token_op;}
{if} {return token_if;}
{comp} {return token_comp;}
{for} {return token_for;}
{paropen} {return token_paropen;}
{parclose} {return token_parclose;}
{curlopen} {return token_curlopen;}
{curlclose} {return token_curlclose;}
{constant} {return token_constant;}
. {printf("\nErreur lexicale a la ligne %d ",nbrligne);}
%%

и bison:

%{
#include <stdio.h>
#include<stdlib.h>

int nbrligne=0;
int yylex();
void yyerror(const char *s);
%}

// Token definitions
%token token_chiffre
%token token_vide
%token token_integer
%token token_float
%token token_bool
%token token_varint
%token token_varfloat
%token token_varbool
%token token_const
%token token_comment
%token token_idf
%token token_affectation
%token token_semicolon
%token token_vg
%token token_plus
%token token_minus
%token token_begin
%token token_end
%token token_op
%token token_if
%token token_comp
%token token_for
%token token_paropen
%token token_parclose
%token token_curlopen
%token token_curlclose
%token token_constant

%%

Prog: DecList token_begin InstList token_end|;

DecList: Declaration DecList|Declaration | token_comment DecList | token_comment;

Declaration: ConstIntDec | ConstFloatDec | ConstBoolDec | IntDec | FloatDec | BoolDec;

ConstIntDec: token_const token_varint MultiIdfInt token_semicolon;

ConstFloatDec: token_const token_varfloat MultiIdfFloat token_semicolon;

ConstBoolDec: token_const token_varbool MultiIdfBool token_semicolon;

IntDec: token_varint MultiIdfInt token_semicolon;
FloatDec: token_varfloat MultiIdfFloat token_semicolon;
BoolDec: token_varbool MultiIdfBool token_semicolon;

MultiIdfInt: token_idf token_vg MultiIdfInt | token_idf | token_idf token_affectation token_integer MultiIdfInt ;

MultiIdfFloat: token_idf token_vg MultiIdfFloat | token_idf | token_idf token_affectation token_integer MultiIdfFloat ;

MultiIdfBool: token_idf token_vg MultiIdfBool | token_idf | token_idf token_affectation token_integer MultiIdfBool ;


InstList: Instruction InstList | Instruction | token_comment InstList | token_comment;

Instruction: Boucle | Affectation | Condition;

Affectation: token_idf token_affectation Exp token_semicolon | Incrementation;

Incrementation: token_constant token_plus | token_constant token_minus;

Exp: token_idf token_op Exp | token_idf | ExpConst;

ExpConst: token_integer token_op ExpConst | token_float token_op ExpConst | token_bool token_op ExpConst 
|   token_bool 
|   token_constant;

Condition: token_if token_paropen ExpCond token_parclose token_curlopen InstList token_curlclose;

ExpCond: token_idf token_comp token_idf 
|   token_idf token_comp token_constant
|   token_idf token_comp token_bool
|   token_constant token_comp token_idf
|   token_bool token_comp token_idf
|   token_constant token_comp token_constant
|   token_bool;

Boucle: token_for token_paropen Affectation token_vg ExpCond token_vg Incrementation token_parclose token_curlopen InstList token_curlclose;









%%

#include"lex.yy.c"
int main() {
    yyparse();
    return yylex();
}

void yyerror(const char *s){ printf("\nERROR %d\n",nbrligne); }
int yywrap(){ return 1; }

// int yywrap(void){
//  return 1;
// }

А вот команды, которые я выполнил чтобы скомпилировать их оба и выполнить компилятор

flex minilang.l
bison -d minilang.y
gcc -o compiler minilang.tab.c

test.minilang - это файл, который я создал, который должен быть тем же языком, который должен интерпретировать этот компилятор, вот его содержимое

int K_ms;
BEGIN
K_ms=16;
END

ошибка, создаваемая этим кодом: «ОШИБКА 1», что означает, что это произошло в первой строке, и я не понимаю, где в моем коде ошибка, язык должен выглядеть следующим образом:

// List of Variable Declarations
BEGIN
// List of Instructions
END

1 Ответ

2 голосов
/ 26 января 2020

Я сейчас не за компьютером, поэтому собираюсь ответить на немного другой вопрос: "Как я могу отладить мой анализатор?"

Много это просто здравый смысл, и он применим к любому инструменту или библиотеке, с которыми вы не знакомы. Но есть также некоторые функции Flex и Bison, которые могут быть действительно полезными.

Итак, мы можем начать с самого очевидного совета: иметь под рукой документацию. Вполне возможно, что у вас действительно есть это на вашем компьютере, если вы используете unix -подобную операционную систему. Правильная установка flex и bison должна включать файлы, необходимые для использования инструмента info. Так что вы можете попробовать набрать

info flex # or info bison

и посмотреть, дает ли это вам руководство. Если нет, вы можете прочитать те же самые документы в Интернете (хотя убедитесь, что ваша версия flex / bison соответствует). Вы найдете их в

Оба эти руководства есть разделы по отладке.

Следующий общий совет: начните с малого и продолжайте свой путь. Не пишите несколько сотен строк кода, используя инструмент, с которым вы не знакомы, и только после этого начинайте тестирование. Начните с самого маленького кусочка, который выполняет то, что вы можете проверить, и проверьте его, прежде чем добавлять дополнительные сложности. Это не только поможет вам решить ваши собственные проблемы; это также поможет вам описать вашу проблему, когда вам нужно обратиться за помощью.

В случае синтаксического анализатора понятно, как начать с малого: начните с лексера и убедитесь, что он разбивает ваш ввод на токены, как и будет ожидать ваша грамматика.

Если вы Если вы собираетесь использовать Flex с Bison, вам нужно написать небольшую часть вашего файла Bison: достаточно, чтобы Bison создал файл заголовка. Для сканеров Flex этот заголовочный файл необходим, поскольку он определяет enum константы, которые вы будете возвращать анализатору, а также объявляет semanti c type YYSTYPE и переменную yylval, используемую для передачи семантики каждого токена * 1066. * ценность. (В руководстве Bison есть целая глава о значениях semanti c, в которой объясняется, как объявлять и использовать значения токенов.)

Вы можете легко протестировать свой лексер, используя флаг -d для Flex, который будет заставить сгенерированный сканер печатать отладочную информацию для каждого сопоставленного шаблона (независимо от того, возвращает ли сканер токен). Вы можете скомпилировать сканер с помощью -lfl; эта библиотека включает в себя простой main, который просто вызывает сканер несколько раз, пока он не сообщит о EOF.

Вы обязательно должны сделать этот шаг, потому что ваш сканер Flex имеет несколько ошибок, которые не связаны с вашим вопросом, но которые приведут к проблемы позже. Вы можете обратиться к главе «Шаблоны» в руководстве по Flex.

После того, как ваш сканер заработает, вы можете начать работу со своим анализатором. Как и Flex, Bison предлагает механизм отладки, который окажется очень полезным. Для его использования требуются лишь очень незначительные изменения:

  • Сначала добавьте флаг -t (trace) к вашему вызову Bison. Это будет включать код для генерации трасс отладки. Но вам все равно нужно запустить трассировку.

  • Добавьте следующее в вашу функцию main() перед вызовом yyparse:

    #if YYDEBUG
      yydebug = 1;
    #endif
    

    Проверка препроцессора необходимо, потому что yydebug не существует, если парсер не был сгенерирован с флагом -t. Возможно, вы захотите сделать настройку yydebug условной для флага командной строки или переменной среды, чтобы включить или отключить отладку без перекомпиляции.

Информация об отладке Bison может быть немного сначала ошеломляюще, но это не так сложно. Это поможет иметь под рукой конечный автомат; Bison генерирует текстовую версию, если вы используете флаг -v. (Он также может нарисовать конечный автомат, используя Graphviz, но кроме игрушечных грамматик с только четырьмя или пятью производствами, графика c в основном непригодна.)

...