Reputation: 3625
I'm trying to create a LESS parser in ANTLR, and I'm using Twitter Bootstrap's LESS files for testing. I've got it mostly working, but there's one part that's stumping me, and I think it's because I don't completely grok ANTLR.
In less/mixins.less, there is a mixin declaration as follows:
.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+
}
The thing that's hanging up my parser is that there's a variable with the same name as a unit. The @deg
token, instead of getting parsed as a variable
, gets parsed as Asperand unit
instead (because deg
is a unit). Since this is invalid, the parser quits. I've tried rearranging the order of my declarations in my ANTLR file, but it still won't work.
Subset of my grammar:
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?
;
How would I have to rearrange my declarations so that @deg
parses as a variable
, but 45deg
parses as a measurement
?
I know I could cheat and define unit: Identifier | '%' ;
but that would be pretty atrocious.
Upvotes: 0
Views: 83
Reputation: 99879
You need to redefine your unit
rule as you described at the end of the question. It's not "cheating". In fact, as long as your resulting grammar is ambiguous, it greatly improves your ability to extend the grammar in the future to accept additional types of units.
You can validate the specific Identifier
for a unit in a listener or visitor that executes after the initial parse is complete.
Upvotes: 1