Parsing 在不依赖lexer规范的情况下生成一个解析器生成器的小型工作示例?

Parsing 在不依赖lexer规范的情况下生成一个解析器生成器的小型工作示例?,parsing,yacc,lex,Parsing,Yacc,Lex,是否可以使用yacc生成一个解析器生成器的小型工作示例,而不依赖lexer规范? 大多数教科书中的语法分析器规范都依赖于词法分析器,这使得语法分析器示例对于学生来说有点难以理解(imho)。如果“没有词法分析器规范”,您的意思是不从(f)lex规范生成词法扫描程序,那么您将在Bison手册中找到大量语法分析器示例。对于学生和新手来说,这是一个重要的(而且常常被忽视的)资源 如果你的意思是“没有lexer”,那么答案是“不”。Yacc(据我所知,它所有常用的派生工具)要求输入来自yylex外部函数

是否可以使用yacc生成一个解析器生成器的小型工作示例,而不依赖lexer规范? 大多数教科书中的语法分析器规范都依赖于词法分析器,这使得语法分析器示例对于学生来说有点难以理解(imho)。

如果“没有词法分析器规范”,您的意思是不从(f)lex规范生成词法扫描程序,那么您将在Bison手册中找到大量语法分析器示例。对于学生和新手来说,这是一个重要的(而且常常被忽视的)资源

如果你的意思是“没有lexer”,那么答案是“不”。Yacc(据我所知,它所有常用的派生工具)要求输入来自
yylex
外部函数。在正常情况下,yacc/byacc/bison生成的解析器根本不与stdio进行交互;它们依赖于
yylex
将输入分解为令牌,并依赖于
yyerror
处理错误消息

还有其他解析器生成器,它们要么内置词法分析,因此只有一个规范(尽管它通常分为两部分),要么生成“无扫描解析器”。这两种方法似乎都有自己的特点,可能会让学习者感到困惑,但我认为,如果不违反StackOverflow对基于观点的答案的告诫,就不可能充分讨论这一点。

如果说“没有词法分析器规范”,你的意思是不从a(f)生成词法扫描器lex规范,那么您将在Bison手册中找到大量的示例。对于学生和新手来说,这是一个重要的(而且常常被忽视的)资源

如果你的意思是“没有lexer”,那么答案是“不”。Yacc(据我所知,它所有常用的派生工具)要求输入来自
yylex
外部函数。在正常情况下,yacc/byacc/bison生成的解析器根本不与stdio进行交互;它们依赖于
yylex
将输入分解为令牌,并依赖于
yyerror
处理错误消息


还有其他解析器生成器,它们要么内置词法分析,因此只有一个规范(尽管它通常分为两部分),要么生成“无扫描解析器”。这两种方法似乎都有自己的特点,可能会让学习者感到困惑,但我认为,如果不违反StackOverflow对基于意见的答案的警告,就不可能充分讨论这一点。

在最简单的情况下,您可以编写一个简单的lexer,只从stdin读取单字符标记:

int yylex() {
    return fgetc(stdin);
}

然后,您需要编写一个解析器来读取每个字符,将数字和标识符等较大的“标记”构建为非终端,并显式跳过空白。这既不是有效的,也不是简单的,但对于理解解析来说是一个有用的练习。

在最简单的情况下,您可以编写一个简单的lexer,只从stdin读取单字符标记:

int yylex() {
    return fgetc(stdin);
}

然后,您需要编写一个解析器来读取每个字符,将数字和标识符等较大的“标记”构建为非终端,并显式跳过空白。这既不高效也不琐碎,但对于理解解析来说是一个有用的练习。

多亏了Bison文档。@rici谢谢。但是,您的示例似乎确实需要一个lexer。例如,第一个(反向波兰计算器)需要一个lexer来获取token NUM。有没有办法让解析器不用lexer?好的,我写了一个答案。我也投了结束票,因为(如我回答的第三段所述),我认为在SO的指导方针内不可能充分回答这个问题,因为这个问题(以及任何合理的答案)取决于一个高度有争议的意见。也许有一个公式适合这种情况。感谢Bison文档。@rici谢谢。但是,您的示例似乎确实需要一个lexer。例如,第一个(反向波兰计算器)需要一个lexer来获取token NUM。有没有办法让解析器不用lexer?好的,我写了一个答案。我也投了结束票,因为(如我回答的第三段所述),我认为在SO的指导方针内不可能充分回答这个问题,因为这个问题(以及任何合理的答案)取决于一个高度有争议的意见。也许有一个公式适合这种情况。