我正在尝试为简单的化学公式创建一个解析器。意思是,他们没有任何物质,指控或类似的状态。公式只有表示化合物,数量和括号的字符串。
Following this answer to a similar question,以及离散数学的一些基本知识,我希望我能写一个简单的Recursive Descent Parser来生成公式中每个原子的数量。我已经有really simple answer这个涉及单括号,但不是嵌套括号。
以下是没有括号的语法的产生:
Compound: Component { Component };
Component: Atom [Quantity]
Atom: 'H' | 'He' | 'Li' | 'Be' ...
Quantity: Digit { Digit }
Digit: '0' | '1' | ... '9'
[...]
被视为可选项,并且将在程序中进行if
测试(无论是存在还是缺失)|
是替代方案,if .. else if .. else或switch'test'也是如此,它说输入必须匹配其中一个{ ... }
被读作重复0或更多,并且在程序中将是一个while循环使用嵌套括号,我不知道该怎么做。通过嵌套括号我的意思是像(Fe2(OH)2(H2O)8)2
,或像(Ab(CD2(Ef(G2H)3)(IJ2)4)3)2
因为现在有一部我不太了解如何表达的作品,但这是我最好的尝试:
Parenthetical: Compound { Parenthetical } [Quantity]
答案 0 :(得分:1)
因此,基本规则解析任何简单的化学符号序列和数量而不用括号。
我认为数量是定义'(' ...')'之间的整块数量。
因此,'(' ... ') [Quantity]
需要被解析为与Component完全相同的东西,即作为替代来解析:Atom [Quantity]
所以唯一要改变的是组件规则;它变成了:
Component: Atom [Quantity] | '(' Compound ')' [Quantity]
在解析Component的代码函数(或过程)中,它将查看下一个字符(标记),如果它是'(',它会消耗它,那么调用负责解析Compound的函数(或程序),然后检查下一个字符(token)是否为')' (如果没有,则表示语法错误),然后处理可选的数量,然后结束。
我假设您使用的是支持递归函数(或过程)调用的编程语言。通过幕后代码为您的程序完成的内务管理将使这个“正常工作”成为可能。 (TM)。
或者,您可以以不同的方式解决问题。添加新规则,其中包含:
Stuff: Atom | '(' Compound ')'
然后修改规则:
Compound: Stuff [Quantity]
然后为Stuff编写一个新函数(或过程),并将Compound代码更改为简单地调用Stuff,然后处理可选的Quantity。
这样做有很好的技术原因来支持一些解析技术。然而,你使用递归下降的地方真的很重要。
编辑:
对于递归的正确解析器非常有效的语法类型称为LL(1),这意味着从左到右进行解析,并创建最左侧的派生。这是一个自然的'当代码和函数调用 控制流时解析的方法。为了找到如何检查语法的理论,LL(1)在网上搜索"解析LL(1)"或"语法遵循集合"。