[使用flex和bison制作的编译器中的语法错误

问题描述 投票:0回答:2

首先,我对flex和bison非常陌生,我似乎真的无法解决这个问题。

我已经创建了flex和bison文件,并且编译正常,这里是我的flex和bison文件

(ps注释为法语)弹性:

%{
// 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);}
%%

和野牛:

%{
#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

此代码产生的错误是“ ERROR 1”,这意味着它发生在第一行,我不知道我的代码中的错误在哪里语言应该看起来像这样:

// List of Variable Declarations
BEGIN
// List of Instructions
END
c syntax compiler-construction bison flex-lexer
2个回答
0
投票

您的问题在flex中,在这里:

idf ([A-Z]([_]?[a-z0-9])*){1,11}  

您需要将其更改为

idf ([A-Z]([_]?[a-z0-9])*) 

0
投票

我现在不在电脑前,所以我要回答一个稍有不同的问题:“我如何调试解析器?”

其中很多只是常识,适用于您不熟悉的任何工具或库的使用。但是Flex和Bison也有一些功能确实有用。

因此,我们可以从最明显的建议开始:轻松获取文档。如果您使用的是类似Unix的操作系统,则很可能实际上已经在计算机上安装了它。正确的flex和bison安装应包括使用info工具所需的文件。因此,您可以尝试输入

info flex # or info bison

然后看看是否能给您手册。如果没有,您可以在线阅读相同的文档(尽管请确保您的flex / bison版本匹配)。您可以在[]找到它们

[下一条一般建议:从小处着手,然后逐步提高。不要使用您不熟悉的工具编写数百行代码,然后才开始测试。从最小的东西开始,您可以做一些可以测试的事情,并在增加更多复杂性之前对其进行测试。这不仅可以帮助您解决自己的问题;当您需要帮助时,它还将帮助您描述问题。

在解析器的情况下,很清楚如何从小处开始:从词法分析器开始,并确保将其输入内容按语法期望的那样拆分为标记。

[如果要与Bison一起使用Flex,则将需要编写Bison文件的一小部分:刚好足以使Bison生成头文件。 Flex扫描程序需要此头文件,因为它定义了将要返回到解析器的enum常量,并声明了用于传递每个令牌的语义值的语义类型YYSTYPE和变量yylval。 (Bison手册中有一整章关于语义值的内容,解释了如何声明和使用令牌值。)

您可以通过在Flex上使用-d标志来轻松测试词法分析器,这将使生成的扫描程序为每个匹配的模式打印调试信息(无论扫描程序是否返回令牌)。您可以使用-lfl编译扫描器;该库包含一个简单的main,它仅反复调用扫描程序,直到报告EOF。

您绝对应该执行此步骤,因为您的Flex扫描仪有一些错误与您的问题无关,但稍后会引起问题。您可能要参考Flex手册中有关“图案”的章节。

一旦扫描仪开始工作,您就可以开始使用解析器了。像Flex一样,Bison提供了一种调试机制,这将非常有用。只需要很小的改动就可以使用它:

  • 首先,在您的Bison调用中添加-t(跟踪)标志。这将包括生成调试跟踪的代码。但是您仍然需要启动跟踪。

  • 在调用main()之前,将以下内容添加到yyparse函数中:

#if YYDEBUG
  yydebug = 1;
#endif

预处理器测试是必要的,因为除非使用yydebug标志生成解析器,否则-t不存在。您可能希望以命令行标志或环境变量为条件设置yydebug,以便无需重新编译即可打开或关闭调试。

Bison调试信息起初可能有点不知所措,但这并不复杂。方便使用状态机;如果使用-v标志,则Bison会生成文本版本。 (它也可以使用Graphviz绘制状态机,但是除了玩具语法只有四个或五个产品外,该图形基本上是不可用的。)

© www.soinside.com 2019 - 2024. All rights reserved.