]> git.lizzy.rs Git - rust.git/blob - src/grammar/RustLexer.g4
Rollup merge of #31031 - brson:issue-30123, r=nikomatsakis
[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, LARROW, 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 LARROW  : '<-' ;
48
49 BINOP
50     : PLUS
51     | SLASH
52     | MINUS
53     | STAR
54     | PERCENT
55     | CARET
56     | AND
57     | OR
58     | SHL
59     | SHR
60     | LARROW
61     ;
62
63 BINOPEQ : BINOP EQ ;
64
65 /* "Structural symbols" */
66
67 AT         : '@' ;
68 DOT        : '.' ;
69 DOTDOT     : '..' ;
70 DOTDOTDOT  : '...' ;
71 COMMA      : ',' ;
72 SEMI       : ';' ;
73 COLON      : ':' ;
74 MOD_SEP    : '::' ;
75 RARROW     : '->' ;
76 FAT_ARROW  : '=>' ;
77 LPAREN     : '(' ;
78 RPAREN     : ')' ;
79 LBRACKET   : '[' ;
80 RBRACKET   : ']' ;
81 LBRACE     : '{' ;
82 RBRACE     : '}' ;
83 POUND      : '#';
84 DOLLAR     : '$' ;
85 UNDERSCORE : '_' ;
86
87 // Literals
88
89 fragment HEXIT
90   : [0-9a-fA-F]
91   ;
92
93 fragment CHAR_ESCAPE
94   : [nrt\\'"0]
95   | [xX] HEXIT HEXIT
96   | 'u' HEXIT HEXIT HEXIT HEXIT
97   | 'U' HEXIT HEXIT HEXIT HEXIT HEXIT HEXIT HEXIT HEXIT
98   | 'u{' HEXIT '}'
99   | 'u{' HEXIT HEXIT '}'
100   | 'u{' HEXIT HEXIT HEXIT '}'
101   | 'u{' HEXIT HEXIT HEXIT HEXIT '}'
102   | 'u{' HEXIT HEXIT HEXIT HEXIT HEXIT '}'
103   | 'u{' HEXIT HEXIT HEXIT HEXIT HEXIT HEXIT '}'
104   ;
105
106 fragment SUFFIX
107   : IDENT
108   ;
109
110 fragment INTEGER_SUFFIX
111   : { _input.LA(1) != 'e' && _input.LA(1) != 'E' }? SUFFIX
112   ;
113
114 LIT_CHAR
115   : '\'' ( '\\' CHAR_ESCAPE
116          | ~[\\'\n\t\r]
117          | '\ud800' .. '\udbff' '\udc00' .. '\udfff'
118          )
119     '\'' SUFFIX?
120   ;
121
122 LIT_BYTE
123   : 'b\'' ( '\\' ( [xX] HEXIT HEXIT
124                  | [nrt\\'"0] )
125           | ~[\\'\n\t\r] '\udc00'..'\udfff'?
126           )
127     '\'' SUFFIX?
128   ;
129
130 LIT_INTEGER
131
132   : [0-9][0-9_]* INTEGER_SUFFIX?
133   | '0b' [01_]+ INTEGER_SUFFIX?
134   | '0o' [0-7_]+ INTEGER_SUFFIX?
135   | '0x' [0-9a-fA-F_]+ INTEGER_SUFFIX?
136   ;
137
138 LIT_FLOAT
139   : [0-9][0-9_]* ('.' {
140         /* dot followed by another dot is a range, not a float */
141         _input.LA(1) != '.' &&
142         /* dot followed by an identifier is an integer with a function call, not a float */
143         _input.LA(1) != '_' &&
144         !(_input.LA(1) >= 'a' && _input.LA(1) <= 'z') &&
145         !(_input.LA(1) >= 'A' && _input.LA(1) <= 'Z')
146   }? | ('.' [0-9][0-9_]*)? ([eE] [-+]? [0-9][0-9_]*)? SUFFIX?)
147   ;
148
149 LIT_STR
150   : '"' ('\\\n' | '\\\r\n' | '\\' CHAR_ESCAPE | .)*? '"' SUFFIX?
151   ;
152
153 LIT_BYTE_STR : 'b' LIT_STR ;
154 LIT_BYTE_STR_RAW : 'b' LIT_STR_RAW ;
155
156 /* this is a bit messy */
157
158 fragment LIT_STR_RAW_INNER
159   : '"' .*? '"'
160   | LIT_STR_RAW_INNER2
161   ;
162
163 fragment LIT_STR_RAW_INNER2
164   : POUND LIT_STR_RAW_INNER POUND
165   ;
166
167 LIT_STR_RAW
168   : 'r' LIT_STR_RAW_INNER SUFFIX?
169   ;
170
171
172 QUESTION : '?';
173
174 IDENT : XID_Start XID_Continue* ;
175
176 fragment QUESTION_IDENTIFIER : QUESTION? IDENT;
177
178 LIFETIME : '\'' IDENT ;
179
180 WHITESPACE : [ \r\n\t]+ ;
181
182 UNDOC_COMMENT     : '////' ~[\n]* -> type(COMMENT) ;
183 YESDOC_COMMENT    : '///' ~[\r\n]* -> type(DOC_COMMENT) ;
184 OUTER_DOC_COMMENT : '//!' ~[\r\n]* -> type(DOC_COMMENT) ;
185 LINE_COMMENT      : '//' ( ~[/\n] ~[\n]* )? -> type(COMMENT) ;
186
187 DOC_BLOCK_COMMENT
188   : ('/**' ~[*] | '/*!') (DOC_BLOCK_COMMENT | .)*? '*/' -> type(DOC_COMMENT)
189   ;
190
191 BLOCK_COMMENT : '/*' (BLOCK_COMMENT | .)*? '*/' -> type(COMMENT) ;
192
193 /* these appear at the beginning of a file */
194
195 SHEBANG : '#!' { is_at(2) && _input.LA(1) != '[' }? ~[\r\n]* -> type(SHEBANG) ;
196
197 UTF8_BOM : '\ufeff' { is_at(1) }? -> skip ;