我正在尝试在ANTLR中创建一个LESS解析器,我正在使用Twitter Bootstrap的LESS文件进行测试。我已经完成了它的工作,但有一部分让我感到难过,我认为这是因为我没有完全理解ANTLR。
在less/mixins.less中,有mixin declaration如下:
.directional(@start-color: #555; @end-color: #333; @deg: 45deg) {
background-repeat: repeat-x;
background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+
background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+
}
悬挂我的解析器的是,有一个与单元同名的变量。 @deg
令牌不是被解析为variable
,而是被解析为Asperand unit
(因为deg
是一个单位)。由于这是无效的,解析器退出。我已经尝试在我的ANTLR文件中重新排列声明的顺序,但它仍然无效。
我的语法子集:
varAssignment
: variable w Colon w expr
;
expr
: expr w term w
| expr w Comma w term w
| term w
;
term
: variable
| measurement
;
variable
: Asperand Identifier
;
// Insignificant whitespace.
w: (W | Comment)*;
Identifier
: NameStart NameChar*
;
Ampersand: '&';
Asperand: '@';
Comma: ',';
Semi: ';';
Colon: ':';
Ellipsis: '...';
OpenBlock: '{';
CloseBlock: '}';
OpenParen: '(';
CloseParen: ')';
OpenSquare: '[';
CloseSquare:']';
W: (' ' | '\t' | '\n' | '\r' | '\f' )+;
number: Number;
Number: Dgt+ | Dgt* '.' Dgt+;
fragment NameChar
: NameStart
| Dgt
;
fragment NameStart
: 'a'..'z' | 'A'..'Z' | '-'
;
fragment Dgt
: '0'..'9'
;
unit:'%'
|'px'
|'em'
|'ex'
|'in'
|'cm'
|'mm'
|'pc'
|'deg'
|'rad'
|'grad'
;
measurement
: Number unit?
;
我如何重新安排声明,以便@deg
解析为variable
,但45deg
解析为measurement
?
我知道我可以作弊并定义unit: Identifier | '%' ;
,但那会非常残忍。
答案 0 :(得分:1)
您需要按照问题末尾所述的方式重新定义unit
规则。这不是“作弊”。事实上,只要你得到的语法含糊不清,它就会大大提高你将来扩展语法的能力,以接受其他类型的单位。
您可以验证在初始解析完成后执行的侦听器或访问者中的单元的特定Identifier
。