gpt4 book ai didi

c++ - Bison 在错误的行后输出字符串

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:04:41 24 4
gpt4 key购买 nike

输入

 1  -- Narrowing Variable Initialization  
2
3 function main a: integer returns integer;
4 b: integer is a * 2.;
5 begin
6 if a <= 0 then
7 b + 3;
8 else
9 b * 4;
10 endif;
11 end;

产生输出

  1  -- Narrowing Variable Initialization
2
3 function main a: integer returns integer;
4 b: integer is a * 2.;
5 begin
Narrowing Variable Initialization
6 if a <= 0 then
7 b + 3;
8 else
9 b * 4;
10 endif;
11 end;

而不是将该错误消息放在第 4 行下,这是实际发生错误的地方。我已经看了好几个小时了,还是想不通。

%union
{
char* ident;
Types types;
}

%token <ident> IDENTIFIER
%token <types> INTEGER_LITERAL
%token <types> REAL_LITERAL
%token BEGIN_
%token FUNCTION
%token IS
%token <types> INTEGER
%token <types> REAL
%token RETURNS

%type <types> expression
%type <types> factor
%type <types> literal
%type <types> term
%type <types> statement
%type <types> type
%type <types> variable

%%

program:
/* empty */ |
functions ;

functions:
function_header_recovery body ; |
function_header_recovery body functions ;

function_header_recovery:
function_header ';' |
error ';' ;

function_header:
FUNCTION {locals = new Locals();} IDENTIFIER optional_parameters RETURNS type {globals->insert($3,locals->tList);} ;

optional_parameters:
/* empty */ |
parameters;

parameters:
IDENTIFIER ':' type {locals->insert($1, $3); locals->tList.push_back($3); } |
IDENTIFIER ':' type {locals->insert($1, $3); locals->tList.push_back($3); } "," parameters;

type:
INTEGER | REAL ;

body:
optional_variables BEGIN_ statement END ';' ;

optional_variables:
/* empty */ |
variables ;

variables:
variable IS statement {checkTypes($1, $3, 2);} |
variable IS statement {checkTypes($1, $3, 2);} variables ;

variable:
IDENTIFIER ':' type {locals->insert($1, $3);} {$$ = $3;} ;

statement:
expression ';' |

...

Types checkTypes(Types left, Types right, int flag)
{
if (left == right)
{
return left;
}
if (flag == 1)
{
Listing::appendError("Conditional Expression Type Mismatch", Listing::SEMANTIC);
}
else if (flag == 2)
{
if (left < right)
{
Listing::appendError("Narrowing Variable Initialization", Listing::SEMANTIC);
}
}
return REAL_TYPE;
}

正在处理的打印:

void Listing::nextLine()
{
printf("\n");
if (error == "")
{
lineNo++;
printf("%4d%s",lineNo," ");
}
else
{
printf("%s", error.c_str());
error = "";
nextLine();
}
}

void Listing::appendError(const char* errText, int errEnum)
{
error = error + errText;

if (errEnum == 997)
{
lexErrCount++;
}
else if (errEnum == 998)
{
synErrCount++;
}
else if (errEnum == 999)
{
semErrCount++;
}
}

void Listing::display()
{
printf( "\b\b\b\b\b\b " );

if (lexErrCount + synErrCount + semErrCount > 0)
{
printf("\n\n%s%d","Lexical Errors ",lexErrCount);
printf("\n%s%d","Syntax Errors ",synErrCount);
printf("\n%s%d\n","Semantic Errors ",semErrCount);
}
else
{
printf("\nCompiled Successfully\n");
}
}

最佳答案

bison 就是这样工作的。它会生成一个单 token 先行解析器,因此您的生产操作不会被触发,直到它读取了生产之后的 token 。因此,必须在与 variables 关联的操作发生之前读取 begin。 (bison 从不尝试组合 Action ,即使它们在文本上是相同的。所以它真的不知道哪个 variables 生产适用以及要执行哪个 Action ,直到它看到以下标记。 )

有多种方法可以将行号和/或列位置与每个标记相关联,并在生成错误消息时使用该信息。通常,在输入文本中穿插错误和/或警告需要缓冲输入;对于语法错误,您只需要缓冲到下一个标记,但这不是通用的解决方案;例如,在某些情况下,您可能希望将错误与运算符相关联,但在解析运算符的尾随参数之前不会检测到错误。

正确地将错误/警告与源代码穿插在一起的一种简单技术是将所有错误/警告写入一个临时文件,将文件偏移量放在每个错误的前面。然后可以对该文件进行排序,然后可以重新读取输入,在适当的位置插入错误消息。这种策略的好处是它避免了必须为每个错误维护行号,这会显着减慢词法分析。当然,如果您允许像 C 的 #include 这样的构造,它就不会那么容易工作。

因为生成良好的错误消息很困难,而且即使跟踪位置也会大大降低解析速度,所以有时我会使用在检测到错误时解析输入两次的策略。第一个解析只检测错误,如果它不能做任何更合理的事情,就会提前失败;如果检测到错误,则会使用更精细的解析器重新解析输入,该解析器会仔细跟踪文件位置,甚至可能使用缩进深度等启发式方法来尝试生成更好的错误消息。

关于c++ - Bison 在错误的行后输出字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15072799/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com