]> git.lizzy.rs Git - rust.git/blob - src/grammar/RustLexer.g4
Make fields and macro defs exported
[rust.git] / src / grammar / RustLexer.g4
1 lexer grammar RustLexer;
2
3 @lexer::members {
4   public boolean is_at(int pos) {
5     return _input.index() == pos;
6   }
7 }
8
9
10 tokens {
11     EQ, LT, LE, EQEQ, NE, GE, GT, ANDAND, OROR, NOT, TILDE, PLUS,
12     MINUS, STAR, SLASH, PERCENT, CARET, AND, OR, SHL, SHR, BINOP,
13     BINOPEQ, AT, DOT, DOTDOT, DOTDOTDOT, COMMA, SEMI, COLON,
14     MOD_SEP, RARROW, FAT_ARROW, LPAREN, RPAREN, LBRACKET, RBRACKET,
15     LBRACE, RBRACE, POUND, DOLLAR, UNDERSCORE, LIT_CHAR, LIT_BYTE,
16     LIT_INTEGER, LIT_FLOAT, LIT_STR, LIT_STR_RAW, LIT_BYTE_STR,
17     LIT_BYTE_STR_RAW, QUESTION, IDENT, LIFETIME, WHITESPACE, DOC_COMMENT,
18     COMMENT, SHEBANG, UTF8_BOM
19 }
20
21 import xidstart , xidcontinue;
22
23
24 /* Expression-operator symbols */
25
26 EQ      : '=' ;
27 LT      : '<' ;
28 LE      : '<=' ;
29 EQEQ    : '==' ;
30 NE      : '!=' ;
31 GE      : '>=' ;
32 GT      : '>' ;
33 ANDAND  : '&&' ;
34 OROR    : '||' ;
35 NOT     : '!' ;
36 TILDE   : '~' ;
37 PLUS    : '+' ;
38 MINUS   : '-' ;
39 STAR    : '*' ;
40 SLASH   : '/' ;
41 PERCENT : '%' ;
42 CARET   : '^' ;
43 AND     : '&' ;
44 OR      : '|' ;
45 SHL     : '<<' ;
46 SHR     : '>>' ;
47
48 BINOP
49     : PLUS
50     | SLASH
51     | MINUS
52     | STAR
53     | PERCENT
54     | CARET
55     | AND
56     | OR
57     | SHL
58     | SHR
59     ;
60
61 BINOPEQ : BINOP EQ ;
62
63 /* "Structural symbols" */
64
65 AT         : '@' ;
66 DOT        : '.' ;
67 DOTDOT     : '..' ;
68 DOTDOTDOT  : '...' ;
69 COMMA      : ',' ;
70 SEMI       : ';' ;
71 COLON      : ':' ;
72 MOD_SEP    : '::' ;
73 RARROW     : '->' ;
74 FAT_ARROW  : '=>' ;
75 LPAREN     : '(' ;
76 RPAREN     : ')' ;
77 LBRACKET   : '[' ;
78 RBRACKET   : ']' ;
79 LBRACE     : '{' ;
80 RBRACE     : '}' ;
81 POUND      : '#';
82 DOLLAR     : '$' ;
83 UNDERSCORE : '_' ;
84
85 // Literals
86
87 fragment HEXIT
88   : [0-9a-fA-F]
89   ;
90
91 fragment CHAR_ESCAPE
92   : [nrt\\'"0]
93   | [xX] HEXIT HEXIT
94   | 'u' HEXIT HEXIT HEXIT HEXIT
95   | 'U' HEXIT HEXIT HEXIT HEXIT HEXIT HEXIT HEXIT HEXIT
96   | 'u{' HEXIT '}'
97   | 'u{' HEXIT HEXIT '}'
98   | 'u{' HEXIT HEXIT HEXIT '}'
99   | 'u{' HEXIT HEXIT HEXIT HEXIT '}'
100   | 'u{' HEXIT HEXIT HEXIT HEXIT HEXIT '}'
101   | 'u{' HEXIT HEXIT HEXIT HEXIT HEXIT HEXIT '}'
102   ;
103
104 fragment SUFFIX
105   : IDENT
106   ;
107
108 fragment INTEGER_SUFFIX
109   : { _input.LA(1) != 'e' && _input.LA(1) != 'E' }? SUFFIX
110   ;
111
112 LIT_CHAR
113   : '\'' ( '\\' CHAR_ESCAPE
114          | ~[\\'\n\t\r]
115          | '\ud800' .. '\udbff' '\udc00' .. '\udfff'
116          )
117     '\'' SUFFIX?
118   ;
119
120 LIT_BYTE
121   : 'b\'' ( '\\' ( [xX] HEXIT HEXIT
122                  | [nrt\\'"0] )
123           | ~[\\'\n\t\r] '\udc00'..'\udfff'?
124           )
125     '\'' SUFFIX?
126   ;
127
128 LIT_INTEGER
129
130   : [0-9][0-9_]* INTEGER_SUFFIX?
131   | '0b' [01_]+ INTEGER_SUFFIX?
132   | '0o' [0-7_]+ INTEGER_SUFFIX?
133   | '0x' [0-9a-fA-F_]+ INTEGER_SUFFIX?
134   ;
135
136 LIT_FLOAT
137   : [0-9][0-9_]* ('.' {
138         /* dot followed by another dot is a range, not a float */
139         _input.LA(1) != '.' &&
140         /* dot followed by an identifier is an integer with a function call, not a float */
141         _input.LA(1) != '_' &&
142         !(_input.LA(1) >= 'a' && _input.LA(1) <= 'z') &&
143         !(_input.LA(1) >= 'A' && _input.LA(1) <= 'Z')
144   }? | ('.' [0-9][0-9_]*)? ([eE] [-+]? [0-9][0-9_]*)? SUFFIX?)
145   ;
146
147 LIT_STR
148   : '"' ('\\\n' | '\\\r\n' | '\\' CHAR_ESCAPE | .)*? '"' SUFFIX?
149   ;
150
151 LIT_BYTE_STR : 'b' LIT_STR ;
152 LIT_BYTE_STR_RAW : 'b' LIT_STR_RAW ;
153
154 /* this is a bit messy */
155
156 fragment LIT_STR_RAW_INNER
157   : '"' .*? '"'
158   | LIT_STR_RAW_INNER2
159   ;
160
161 fragment LIT_STR_RAW_INNER2
162   : POUND LIT_STR_RAW_INNER POUND
163   ;
164
165 LIT_STR_RAW
166   : 'r' LIT_STR_RAW_INNER SUFFIX?
167   ;
168
169
170 QUESTION : '?';
171
172 IDENT : XID_Start XID_Continue* ;
173
174 fragment QUESTION_IDENTIFIER : QUESTION? IDENT;
175
176 LIFETIME : '\'' IDENT ;
177
178 WHITESPACE : [ \r\n\t]+ ;
179
180 UNDOC_COMMENT     : '////' ~[\n]* -> type(COMMENT) ;
181 YESDOC_COMMENT    : '///' ~[\r\n]* -> type(DOC_COMMENT) ;
182 OUTER_DOC_COMMENT : '//!' ~[\r\n]* -> type(DOC_COMMENT) ;
183 LINE_COMMENT      : '//' ( ~[/\n] ~[\n]* )? -> type(COMMENT) ;
184
185 DOC_BLOCK_COMMENT
186   : ('/**' ~[*] | '/*!') (DOC_BLOCK_COMMENT | .)*? '*/' -> type(DOC_COMMENT)
187   ;
188
189 BLOCK_COMMENT : '/*' (BLOCK_COMMENT | .)*? '*/' -> type(COMMENT) ;
190
191 /* these appear at the beginning of a file */
192
193 SHEBANG : '#!' { is_at(2) && _input.LA(1) != '[' }? ~[\r\n]* -> type(SHEBANG) ;
194
195 UTF8_BOM : '\ufeff' { is_at(1) }? -> skip ;