代码之家  ›  专栏  ›  技术社区  ›  Erik van Brakel scottrakes

用Antlr-Edge案例分析CSS

  •  8
  • Erik van Brakel scottrakes  · 技术社区  · 15 年前

    我正在尝试使用antlr解析CSS,或者至少是基本的CSS。不过,我的雷克萨斯规则遇到了一些问题。问题在于ID选择器和十六进制颜色值之间的模糊性。为清晰起见,请考虑以下输入:

    #bbb {
      color: #fff;
    }
    

    以及以下解析器规则:

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

    这些lexer令牌:

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

    这将不起作用,因为bbb被标记为颜色标记,即使它应该是一个选择器。如果我将选择器更改为不以十六进制字符开头,它将正常工作。我不知道怎么解决这个问题。有没有一种方法可以告诉Antlr,如果某个特定的令牌处于某个位置,就只能将它作为颜色令牌来处理?比如说,如果它在属性规则中,我可以安全地假设它是一个颜色标记。如果不是,则将其视为选择器。

    任何帮助都将不胜感激!


    解决方案:结果发现我在语法方面做了太多的工作,我应该在代码中使用AST来处理这些工作。CSS有太多不明确的标记,无法可靠地拆分为不同的标记,因此我现在使用的方法基本上是标记化特殊字符,如“”、“”、“:”和大括号,并在使用者代码中进行后期处理。工作得更好,处理边缘情况也更容易。

    4 回复  |  直到 11 年前
        1
  •  8
  •   Walt W    15 年前

    尝试将lexer文件中的从颜色移动到它自己的对象,例如:

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

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

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

    等。

    这允许您在语法上指定差异,可以大致描述为上下文差异,而在词汇上可以大致描述为外观差异。如果某个东西的意思随它的位置而变化,那么应该在语法中指定这种差异,而不是在词法分析器中。

    请注意,颜色和选择器的定义完全相同。lexer通常是与将输入字符串转换为语法的模块分开的一个阶段,因此具有不明确的词法是无效的(正如前面指出的,bbb可以是十六进制的,也可以是小写字母字符串)。因此,数据有效性检查需要在其他地方进行。

        2
  •  2
  •   ChrisW    15 年前

    和沃尔特说的一样, Appendix G. Grammar of CSS 2.1 对莱克斯说 HASH ,然后(取决于它相对于其他令牌的位置)分析 搞砸 要么作为 simple_selector 或作为 hexcolor .

    lexer定义了以下令牌…

    "#"{name}       {return HASH;}
    

    …语法包括以下规则…

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

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

    稍后,我将在代码中检测到一个非十六进制十六进制十六进制,它分析/解释lexed+解析的语法树。

        3
  •  0
  •   ЯegDwight kri    12 年前

    为了从多个备选方案中做出决定,ANTLR有两个选择:

    • 句法谓词
    • 语义谓词

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

    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

        4
  •  0
  •   diyoda_    11 年前

    只是通过谷歌搜索来到这里,发现了一个很好的资源,一个真正的暗示。对于那些来搜索完整的CSS Antlr语法的人,然后看看 this 语法文件。这可以给你一个想法,或者你可以直接使用它。