Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 野牛意外代币_C_Bison_Flex Lexer - Fatal编程技术网

C 野牛意外代币

C 野牛意外代币,c,bison,flex-lexer,C,Bison,Flex Lexer,我正在创建bison/flex编译器,但遇到了一个问题。我添加了%glr解析器,但问题仍然存在。我有: 有一个简单的例子代表了我的问题 .y文件: %{ #include <stdio.h> #include <stdlib.h> extern FILE *yyin; extern int yylex(); int line=1; int error=0; #define YYERROR_VERBOSE

我正在创建bison/flex编译器,但遇到了一个问题。我添加了
%glr解析器
,但问题仍然存在。我有:

有一个简单的例子代表了我的问题

.y文件:

%{ 
    #include <stdio.h> 
    #include <stdlib.h> 
    extern FILE *yyin; 
    extern int yylex(); 
    int line=1; 
    int error=0; 
    #define YYERROR_VERBOSE 

    void yyerror(const char *msg) 
    { 
        error = 1; 
        printf("ERROR in line %d : %s.\n", line, msg); 
    } 
%}

%start programme
%token SP
%token CRLF
%token LETTER
%%

programme : id CRLF;

id : LETTER;

%%

int main(int argc, char *argv[])
{
    if(argc == 2) yyin = fopen(argv[1], "r");
    else if(argc < 2){
        printf("No file found.\n");
        return 0;
    } else printf("Only one file is permitted.\n");

    yyparse();
    if(error == 0) printf("Finished at %d line.\nNo errors!\n",line); 
    return 0; 
} 
我的程序得到一个.txt文件:

文件\u correct.txt包含:
A
在我的终端上,我写:

bison -d bison.y
flex myParser.l
gcc bison.tab.c lex.yy.c -lfl -o a
./a file_correct.txt
->第1行错误:语法错误,意外$undefined,应为字母


输入的
A\n
应该是正确的。相反,我有这样的信息。。你能帮我吗?

你必须使用bison生成的头文件。您可以将它包含到您自己的头文件中(尽管这没有什么实用价值),但您不能尝试自己编写它,并且希望它总是正确的

在本例中,
myparser.h
包含

enum yytokentype {
    SP = 259,
    LETTER = 260,
    CRLF = 261
};
这些是
yylex
将返回的令牌类型编号,因为在flex文件中,您包含了

但是,bison生成的文件
bison.tab.h
(以文本形式包含在
bison.tab.c
中)具有不同的值:

  enum yytokentype
  {
    SP = 258,
    CRLF = 259,
    LETTER = 260
  };
碰巧,
字母
在两个文件中的代码相同,但其他两个代码不同。特别是,当扫描器看到换行符时,它将返回261,但是解析器需要一个类型号为259的令牌。当它收到261时,它抱怨:

ERROR in line 2 : syntax error, unexpected $undefined, expecting CRLF.
(对于bison,代码261与任何内容都不对应,因此它将其报告为
$undefined

这与您在问题中报告的错误消息不同,可能是由于不同的野牛版本以不同的顺序对标记进行编号,也可能只是一个复制粘贴问题

底线是你应该始终

#include "bison.tab.h"
进入您的
.l
文件(根据您的项目更改名称,但始终使用bison生成的文件),而不是(或添加)您自己的头文件。(当然,如果您还插入了自己的头文件,则不应尝试定义令牌值。包含自己的头文件的原因是为扫描仪操作使用的自己的外部函数声明原型。)

总的来说,很少有空白(空格和换行符)应该传递给解析器的情况。(例外情况是,在一种语言中,语句肯定是以换行符而不是分号终止的。即使如此,您也不希望将空格传递给解析器。)在解析器中处理空白会产生比必要的多得多的工作;混淆语法;并可能导致不必要的转移,减少冲突

以简化语法产品为例:

decl: type SP id SEMICOLON
将匹配
inta,如预期。但它不符合以下任何条件:

int  a;
int a ;
  int a;
所有这些都可能出现在有效的程序中,因此用户会认为对空格的挑剔是一个问题。(让语法更加灵活将是一件痛苦的事。)

此外,您可能会考虑将其放在更广泛的背景下:

program: %empty
       | program decl CRLF
但是现在你的解析器会拒绝空行,这会进一步激怒你的用户。它也会拒绝

int a; int b;
这可能会让一些人想知道为什么需要分号

并注意以下根据编辑历史记录改编的错误:

prog: stmt
stmt: decl more
more: %empty | stmt CRLF more
这可能永远无法成功解析程序,因为所有程序文本都以换行符结尾,但语法只允许语句之间换行。因此,当解析器拼命寻找另一条语句时,文件末尾的换行符将导致语法错误


(上述代码片段最初可能是在误解消除左递归是个好主意的情况下编写的。至少如果您使用bison等LR解析器,情况并非如此。bison喜欢左递归,认为右递归最乏味。许多语法在左递归编写时可读性也更高。)

必须使用bison生成的头文件。您可以将它包含到您自己的头文件中(尽管这没有什么实用价值),但您不能尝试自己编写它,并且希望它总是正确的

在本例中,
myparser.h
包含

enum yytokentype {
    SP = 259,
    LETTER = 260,
    CRLF = 261
};
这些是
yylex
将返回的令牌类型编号,因为在flex文件中,您包含了

但是,bison生成的文件
bison.tab.h
(以文本形式包含在
bison.tab.c
中)具有不同的值:

  enum yytokentype
  {
    SP = 258,
    CRLF = 259,
    LETTER = 260
  };
碰巧,
字母
在两个文件中的代码相同,但其他两个代码不同。特别是,当扫描器看到换行符时,它将返回261,但是解析器需要一个类型号为259的令牌。当它收到261时,它抱怨:

ERROR in line 2 : syntax error, unexpected $undefined, expecting CRLF.
(对于bison,代码261与任何内容都不对应,因此它将其报告为
$undefined

这与您在问题中报告的错误消息不同,可能是由于不同的野牛版本以不同的顺序对标记进行编号,也可能只是一个复制粘贴问题

底线是你应该始终

#include "bison.tab.h"
进入您的
.l
文件(根据您的项目更改名称,但始终使用bison生成的文件),而不是(或添加)您自己的头文件。(当然,如果您还插入了自己的头文件,则不应尝试定义令牌值。包含自己的头文件的原因是为扫描仪操作使用的自己的外部函数声明原型。)

总的来说,很少有空白(空格和换行符)应该传递给解析器的情况。(例外情况是,在一种语言中,语句肯定是以换行符而不是分号结尾的。即使这样,您也不希望将空格传递给解析器。)