1use logos::Logos;
2
3use plc_ast::ast::{DirectAccessType, HardwareAccessType};
4
5#[derive(Debug, PartialEq, Eq, Logos, Clone, Copy)]
6pub enum Token {
7 #[error]
8 #[regex(r"\(\*", |lex| super::parse_comments(lex))]
9 #[regex(r"/\*", |lex| super::parse_comments(lex))]
10 #[regex(r"\{", |lex| super::parse_pragma(lex))]
11 #[regex(r"//.*", logos::skip)]
12 #[regex(r"(?m)\r", logos::skip)]
13 Error,
14
15 #[token("@EXTERNAL")]
16 #[token("{external}")]
17 PropertyExternal,
18
19 #[token("{ref}")]
20 PropertyByRef,
21
22 #[token("@CONSTANT")]
23 #[token("{constant}")]
24 PropertyConstant,
25
26 #[token("{sized}")]
27 PropertySized,
28
29 #[token("PROGRAM", ignore(case))]
30 KeywordProgram,
31
32 #[token("CLASS", ignore(case))]
33 KeywordClass,
34
35 #[token("END_CLASS", ignore(case))]
36 #[token("ENDCLASS", ignore(case))]
37 KeywordEndClass,
38
39 #[token("EXTENDS", ignore(case))]
40 KeywordExtends,
41
42 #[token("IMPLEMENTS", ignore(case))]
43 KeywordImplements,
44
45 #[token("INTERFACE", ignore(case))]
46 KeywordInterface,
47
48 #[token("END_INTERFACE", ignore(case))]
49 #[token("ENDINTERFACE", ignore(case))]
50 KeywordEndInterface,
51
52 #[token("VAR_INPUT", ignore(case))]
53 #[token("VARINPUT", ignore(case))]
54 KeywordVarInput,
55
56 #[token("VAR_OUTPUT", ignore(case))]
57 #[token("VAROUTPUT", ignore(case))]
58 KeywordVarOutput,
59
60 #[token("VAR", ignore(case))]
61 KeywordVar,
62
63 #[token("VAR_CONFIG", ignore(case))]
64 KeywordVarConfig,
65
66 #[token("ABSTRACT", ignore(case))]
67 KeywordAbstract,
68
69 #[token("FINAL", ignore(case))]
70 KeywordFinal,
71
72 #[token("METHOD", ignore(case))]
73 KeywordMethod,
74
75 #[token("END_METHOD", ignore(case))]
76 #[token("ENDMETHOD", ignore(case))]
77 KeywordEndMethod,
78
79 #[token("SUPER", ignore(case))]
80 KeywordSuper,
81
82 #[token("THIS", ignore(case))]
83 KeywordThis,
84
85 #[token("PROPERTY_GET", ignore(case))]
86 #[token("PROPERTYGET", ignore(case))]
87 KeywordPropertyGet,
88
89 #[token("PROPERTY_SET", ignore(case))]
90 #[token("PROPERTYSET", ignore(case))]
91 KeywordPropertySet,
92
93 #[token("END_PROPERTY", ignore(case))]
94 #[token("ENDPROPERTY", ignore(case))]
95 KeywordEndProperty,
96
97 #[token("CONSTANT", ignore(case))]
98 KeywordConstant,
99
100 #[token("RETAIN", ignore(case))]
101 KeywordRetain,
102
103 #[token("NON_RETAIN", ignore(case))]
104 #[token("NONRETAIN", ignore(case))]
105 KeywordNonRetain,
106
107 #[token("VAR_TEMP", ignore(case))]
108 #[token("VARTEMP", ignore(case))]
109 KeywordVarTemp,
110
111 #[token("PUBLIC", ignore(case))]
112 KeywordAccessPublic,
113
114 #[token("PRIVATE", ignore(case))]
115 KeywordAccessPrivate,
116
117 #[token("INTERNAL", ignore(case))]
118 KeywordAccessInternal,
119
120 #[token("PROTECTED", ignore(case))]
121 KeywordAccessProtected,
122
123 #[token("OVERRIDE", ignore(case))]
124 KeywordOverride,
125
126 #[token("VAR_GLOBAL", ignore(case))]
127 #[token("VARGLOBAL", ignore(case))]
128 KeywordVarGlobal,
129
130 #[token("VAR_IN_OUT", ignore(case))]
131 #[token("VARINOUT", ignore(case))]
132 KeywordVarInOut,
133
134 #[token("VAR_EXTERNAL", ignore(case))]
135 KeywordVarExternal,
136
137 #[token("END_VAR", ignore(case))]
138 #[token("ENDVAR", ignore(case))]
139 KeywordEndVar,
140
141 #[token("END_PROGRAM", ignore(case))]
142 #[token("ENDPROGRAM", ignore(case))]
143 KeywordEndProgram,
144
145 #[token("FUNCTION", ignore(case))]
146 KeywordFunction,
147
148 #[token("END_FUNCTION", ignore(case))]
149 #[token("ENDFUNCTION", ignore(case))]
150 KeywordEndFunction,
151
152 #[token("FUNCTION_BLOCK", ignore(case))]
153 #[token("FUNCTIONBLOCK", ignore(case))]
154 KeywordFunctionBlock,
155
156 #[token("END_FUNCTION_BLOCK", ignore(case))]
157 #[token("ENDFUNCTIONBLOCK", ignore(case))]
158 KeywordEndFunctionBlock,
159
160 #[token("TYPE", ignore(case))]
161 KeywordType,
162
163 #[token("STRUCT", ignore(case))]
164 KeywordStruct,
165
166 #[token("END_TYPE", ignore(case))]
167 #[token("ENDTYPE", ignore(case))]
168 KeywordEndType,
169
170 #[token("END_STRUCT", ignore(case))]
171 #[token("ENDSTRUCT", ignore(case))]
172 KeywordEndStruct,
173
174 #[token("ACTIONS", ignore(case))]
175 KeywordActions,
176
177 #[token("ACTION", ignore(case))]
178 KeywordAction,
179
180 #[token("END_ACTION", ignore(case))]
181 #[token("ENDACTION", ignore(case))]
182 KeywordEndAction,
183
184 #[token("END_ACTIONS", ignore(case))]
185 #[token("ENDACTIONS", ignore(case))]
186 KeywordEndActions,
187
188 #[token(":")]
189 KeywordColon,
190
191 #[token(";")]
192 KeywordSemicolon,
193
194 #[token(":=")]
195 KeywordAssignment,
196
197 #[token("=>")]
198 KeywordOutputAssignment,
199
200 #[token("REF=", ignore(case))]
201 KeywordReferenceAssignment,
202
203 #[token("(")]
204 KeywordParensOpen,
205
206 #[token(")")]
207 KeywordParensClose,
208
209 #[token("[")]
210 KeywordSquareParensOpen,
211
212 #[token("]")]
213 KeywordSquareParensClose,
214
215 #[token(",")]
216 KeywordComma,
217
218 #[token("...")]
219 KeywordDotDotDot,
220
221 #[token("..")]
222 KeywordDotDot,
223
224 #[token(".")]
225 KeywordDot,
226
227 #[token("IF", ignore(case))]
229 KeywordIf,
230
231 #[token("THEN", ignore(case))]
232 KeywordThen,
233
234 #[token("ELSIF", ignore(case))]
235 KeywordElseIf,
236
237 #[token("ELSE", ignore(case))]
238 KeywordElse,
239
240 #[token("END_IF", ignore(case))]
241 #[token("ENDIF", ignore(case))]
242 KeywordEndIf,
243
244 #[token("FOR", ignore(case))]
245 KeywordFor,
246
247 #[token("TO", ignore(case))]
248 KeywordTo,
249
250 #[token("BY", ignore(case))]
251 KeywordBy,
252
253 #[token("DO", ignore(case))]
254 KeywordDo,
255
256 #[token("END_FOR", ignore(case))]
257 #[token("ENDFOR", ignore(case))]
258 KeywordEndFor,
259
260 #[token("WHILE", ignore(case))]
261 KeywordWhile,
262
263 #[token("END_WHILE", ignore(case))]
264 #[token("ENDWHILE", ignore(case))]
265 KeywordEndWhile,
266
267 #[token("REPEAT", ignore(case))]
268 KeywordRepeat,
269
270 #[token("UNTIL", ignore(case))]
271 KeywordUntil,
272
273 #[token("END_REPEAT", ignore(case))]
274 #[token("ENDREPEAT", ignore(case))]
275 KeywordEndRepeat,
276
277 #[token("CASE", ignore(case))]
278 KeywordCase,
279
280 #[token("RETURN", ignore(case))]
281 KeywordReturn,
282
283 #[token("EXIT", ignore(case))]
284 KeywordExit,
285
286 #[token("CONTINUE", ignore(case))]
287 KeywordContinue,
288
289 #[token("POINTER", ignore(case))]
290 KeywordPointer,
291
292 #[token("__FPOINTER", ignore(case))]
293 KeywordFunctionPointer,
294
295 #[token("REF_TO", ignore(case))]
296 #[token("REFTO", ignore(case))]
297 KeywordRef,
298
299 #[token("REFERENCE TO", ignore(case))]
300 KeywordReferenceTo,
301
302 #[token("ARRAY", ignore(case))]
303 KeywordArray,
304
305 #[token("STRING", ignore(case))]
306 KeywordString,
307
308 #[token("WSTRING", ignore(case))]
309 KeywordWideString,
310
311 #[token("OF", ignore(case))]
312 KeywordOf,
313
314 #[token("AT", ignore(case))]
315 KeywordAt,
316
317 #[token("END_CASE", ignore(case))]
318 #[token("ENDCASE", ignore(case))]
319 KeywordEndCase,
320
321 #[token("+")]
323 OperatorPlus,
324
325 #[token("-")]
326 OperatorMinus,
327
328 #[token("*")]
329 OperatorMultiplication,
330
331 #[token("**")]
332 OperatorExponent,
333
334 #[token("/")]
335 OperatorDivision,
336
337 #[token("=")]
338 OperatorEqual,
339
340 #[token("<>")]
341 OperatorNotEqual,
342
343 #[token("<")]
344 OperatorLess,
345
346 #[token(">")]
347 OperatorGreater,
348
349 #[token("<=")]
350 OperatorLessOrEqual,
351
352 #[token(">=")]
353 OperatorGreaterOrEqual,
354
355 #[token("&")]
356 OperatorAmp,
357
358 #[token("^")]
359 OperatorDeref,
360
361 #[token("MOD", ignore(case))]
362 OperatorModulo,
363
364 #[token("AND_THEN", ignore(case))]
365 OperatorAndThen,
366
367 #[token("AND", ignore(case))]
368 OperatorAnd,
369
370 #[token("OR_ELSE", ignore(case))]
371 OperatorOrElse,
372
373 #[token("OR", ignore(case))]
374 OperatorOr,
375
376 #[token("XOR", ignore(case))]
377 OperatorXor,
378
379 #[token("NOT", ignore(case))]
380 OperatorNot,
381
382 #[regex(r"[a-zA-Z_][a-zA-Z_0-9]*")]
384 Identifier,
385
386 #[regex(r"16#[0-9a-fA-F]+(_[0-9a-fA-F]+)*")]
388 LiteralIntegerHex,
389
390 #[regex(r"8#[0-7]+(_[0-7]+)*")]
391 LiteralIntegerOct,
392
393 #[regex(r"2#[0-1]+(_[0-1]+)*")]
394 LiteralIntegerBin,
395
396 #[regex(r"[0-9]+(_[0-9]+)*([eE][+-]?[0-9]+)?")]
397 LiteralInteger,
398
399 #[token("NULL", ignore(case))]
400 LiteralNull,
401
402 #[token("TRUE", ignore(case))]
403 LiteralTrue,
404
405 #[token("FALSE", ignore(case))]
406 LiteralFalse,
407
408 #[regex("(LDATE|DATE|LD|D)#\\d+-\\d+-\\d+", ignore(case))]
409 LiteralDate,
410
411 #[regex(
412 "(DATE_AND_TIME|DT|LDATE_AND_TIME|LDT)#\\d+-\\d+-\\d+-\\d+:\\d+(:\\d+(\\.\\d+)?)?",
413 ignore(case)
414 )]
415 LiteralDateAndTime,
416
417 #[regex("(TIME_OF_DAY|LTIME_OF_DAY|TOD|LTOD)#\\d+:\\d+(:\\d+(\\.\\d+)?)?", ignore(case))]
418 LiteralTimeOfDay,
419
420 #[regex("(LTIME|LT|TIME|T)#-?(\\d+(\\.\\d+)?(d|h|ms|m|s|us|ns))+", ignore(case))]
421 LiteralTime,
422
423 #[regex("%(B|b|D|d|W|w|L|l|X|x)", super::parse_access_type)]
424 DirectAccess(DirectAccessType),
425
426 #[regex(r"%(I|i|Q|q|M|m|G|g)(B|b|D|d|W|w|L|l|X|x|\*)", super::parse_hardware_access_type)]
427 HardwareAccess((HardwareAccessType, DirectAccessType)),
428
429 #[regex("'((\\$.)|[^$'])*'")]
430 LiteralString,
431
432 #[regex("\"((\\$.)|[^$\"])*\"")]
433 LiteralWideString,
434
435 #[regex("[a-zA-Z_][a-zA-Z_0-9]*#")]
436 TypeCastPrefix,
437
438 #[regex(r"[ \t\n\f]+", logos::skip)]
439 End,
440}
441
442impl Token {
443 pub fn is_var(&self) -> bool {
445 matches!(
446 self,
447 Token::KeywordVar
448 | Token::KeywordVarInput
449 | Token::KeywordVarOutput
450 | Token::KeywordVarInOut
451 | Token::KeywordVarTemp
452 )
453 }
454
455 pub fn is_identifier_like(&self) -> bool {
460 matches!(self, Token::Identifier | Token::KeywordPropertyGet | Token::KeywordPropertySet)
461 }
462
463 pub fn classes(&self) -> &'static [TokenClass] {
467 use TokenClass::*;
468 match self {
469 Token::KeywordConstant
470 | Token::KeywordRetain
471 | Token::KeywordNonRetain
472 | Token::KeywordAbstract
473 | Token::KeywordFinal
474 | Token::KeywordOverride
475 | Token::KeywordAccessPublic
476 | Token::KeywordAccessPrivate
477 | Token::KeywordAccessInternal
478 | Token::KeywordAccessProtected => &[Modifier],
479
480 Token::KeywordExit => &[ControlFlowJump],
481
482 Token::KeywordString | Token::KeywordWideString => &[BuiltinDatatype],
483
484 _ => &[],
485 }
486 }
487}
488
489#[derive(Debug, Clone, Copy, PartialEq, Eq)]
490pub enum TokenClass {
491 Modifier,
493 ControlFlowJump,
495 BuiltinDatatype,
497}