Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/apache/9.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++;来源:如何在lex/yacc中指定令牌边界/交互? 我想解析一些C++代码,作为指导,我一直在这里查看C Lex/YACC定义:_C++_C_Parsing_Yacc_Bison - Fatal编程技术网

解析C/C++;来源:如何在lex/yacc中指定令牌边界/交互? 我想解析一些C++代码,作为指导,我一直在这里查看C Lex/YACC定义:

解析C/C++;来源:如何在lex/yacc中指定令牌边界/交互? 我想解析一些C++代码,作为指导,我一直在这里查看C Lex/YACC定义:,c++,c,parsing,yacc,bison,C++,C,Parsing,Yacc,Bison,我了解令牌本身的规范,但不了解它们如何交互。例如,在不插入空格的情况下,让诸如=之类的运算符直接跟随标识符是可以的(即“foo=”),但让数字常量紧跟标识符(即123foo)是不可以的。然而,我看不出这样的规则有任何体现 我错过了什么?。。。或者这个lex/yacc在接受错误方面过于自由。本质上是每个标记类型的词汇规则都是贪婪的。例如,字符序列foo=不能解释为单个标识符,因为标识符不包含符号。另一方面,123abc实际上是一个数值常量,尽管格式不正确,因为数值常量可以以字母字符序列结尾,用于表

我了解令牌本身的规范,但不了解它们如何交互。例如,在不插入空格的情况下,让诸如=之类的运算符直接跟随标识符是可以的(即“foo=”),但让数字常量紧跟标识符(即123foo)是不可以的。然而,我看不出这样的规则有任何体现


我错过了什么?。。。或者这个lex/yacc在接受错误方面过于自由。

本质上是每个标记类型的词汇规则都是贪婪的。例如,字符序列
foo=
不能解释为单个标识符,因为标识符不包含符号。另一方面,
123abc
实际上是一个数值常量,尽管格式不正确,因为数值常量可以以字母字符序列结尾,用于表示数值常量的类型

lexer将字符流转换为令牌流(我认为这就是您所说的令牌规范)。语法指定可接受的标记序列。因此,你不会看到某些事情是不允许的;你只看到允许的东西。这有意义吗

编辑

如果要让lexer区分序列“123foo”和序列“123foo”,一种方法是为“123foo”添加一个规范。另一种方法是将空间视为有意义的

EDIT2


语法错误可以从lexer、语法产品或编译器的后期“检测到”(比如说,类型错误,它们仍然是“语法错误”)。我认为,整个编译过程的哪个部分检测到哪个错误在很大程度上是一个设计问题(因为它会影响错误消息的质量)。在给定的示例中,通过对无效令牌进行标记化来取缔“123foo”可能更有意义,而不是依赖于不存在带有数字文本后跟标识符的产品(至少,这是gcc的行为)。

lexer可以使用123foo并将其拆分为两个令牌

  • 整型常数
  • 和一个标识符
但是试着在语法中找到允许这两个标记像那样并排放置的部分。因此,我打赌lexer在看到这两个令牌时会产生错误

注意lexer不关心空格(除非您明确告诉它)。在这种情况下,它只是将空白区域扔掉:

[ \t\v\n\f]     { count(); } // Throw away white space without looking.
只是为了检查这是我构建的:

wget http://www.lysator.liu.se/c/ANSI-C-grammar-l.html > l.l
wget http://www.lysator.liu.se/c/ANSI-C-grammar-y.html > y.y
已编辑的文件l.l在编译器中停止,抱怨未声明的函数:

#include "y.tab.h"

// Add the following lines
int  yywrap();
void count();
void comment();
void count();
int  check_type();
// Done adding lines

%}
创建以下文件:main.c:

#include <stdio.h>

extern int yylex();

int main()
{
    int x;
    while((x = yylex()) != 0)
    {
        fprintf(stdout, "Token(%d)\n", x);
    }
}

是的,它把它分成两个标记。

< p>你不能用LeX和YACC解析C++,因为它是一个模糊的语法。您需要一个更强大的方法,例如GLR或一些HACKISH解决方案,它在运行时修改Listar(这就是当前大多数C++解析器所做的)。
看看Elsa/Elkhound。

啊,你不是说“123foo”被直接禁止,而是说即使是“123foo”也不合法,是吗?我想我有点被你的问题弄糊涂了。“123foo”可能甚至没有将lex作为单个标记(在lex规范中没有接受123foo的表达式)。但其思想是,指定了可接受的标记,并且所有与规范不匹配的内容都是不可接受的。确切地说,123foo(我认为)将被作为两个独立的标记进行分析,123和foo。这就是我的观点,当有中间空白但没有中间空白时,它如何“知道”在“123”之后加上“foo”是有效的。但我明白,不是词法分析器知道这一点,而是语法。@Greencpp:你为什么希望它在词法分析器阶段拒绝123foo?严格来说,
123abc
是无效的c++03,但有效的c++0x,因为c++0x有一个用户定义的文字功能(),我认为数字后面只允许有限的字母,即[uUlL]... 你是说规范比这更通用吗?我很确定链接到lex规范实际上会将
123foo
标记为一个后跟标识符的常量,而不是一个单独的(格式错误的)常量。假设在c++03中,我有一个类似
123ublabla
的源序列,这可能被含糊不清地解释为文字
123
,后跟标识符
ublabla
,这可能就是它的意思,但由于lexer是贪婪的,它将被解释为
123u
blablablabla
。基本上不可能证明这是好的,因此文字可能以类似标识符的序列结束,并作为单独的步骤进行验证/评估。我认为这是一个故意的吗?选择是否在lexer中执行贪婪匹配(只是大多数语言都会贪婪地匹配)。没错,我对空格的存在感到不安,但无论如何它都是无效的。如果标记在语法中不匹配,lex生成的部分不会抱怨;yacc生成的部件将被删除。@Greencpp:What's invalid。它是一个完全有效的令牌流(因为lexer不关心语法)。但是它是语法错误,因此分析器应该抱怨。你在我“想要解析一些C++代码”。BiSon支持GLR,所以它适合于解析C++。不要混淆在处理真实C++代码方面做“原始解析”的能力。您还需要名称和类型解析以及许多其他内容。C++14标准已经过时;把所有这些都考虑在内,这真是“吉诺莫斯”的好运气。(我的公司提供了一个完整的C++11和C++14解析器,因此可能会被指责有偏见;请注意,我的公司已经开发了十多年。)@IraBaxter,在
$ bison -d y.y
y.y: conflicts: 1 shift/reduce
$ flex l.l
$ gcc main.c lex.yy.c
$ ./a.out
123foo
123Token(259)
fooToken(258)