使用ANTLR解析CSS - 边缘情况

时间:2009-08-24 23:25:21

标签: css antlr css-parsing

我正在尝试使用ANTLR解析CSS或至少是基础知识。我的lexer规则遇到了一些问题。问题在于ID选择器和十六进制颜色值之间的模糊性。为清晰起见,使用简化的语法,请考虑以下输入:

#bbb {
  color: #fff;
}

以及以下解析器规则:

ruleset : selector '{' property* '}';
selector: '#' ALPHANUM;
property: ALPHANUM ':' value ';' ;
value: COLOR;

和这些词法分子代币:

ALPHANUM : ('a'..'z' | '0'..'9')+;
COLOR : '#' ('0'..'9' | 'a'..'f')+;

这不起作用,因为#bbb被标记为COLOR标记,即使它应该是一个选择器。如果我将选择器更改为不以十六进制字符开头,则它可以正常工作。我不知道如何解决这个问题。有没有办法让ANTLR将特定令牌仅作为COLOR令牌处理,如果它在某个位置?比方说,如果它属于属性规则,我可以放心地认为它是一个颜色标记。如果不是,请将其视为选择器。

任何帮助将不胜感激!


解决方案:原来我试图在语法中做太多,我应该在使用AST的代码中处理。 CSS有太多不明确的令牌可靠地分成不同的令牌,所以我现在使用的方法基本上是对'#','。',':'和花括号等特殊字符进行标记,并在消费者代码。工作得更好,处理边缘情况更容易。

4 个答案:

答案 0 :(得分:8)

尝试将lexer文件中的#从COLOR移动到它自己的东西,如下:

LLETTERS: ( 'a'..'z' )
ULETTERS: ( 'A'..'Z' )
NUMBERS: ( '0'..'9' )
HASH : '#';

然后,在您的解析器规则中,您可以这样做:

color: HASH (LLETTERS | ALPHANUM)+;
selector: HASH (ULETTERS | LLETTERS) (ULETTERS | LLETTERS | NUMBERS)*;

这允许您以语法方式指定差异,这可以大致描述为上下文,而不是词法,大致可以通过外观来描述。如果某些东西的含义根据它的位置而改变,那么应该在语法中指定差异,而不是词法分析器。

请注意,颜色和选择器的定义完全相同。词典通常是将模块转换为语法的模块的一个独立阶段,因此有一个含糊不清的词典是无效的(如所指出的,bbb可以是十六进制或者它可以是小写字母字符串)。因此,数据有效性检查需要在其他地方进行。

答案 1 :(得分:2)

与Walt所说的相同,Appendix G. Grammar of CSS 2.1对lex HASH说,然后(取决于它相对于其他标记的位置)将HASH解析为simple_selector或者作为hexcolor

词法分析器定义以下标记......

"#"{name}       {return HASH;}

...语法包括以下规则......

hexcolor
  : HASH S*
  ;

simple_selector
  : element_name [ HASH | class | attrib | pseudo ]*
  | [ HASH | class | attrib | pseudo ]+
  ;

这意味着基于语法的解析器将允许非十六进制的hexcolor。

我会在代码中检测到一个非十六进制的hexcolor,用于分析/解释lexed + parsed语法树。

答案 2 :(得分:0)

要从多种选择中做出决定,ANTLR有两个选项,

  • 句法谓词
  • 语义谓词

这是来自antlr语法库(css2.1 g):

simpleSelector
    : elementName 
        ((esPred)=>elementSubsequent)*

    | ((esPred)=>elementSubsequent)+
    ;

esPred
    : HASH | DOT | LBRACKET | COLON
    ;

elementSubsequent
    : HASH
    | cssClass
    | attrib
    | pseudo
    ;

cssClass
    : DOT IDENT
    ;

elementName
    : IDENT
    | STAR
    ;

这用于句法谓词。

语法链接:http://www.antlr.org/grammar/1240941192304/css21.g

答案 3 :(得分:0)

刚刚通过谷歌搜索来到这里,并找到了一个很好的资源,一个真正的赞美。对于那些来搜索完整的CSS Antlr语法的人,请查看this语法文件。这可以给你一个想法,或者你可以直接使用它。