从零开始写一个Jison解析器(7/10):解析器生成器 `parser generator` 的迭代式开发流程

解析器生成器 parser generator 的迭代式开发流程
如前所述Jison解析器生成器 parser generator 的代码包含两部分词法分析 lexical analysis 和语义分析 semantic analyse ,因此可以把词法分析 lexical analysis 和语义分析 semantic analyse 视为一次迭代开发的两个阶段,例如上一篇和本篇讲解按照花括号 { 和 } 解析文件结构,这是一次迭代,上一篇是第一阶段,在词法分析 lexical analysis 中解析出花括号 { 和 } ;本篇是第二阶段,在语义分析 semantic analyse 中基于花括号 { 和 } 解析文件结构。

从定义语法的角度看解析器生成器 parser generator 时,很直观的想法就是既然语法已经定义出来了,那么按照语法直接写解析器生成器 parser generator 代码就可以了。一步到位的愿望是美好的,然而解析不同于定义语法,开发解析用途的解析器生成器 parser generator 代码有着不同的开发流程。

在前面内容中提到,开发解析器生成器 parser generator 时,不同于开发程序时先从一个简单的功能开始逐步完善,而是从一开始就需要能正确解析目标数据,因此本例先按行解析,然后在上一篇中解析出花括号 { 和 } ,由此可以看出与普通开发程序的工作流程的差异。

本例中把去掉花括号 { 和 } 后的标记 token 命名为 UNKNOWN。标记 token 的名称就是表示不需要关心这里面的内容有什么具体含义,能区别于花括号标记 LBRACE 和 RBRACE 匹配不同的字符即可,先保证能成功解析数据文件。而普通的程序开发流程往往会要求比较精确的数据定义,这也是解析器生成器 parser generator 在开发流程上的差异,没有解析的内容留着以后处理。

结合前面的讲解,简单总结解析器生成器 parser generator 的迭代式开发流程包括三个要点:

每一步都要保证能成功解析样例文件
对于还没有解析的部分暂时不关注怎么精确定义,留待后续处理
词法分析 lexical analysis 和语义分析 semantic analyse 分成两个阶段,先在词法分析 lexical analysis 中解析出标记 token,然后在语义分析 semantic analyse 解析成规则
像其他程序开发技术的工作流程适用于一定范围的场景一样,这个流程也不是广泛适用于各种开发解析器生成器 parser generator 的场景,然而遵循这个流程可以使得每一步的目标和逻辑很明确,即使遇到问题,也可以回溯到前一个可行的步骤,更换其他的解析思路探索。

上一篇词法分析 lexical analysis 实现了解析出花括号 { 和 } ,本篇在语义分析 semantic analyse 中将解析出成对的花括号 { 和 }。如果本篇解析成功,那么说明可以继续进一步尝试,如果本篇解析失败,也可以尝试更换其他的解析方式,仍旧基于上一篇解析出的花括号 { 和 }。

从零开始分析成对的花括号 { 和 }
在上一篇中讲解了如何从零开始发现应该从花括号 { 和 } 开始,接下来仍旧遵循从零开始的原则,分析左花括号 { 和右花括号 } 出现的位置和文件结构的关系。

使用上一篇中搜索左花括号 { 的命令


这几对花括号 { 和 } 比较明显的成对出现,其他包含左花括号 { 的几行距离成对的右花括号 } 较远,分析过程仍旧遵循从零开始的原则,不做假设,仅从观察发现规律。

其中有几对花括号 { 和 } 之间没有额外的行,按照词法分析 lexical analysis 中的模式分析标记 token,结果都是

UNKNOWN LBRACE EOL
UNKNOWN RBRACE EOL
1
2
类似的分析花括号 { 和 } 之间包含额外的行的情况,按照词法分析 lexical analysis 中的模式分析标记 token,结果是

UNKNOWN LBRACE EOL
UNKNOWN EOL
UNKNOWN EOL
UNKNOWN RBRACE EOL

对照解析器生成器 parser generator 代码会发现,UNKNOWN EOL 在词法分析 lexical analysis 中被匹配为 l,而连续的UNKNOWN EOL 匹配为连续的 l,将进一步匹配为 ll。因此花括号 { 和 } 之间包含额外的行的情况可以改写为

UNKNOWN LBRACE EOL
ll
UNKNOWN RBRACE EOL
1
2
3
从一开始的解析器生成器 parser generator 的迭代式开发技巧
上一篇中在词法分析 lexical analysis 部分中保持标记 EOL和EOF不变,去掉了标记 LINE。


这种改进是在词法分析 lexical analysis 部分中的局部改进,保持其他规则不变。回顾前面根据搜索成对的花括号 { 和 } 搜索到的两个位置。

  
这种改进也就是在语义分析 semantic analyse 部分中的局部改进,保持其他规则不变。

在上一篇中讨论过从零开始分析要抛开生产生活经验的约定,而前面讲解的词法分析 lexical analysis 和语义分析 semantic analyse 中保持已经成功运行的部分标记 token 和部分语法规则 grammar rules 不变,尝试改进其他标记 token 和语法规则 grammar rules ,即可称之为从一开始,这种思路也是遵循前面提到的迭代式开发流程的三个要点。

从一开始分析成对的花括号 { 和 }
上一篇中通过筛选样例文件中的花括号 { 和 },通过观察发现花括号 { 和 } 仅出现在行末,然后进一步通过这个规律改进词法分析 lexical analysis ,前面通过观察发现了部分成对花括号 { 和 } 可以通过两种语法规则 grammar rules 匹配。当花括号 { 和 } 之间没有额外的行可以使用如下方式匹配

UNKNOWN LBRACE EOL
UNKNOWN RBRACE EOL
1
2
这种情况因为成对花括号 { 和 } 距离较近,所以容易观察。另有两组成对花括号 { 和 } 的情况可以使用如下方式匹配

UNKNOWN LBRACE EOL
ll
UNKNOWN RBRACE EOL
1
2
3
这是因为这两组成对花括号 { 和 } 之间只有两行,所以能比较直观的观察,当成对花括号 { 和 } 之间的内容较多时,就不那么容易直观观察了。

上一篇中通过命令筛选出花括号 { 和 } 后通过观察寻找出词法分析 lexical analysis 的规律,是因为筛选过滤掉了干扰的内容,那么语义分析 semantic analyse 中能否有类似的思路呢?

前面通过直观观察距离较近的成对花括号 { 和 } 发现了规律,那么能否采用类似的方式筛选过滤掉干扰的内容让成对的花括号之间的距离近些便于直观观察呢?

由于本例的数据文件具有明显的分行的特点,因此通过直观观察寻找词法分析 lexical analysis 规律时,可以借助命令行中的行处理命令,而语义分析 semantic analyse 往往跨越多行,是否可以借助命令行中的更复杂的文本处理命令呢?

这是一个很自然的想法,不过,等等!

目前正在做的就是文本内容分析,而且已经完成了初步的分析,如果使用其他的文本处理命令,还需要在其他文本处理命令中从零开始重复实现已经分析过的规则。

那么能否基于已经完成的工作从一开始呢?

目前语义分析 semantic analyse 中的动作 action 是按照输入文件的原样输出,也就是把输入的文件内容分析之后按照分析的标记 token 重新组合成原样,三个语法规则 grammar rules 中,l 的规则包含标记 token,而 ll 不包含标记 token,p 包含的标记 EOF 没有实际内容而且不影响分析,下面看一下规则 l

l
————————————————
版权声明:本文为CSDN博主「胡争辉」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/hu_zhenghui/article/details/107108544

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果你想在使用QT框架中编Jison字符串,你可以按照以下步骤进行: 1. 首先,确保你已经安装了Jison。你可以通过npm(Node.js包管理器)来安装Jison。在终端或命令提示符中运行以下命令进行安装: ``` npm install jison -g ``` 2. 创建一个新的Jison语法描述文件,例如`grammar.jison`,并在文件中定义你的语法规则。例如,以下是一个简单的Jison语法规则示例: ``` %lex %% [0-9]+\b return 'NUMBER'; \+ return '+'; \- return '-'; \* return '*'; \/ return '/'; \s+ /* skip whitespace */ <<EOF>> return 'EOF'; /lex %start expressions %% expressions : expressions '+' expressions { $$ = $1 + $3; } | expressions '-' expressions { $$ = $1 - $3; } | expressions '*' expressions { $$ = $1 * $3; } | expressions '/' expressions { $$ = $1 / $3; } | NUMBER { $$ = Number($1); } ; ``` 3. 在QT项目中创建一个新的文件,例如`parser.js`,并在其中编解析器相关的代码。你可以使用`require`函数来引入Jison和你的语法描述文件。 ```javascript const jison = require('jison'); const fs = require('fs'); const grammar = fs.readFileSync('grammar.jison', 'utf-8'); const parser = new jison.Parser(grammar); const input = "2 + 3 * 4"; const result = parser.parse(input); console.log(result); // 输出解析结果 ``` 请确保你已经将`grammar.jison`文件与`parser.js`文件放置在同一个目录下。 4. 在QT项目中的相关文件中调用你的`parser.js`代码,以实现对Jison字符串的解析。你可以使用QT的相关函数和类来获取输入的字符串,并将解析结果进行展示或进一步处理。 这是一个简单的示例,希望对你有所帮助。如果你有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值