首页
学习
活动
专区
工具
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.6K20
  • 如何愉快地写个小parser

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

    3.1K100

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

    《自制计算器(借助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和lexmac上已经预装。...规则区块中遵循如下书写方式:一个正则表达式后面紧跟若干个空格,后接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 bisonBison意为犎牛;而Yacc与意为牦牛Yak同音)是一个自由软件,用于自动生成语法分析器程序,实际上可用于所有常见操作系统。...GNU bison基本兼容Yacc,并做了一些改进。它一般与flex一起使用。 上面介绍了几个有名工具,这些工具在其他语言中都有对应类库,比如 JS 中 bison 叫 jison。...语法分析也只做一件事,就是把词法分析生成单词流,转换成抽象语法树。 但是语法分析之前,我们还需要了解一些概念。

    77710

    TiDB SQL Parser 实现

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

    53910

    【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.7K30

    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.5K30

    (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

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

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

    2.3K41

    浏览器运行原理

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

    1.3K20

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

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

    56220

    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
    领券