首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Bison/yacc解析器在未用空格分隔时跳过语法-“意外的$end”

Bison(或yacc)是一种用于创建语法分析器的工具,它将上下文无关文法转换为LALR(1)或GLR(通用递归下降)解析器。当使用Bison/yacc解析器时,如果输入的代码没有正确地用空格或其他分隔符分隔,解析器可能会遇到语法错误,例如“意外的$end”。

基础概念

  • 上下文无关文法(CFG):这是一种形式文法,用于描述编程语言的语法结构。
  • LALR(1)解析器:这是一种自底向上的解析技术,它使用一个状态机来跟踪可能的解析路径,并且能够处理大多数常见的编程语言语法。
  • $end:在Bison/yacc中,$end是一个特殊的符号,表示输入的结束。

问题原因

当Bison/yacc解析器遇到“意外的$end”错误时,通常是因为解析器在期望更多输入时到达了文件的末尾。这可能是由于以下原因造成的:

  1. 缺少分隔符:代码行之间没有足够的空格或其他分隔符,导致解析器无法正确地将输入分割成标记(tokens)。
  2. 语法错误:代码中存在语法错误,使得解析器无法按照预期的语法规则进行解析。
  3. 输入不完整:输入文件可能在预期的结束之前就被截断了。

解决方法

要解决这个问题,可以尝试以下步骤:

  1. 检查代码格式:确保代码中的每个语句都以适当的分隔符(通常是分号;)结束,并且代码块之间有适当的缩进和空格。
  2. 使用词法分析器(Lexer):确保有一个正确的词法分析器来处理输入,将其分割成有意义的标记。Bison/yacc通常与Flex(或lex)一起使用,后者是一个词法分析器生成器。
  3. 检查输入完整性:确保输入文件没有损坏或不完整。
  4. 调试输出:使用Bison/yacc提供的调试选项来查看解析器在遇到错误之前的状态,这有助于定位问题所在。

示例代码

以下是一个简单的Bison/yacc语法规则示例,用于解析基本的算术表达式:

calc.y

代码语言:txt
复制
%{
#include <stdio.h>
int yylex(void);
void yyerror(const char *s);
%}

%token NUMBER
%left '+' '-'
%left '*' '/'

%%

expression:
    NUMBER
    | expression '+' expression
    | expression '-' expression
    | expression '*' expression
    | expression '/' expression
    ;

%%

void yyerror(const char *s) {
    fprintf(stderr, "Error: %s\n", s);
}

int main(void) {
    yyparse();
    return 0;
}

calc.l

代码语言:txt
复制
%{
#include "calc.y"
%}

%%

[ \t\n] ; /* skip whitespace */

[0-9]+ { yylval = atoi(yytext); return NUMBER; }

. { yyerror("unexpected character"); }

%%

int yywrap(void) {
    return 1;
}

参考链接

通过上述步骤和示例代码,你应该能够诊断并解决Bison/yacc解析器在未用空格分隔时跳过语法的问题。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

bison解析中lookahead前瞻工作原理

https://www.gnu.org/software/bison/manual/bison.html#Algorithm 1 lookahead token 学习yacc后一直有一个疑问,reduce...遇到匹配的规则立即执行reduce吗?还是在等一等看看后面的token,可能匹配上其他的规则? bison行为: bison解析器并不是遇到栈顶的一组token匹配上规则后,立即执行recude。...因为这种简单的策略不能满足一些复杂语言的需要。 bison解析器在发现一次匹配后,会继续向前看一个lookahead,再决定做什么。...| "number" ; 当1+2进入语法树时,如果不向前看一个token,会发生的问题: 1 + 2 ) \ / 1 + 2 reduce为...· 每次读lookahead时,状态机的状态 和 lookahead一并去 “table”里面查出来一条转移指令。 转移指令可能是shift:解析器堆栈入栈。

1.5K70

Yacc 与 Lex 快速入门(词法分析和语法分析)

Yacc Yacc 代表 Yet Another Compiler Compiler。 Yacc 的 GNU 版叫做 Bison。...如果你在查看标记序列,你可能想在这一序列出现时执行某一动作。 这种情况下有效序列的规范称为语法。Yacc 语法文件包括这一语法规范。 它还包含了序列匹配时你想要做的事。...用 Yacc 来创建一个编译器包括四个步骤: 通过在语法文件上运行 Yacc 生成一个解析器。 说明语法: 编写一个 .y 的语法文件(同时说明 C 在这里要进行的动作)。...它们是:声明、语法规则和 C 代码。 我们将解析一个格式为 姓名 = 年龄 的文件作为例子,来说明语法规则。 我们假设文件有多个姓名和年龄,它们以空格分隔。...在看 Yacc 程序的每一段时,我们将为我们的例子编写一个语法文件。 C 与 Yacc 的声明 C 声明可能会定义动作中使用的类型和变量,以及宏。 还可以包含头文件。

5.9K20
  • 如何愉快地写个小parser

    (一) 在前几日的文章『软件随想录』里,我随性写了一句:「现在似乎已经不是lex/yacc 或 bison/flex的时代了。...parsing(yacc/bison)只是更好的文本处理工具(parser),是个高效处理带有语法的文本的DSL(Domain Specific Language)!...其主体代码还是很清晰的,一个 server {…} 就用 SERVER OP({) exp_list CP(}) 这样一条规则匹配,当解析器碰到 exp_list 这样一个它无法认识的内容时,它会寻找名为...从上面的编译过程里,你可以看到,flex/bison是一个C语言的DSL。因此,你可以在处理词法和语法的过程中嵌入C代码,处理(transform)你需要的结果。...当你使用flex/bison在make和editor之间来回切换,郁闷地寻找语法定义问题的时候,你就知道一个REPL是多么地重要了!

    3.2K100

    自制计算器——《自制编程语言》二

    《自制计算器(借助yacc和lex)—《自制编程语言》一》 本文介绍下不用yacc和lex的实现过程,其实就是自己编写词法解析器和词法分析器来代替yacc和lex。...完整代码如下: 根据语法图可以看到,当命中非终结符时,会通过递归的方式调用其下级函数,因此这种解析器称为递归下降解析器。 自此,语法解析器已经完成。 parser.h: ?...LL(1)解析器所能解析的语法叫作LL(1)语法。 Pascal语法采用的就是LL(1) LL(1)解析器在语法上需要非终结符与解析器内部的函数一一对应。...BNF这样的语法称为左递归,原封照搬左递归的语法规则是无法实现递归下降分析的。 yacc生成的解析器称为LALR(1)解析器,这种解析器能解析的语法称为LALR(1)语法。...在C语言中,如果是通过typedef命名的一些类型,其标识符yacc(LALR(1)解析器)是无法解析的。

    1.6K20

    Python 之父撰文回忆:为什么要创造 pgen 解析器?

    在这篇旧文里,Guido 回忆了他创造 pgen 时的一些考量,在当时看来,创造一个新的解析器无疑是明智的,只不过时过境迁,现在有了更好的选择罢了。...之所以我要写自己的语法分析生成器,原因是当时这玩意(我熟悉的)相当稀少——基本上就是用 Yacc(有个 GNU 的重写版,叫作 Bison(译注:美洲野牛),但我不确定那时的自己是否知道);或者是自己手写一个...至于词法分析器(lexer),我决定不使用生成器——我对 Lex 的评价要比 Yacc 低得多,因为在尝试扫描超过 255 个字节的标记符时,我所熟悉的 Lex 版本会发生段错误(真实的!)。...所以我使用正则表达式的原因,很可能是为了使语法更易于阅读:在使用了必要的重写以解决冲突之后,我发现语法不是那么可读(此处应插入《Python 之禅》的说法 :-) ,而正则表达式则更符合我对于经典语言的语法的看法...如果让我重做一遍,我可能会选择一个更强大的解析引擎,可能是 LALR(1) 的某个版本(例如 Yacc/Bison)。

    1.4K30

    借助yacc和lex自制计算器——《自制编程语言》一

    执行语法分析的程序称为解析器(parser),yacc就是能根据语法规则自动生成解析器的程序 yacc和lex在mac上已经预装。...在规则区块中遵循如下的书写方式:一个正则表达式的后面紧跟若干个空格,后接C代码。如果输入的字符串匹配正则表达式,则执行后面的C代码。...yacc的规则区块由语法规则以及C语言编写的相应动作两部分构成。 语法规则     在yacc中,会使用类似BNF(巴克斯范式)的规范来编写语法规则。...即yacc输出解析器的代码时,栈中相应位置的元素会转换为一个能表达元素特征的数组引用。这里的2是乘法运算符(*),并不存在记号值,所以这里引用2的话会报错。   ...所谓冲突,就是遇到语法中模糊不清的地方时,yacc报出呃错误。

    4.6K10

    再探 Parser 和 Parser Combinator

    我们之前用的 BNF 工具(比如 Flex/Bison)用于撰写解析 CFG。PEG 和 CFG 的主要区别是:PEG 会在语法歧义发生时总选择第一个匹配项,而 CFG 则是未定义的。...我采用了自顶向下的方式来描述这个语法。首先,我让所有的空格自动解析,自动忽略。...剩下的我就不一一赘述了,很好理解。 我们可以看到,pest 声明的语法结构和 Bison 很像。...@{}:如果规则前加 @,意味着这是原子规则(atomic rule),里面的空格需要被显式定义,且其子规则不会生成在语法树中。...{}:如果规则前加 ,意味着这是复合原子规则(compound atomic rule),里面的空格需要给显式定义,但子规则会生成在语法树中。

    2.4K10

    编译入门 - 从零实现中文计算器

    如果再复杂一点可能会加上语义分析等其他步骤,比如 {a = 1; let a} 这行代码,它的语法是对的,但是它的语义是错的,因为在 a 初始化之前访问了 a。...yacc生成的编译器主要是用C语言写成的语法解析器,需要与词法解析器Lex一起使用,再把两部分产生出来的C程序一并编译。...GNU bison(Bison意为犎牛;而Yacc与意为牦牛的Yak同音)是一个自由软件,用于自动生成语法分析器程序,实际上可用于所有常见的操作系统。...GNU bison基本兼容Yacc,并做了一些改进。它一般与flex一起使用。 上面介绍了几个有名的工具,这些工具在其他语言中都有对应的类库,比如 JS 中的 bison 叫 jison。...语法分析也只做一件的事,就是把词法分析生成的单词流,转换成抽象语法树。 但是在语法分析之前,我们还需要了解一些概念。

    78510

    TiDB SQL Parser 的实现

    的Golang版,所以要想看懂语法规则定义文件parser.y,了解解析器是如何工作的,先要对Lex & Yacc有些了解。...Spark的SQL解析就是使用了ANTLR。Lex & Yacc 相对显得有些古老,实现的不是那么优雅,不过我们也不需要非常深入的学习,只要能看懂语法定义文件,了解生成的解析器是如何工作的就够了。...= atoi(yytext); return INTEGER; } /* 操作符 */ [-+()=/*\n] { return *yytext; } /* 跳过空格...,我们可以看到,每个规则关联的动作不再是求值,而是调用相应的函数,该函数会返回抽象语法树的节点类型 nodeType,然后将这个节点压回堆栈,解析完成时,我们就得到了一颗由 nodeType 构成的抽象语法树...和 Yacc的功能一样,goyacc 根据输入的语法规则文件,生成该语法规则的go语言版解析器。

    61110

    【Python】Ply 简介

    Ply 是一个纯 python 的词法分析和语法分析库,包括两个模块:lex 和 yacc Ply Ply 是一个纯 python 的词法分析和语法分析库,包括两个模块:lex 和 yacc lex 用于将输入的文本通过正则表达式转换为一系列...def t_CHAR(t): r'[a-zA-Z_][a-zA-Z_0-9]*' t.type = reserved2.get(t.value,'ID') return t 跳过空格之类无意义的填充符号有时也是非常必要的...# or parser = yacc.yacc(start="foo") 移入/规约 上面给出的语法规则是经过规约的规则,对解析器来说,它更容易处理,因为它几乎不存在歧义,但从编程的角度来说,我们可能会以一种更符合人类直觉的方式定义语法规则...在进行语法分析时,将会按以下具体规则通过优先级解决冲突问题: 如果当前 TOKEN 优先级小于堆栈上的优先级,进行规约,例如堆栈上是 expr * expr 优先级由 * 决定就是 2,当前 TOKEN...解析器是依赖堆栈工作的,阅读时注意栈顶在靠右 文件中用 ! 标注出了冲突的地方,虽然这些冲突不见得都是不好的。

    2.8K30

    TiDB 源码阅读系列文章(五)TiDB SQL Parser 的实现

    的 Golang 版,所以要想看懂语法规则定义文件 parser.y,了解解析器是如何工作的,先要对 Lex & Yacc 有些了解。...Lex & Yacc 相对显得有些古老,实现的不是那么优雅,不过我们也不需要非常深入的学习,只要能看懂语法定义文件,了解生成的解析器是如何工作的就够了。...= atoi(yytext); return INTEGER; } /* 操作符 */ [-+()=/*\n] { return *yytext; } /* 跳过空格...,我们可以看到,每个规则关联的动作不再是求值,而是调用相应的函数,该函数会返回抽象语法树的节点类型 nodeType,然后将这个节点压回堆栈,解析完成时,我们就得到了一颗由 nodeType 构成的抽象语法树...和 Yacc 的功能一样,goyacc 根据输入的语法规则文件,生成该语法规则的 go 语言版解析器。

    4.6K100

    RPC的实现

    4. flex和bison 经典的lex和yacc由贝尔实验室在1970年代开发,flex和bison是它们的现代版本。...《lex & yacc》的续篇。...准备概念 在阅读后续章节时,最好对以下几个概念有些了解,当然不了解也成,但可能会有些懵懂。本节是全文最晦涩的部分,可以尝试跳过本节往后看,或者有需要时再回头看看,但最终还是需要了解的。...记号的编号在bison编译时自动按顺连续分配,最小值从258开始。之所以从258开始,是因为258之前的数值是ACSII字符的值。 4.1.5. ...不管是flex还是bison,在规则部分都可以添加注释,但两者方式有不同之处: 1) flex 注释不能顶格写,“/*”前至少要有一个空格或Tab,“*/”可以顶格,还可以与“/*”不在同一行

    1.6K30

    (1)PHP内核 - 玩转php的编译与执行

    词法分析就是将分割出来的token再按照语法规则重新组合到一起。PHP内词法分析和语法分析分别使用的是re2c和yacc来完成的。其实准确来说一个应该是re2c和bison。...放到后面语法分析用来存储token的栈中,这个类型在yyac匹配语法时的指定为YYSTYPE,在匹配语法会根据定义的%type,转化为指定zend_parser_stack_elem中的一种类型。...&& bison 接下来就是yacc语法分析器,yacc对应的功能函数在php里面为zendparse(),这个函数其实预处理自动生成的,在这个函数通过不断的调用lex_scan返回token,根据定义的语法规则动态的生成抽象语法数...如果你真的想看看yacc内部扫描语法的,不要去看经过bison预处理之后的.c文件,同级目录下有一个.output后缀相同文件名的文件,里面描述了yacc里面的状态机是如何工作的。...抽象语法树其实是和它们耦合在一起的,虽然把编译器和执行器隔开了。re2c在返回的token对应的值的时候,就是以抽象语法树节点返回的。再通过yacc语法分析进一步建立完整的抽象语法树。

    1.9K10

    浏览器运行原理

    解析器一般将工作分配给两个组件——词法分析器(有时也叫分词器)负责将输入分解为合法的符号,解析器则根据语言的语法规则分析文档结构,从而构建解析树,词法分析器知道怎么跳过空白和换行之类的无关字符。...解析过程是迭代的,解析器从词法分析器处取到一个新的符号,并试着用这个符号匹配一条语法规则,如果匹配了一条规则,这个符号对应的节点将被添加到解析树上,然后解析器请求另一个符号。...自动化解析(Generating parsers automatically) 解析器生成器这个工具可以自动生成解析器,只需要指定语言的文法——词汇表及语法规则,它就可以生成一个解析器。...Webkit使用两个知名的解析生成器——用于创建语法分析器的Flex及创建解析器的Bison(你可能接触过Lex和Yacc)。...Flex的输入是一个包含了符号定义的正则表达式,Bison的输入是用BNF格式表示的语法规则。 HTML解析器(HTML Parser) HTML解析器的工作是将html标识解析为解析树。

    1.4K20

    懂前端的你也可以轻松定义自己业务的DSL

    通过使用 Jison,开发人员可以定义自己的模版语法规则,然后将其转换为解析器,从而实现对自定义模版语法的支持。...,然后计算结果,而是只用定义规则,剩下的事让机器帮你搞定就好了:cala.bison/* description: Parses end executes mathematical expressions...语法定义通常使用BNF或EBNF表示。2.实现DSL的解析器:DSL解析器是将DSL代码解析为计算机可执行的指令的程序。解析器通常使用词法分析器和语法分析器来实现。...其中词法分析器,语法分析器这些都有非常稳定的工具,比如,如果有定义好的BNF范式,直接丢给 flex 就可以解决词法分析的这个过程,然后在丢给 yacc,就可以按照这个规则编译出可执行程序,也许你会觉得这个非常不可思议...如果某个非终结符的所有产生式都是空规则,那么这个非终结符可以被省略,也就没有必要存在了。但是,如果存在空规则,那么在语法分析时需要进行特殊处理,增加算法的复杂度。因此,尽量避免使用空规则。

    2.5K41

    Python 之父的解析器系列之六:给 PEG 语法添加动作

    如果你在语法规则中还可以添加(某些)语义,那么语法就会更好。特别是对于我正在构建的 Python 解析器,我需要控制每个备选项返回的 AST 节点,因为 AST 的格式已经规定好。...一般而言,动作的语法如下: rule: item item item { action 1 } | item item { action 2 } 因为它会使语法变得冗长,所以解析器生成器通常支持跨行分割规则...一个永恒的问题是何时执行动作块。在 Yacc / Bison 中,因为没有回溯,一旦规则被解析器识别到,就会执行动作块。...在 PEG 解析器中,因为有无限回溯,我们有其它的选择: 延迟所有动作,直到解析完所有内容。这对我的目的没有用,因为我想在解析期间构造一个 AST。...当一个备选项中多次出现相同的规则名称时,我们该怎么办?对同一备选项中出现的规则,解析器生成器会给出唯一的名称,即在随后出现的规则上添加 1、2 等等。

    56720

    JavaScript 实现 JSON 解析器

    编写 JSON 解析器所需的知识和技术可以转移到编写 JS 解析器中。 因此,让我们开始编写 JSON 解析器! 理解语法 如果您查看了规范页面,会发现有2个图。 •左侧的语法图(或者铁路图): ?...一个是可视化的,另一个是基于文本的。基于文本的语法( Backus-Naur 形式)通常被提供给另一个解析器,该解析器解析该语法并为其生成一个解析器。?...如果要解析“空格”,我们需要查看空格的语法。 因此,对于一个对象,从左边开始第一个字符必须是一个左花括号。...中,我们将调用其他语法的解析,例如“字符串”和”空格”,当我们实现它们时,一切都会起作用?。...== '}') { 我们需要确保访问的字符不会超过字符串的长度。在这个例子中,这发生在字符串意外结束时,而我们仍然在等待一个结束字符“}”。

    3.5K30

    javacc功能一览

    从左到右(即,输入按读取的顺序处理)和R-最右派生 LL仅从堆栈的根非终结符开始。 LR在堆栈上仅以根非终结符结尾。 当堆栈为空时,LL结束。 LR从空堆栈开始。 LL扩展为非末尾。...LL读取终端时,将其弹出堆栈之一。 LR在将它们压入堆栈时读取端子。 LL使用分析树的预遍历。 LR使用解析树的后序遍历。 在LL解析器期间,解析器在两个动作之间连续选择。...预测:基于最左边的非终结符和一些先行标记。 匹配:将最左侧的猜测终端符号与输入的最左侧未使用符号匹配。 在LR解析器期间,解析器在两个动作之间连续选择。...javacc特征 •JavaCC生成自上而下的(递归下降[1])解析器,而不是类似YACC[2]的工具生成的自下而上的解析器。尽管不允许左递归[3],这允许使用更通用的语法。...自上而下的解析器还有许多其他优点(除了更通用的语法外),例如,调试起来更容易,能够解析到语法中的任何非终结[4]符,还可以向上传递值(属性)在解析期间在解析树中向下移动。

    2K10
    领券