Css 递归下降解析和抽象语法树

Css 递归下降解析和抽象语法树,css,parsing,css-selectors,abstract-syntax-tree,recursive-descent,Css,Parsing,Css Selectors,Abstract Syntax Tree,Recursive Descent,我正在硬编码一个递归解析器,主要是为了学习,我遇到了一些麻烦 我将以CSS3语法中的这段简短摘录为例: simple_selector = type_selector | universal; type_selector = [ namespace_prefix ]? element_name; namespace_prefix = [ IDENT | '*' ]? '|'; element_name = IDENT; universal = [ namespace_prefix ]? '*';

我正在硬编码一个递归解析器,主要是为了学习,我遇到了一些麻烦

我将以CSS3语法中的这段简短摘录为例:

simple_selector = type_selector | universal;
type_selector = [ namespace_prefix ]? element_name;
namespace_prefix = [ IDENT | '*' ]? '|';
element_name = IDENT;
universal = [ namespace_prefix ]? '*';
首先,我没有意识到
namespace\u prefix
type\u选择器
universal
中的可选部分。这导致
类型选择器
在像
*.*
这样输入时总是失败,因为它被盲目地考虑与
名称空间前缀
匹配的任何输入

Recursive Delegate非常简单,但我对它的理解是,在开始生产之前,我需要做很多(因为没有更好的词)探索性递归。因此,我更改了产品的签名以返回布尔值。通过这种方式,我可以很容易地判断某个特定的制作是否成功

我使用一个链表数据结构来支持任意的前瞻性,并且可以很容易地分割这个列表来尝试生产,如果生产没有成功,那么就返回到我的起点。然而,在尝试一个产品时,我正在传递可变状态,试图构建一个文档对象模型。这并没有真正起作用,因为我无法知道制作是否会成功。如果制作不成功,我需要以某种方式撤销所做的任何更改


我的问题是。我是否应该使用抽象语法树作为中间表示,然后从那里开始?这是解决这个问题的常用方法吗?因为问题似乎主要在于文档对象模型不是适合递归的树数据结构。

我对CSS不太熟悉,但一般来说,您要做的是重构语法,尽可能消除歧义。在这里的例子中,可以在type_selector和universal开头的名称空间_前缀产品可以作为一个单独的可选产品放在前面:

simple_selector = [ namespace_prefix ]? (type_selector | universal);
type_selector = element_name;
namespace_prefix = [ IDENT | '*' ]? '|';
element_name = IDENT;
universal =  '*';

不过,并非所有语法都可以简化为这样简单的前瞻性语法,对于那些语法,您可以使用更复杂的shift-reduce解析器,或者——正如您所建议的——回溯。对于回溯,您通常只是尝试解析产品并记录语法中的路径。一旦您有了一个与输入匹配的产品,您就可以使用记录的路径来实际执行该产品的语义操作。

我考虑过这一点,但它并没有真正改变任何事情。语法并没有因为它而变得多多少少模棱两可,结果仍然存在。我真的很享受递归解析的本质。我最感兴趣的是如何合并一个AST来简化递归代码。当然,你不能用任何语法来无限表达,你需要在设计语言时非常小心。但在本例中,选择使用look-a-head的产品是一个简单的问题。