jejune 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1029 @@
1
+ grammar Jejune;
2
+
3
+ options {
4
+ language = Ruby;
5
+ output = AST;
6
+ //memoize = true;
7
+ }
8
+
9
+
10
+ tokens {
11
+ AMP='&'; GENERAL; POST_DECR;
12
+ AMP_ASGN='&='; GEQ='>='; POST_IF;
13
+ AND='&&'; GET='get'; POST_INCR;
14
+ AREF; GREATER='>'; POST_UNLESS;
15
+ ARGUMENTS; HAT='^'; PROGRAM;
16
+ ARRAY; HAT_ASGN='^='; QMARK='?';
17
+ ARROW='->'; HIDE; RBRACE='}';
18
+ ASGN='='; IF='if'; RBRACK=']';
19
+ BLOCK; IN='in'; REGEX;
20
+ BL_END='end'; INCR='++'; REQUIRE;
21
+ BREAK='break'; INSTANCEOF='instanceof'; RETURN='return';
22
+ CALL; IS_DEFINED='defined?'; RPAREN=')';
23
+ CASE='case'; ITER; RSHIFT='>>';
24
+ CATCH='catch'; LABEL; RSHIFT3='>>>';
25
+ COLON=':'; LBRACE='{'; RSHIFT3_ASGN='>>>=';
26
+ COMMA=','; LBRACK='['; RSHIFT_ASGN='>>=';
27
+ COMMENT; LEQ='<='; SEMI=';';
28
+ CONST='const'; LESS='<'; SET='set';
29
+ CONTINUE='continue'; LET='let'; SLASH;
30
+ DDOC; LINE_COMMENT; SLASH_ASGN;
31
+ DECR='--'; LPAREN='('; SPLAT;
32
+ DEFAULT='default'; LSHIFT='<<'; STAR='*';
33
+ DELETE='delete'; LSHIFT_ASGN='<<='; STAR_ASGN='*=';
34
+ DGENERAL; MACRO='macro'; SWITCH='switch';
35
+ DIRECTIVE; MINUS='-'; THIS='this';
36
+ DO='do'; MINUS_ASGN='-='; THROW='throw';
37
+ DOT='.'; MOD; TILDE='~';
38
+ DO_UNTIL; MOD_ASGN; TRUE='true';
39
+ DO_WHILE; NEQ='!='; TRY='try';
40
+ DREGEX; NEQQ='!=='; TYPEOF='typeof';
41
+ DSTRING; NEW='new'; UMINUS;
42
+ EACH='each'; NOT='!'; UNDEFINED='undefined';
43
+ ELSE='else'; NULL='null'; UNLESS='unless';
44
+ EQ='=='; OBJECT; UNTIL='until';
45
+ EQQ='==='; OR='||'; UPLUS;
46
+ FALSE='false'; OR_ASGN='||='; VAR='var';
47
+ FINALLY='finally'; PARAMS; VOID='void';
48
+ FOR='for'; PIPE='|'; WHILE='while';
49
+ FOR_IN; PIPE_ASGN='|='; WITH='with';
50
+ FUNCTION='function'; PLUS='+'; YIELD='yield';
51
+ FUNC_ARG; PLUS_ASGN='+=';
52
+ IS_UNDEFINED='undefined?'; POUND='#'; DEF='def'; CLASS_DEF='class'; OBJECT_DEF='object';
53
+ }
54
+
55
+ scope InFor { active; }
56
+
57
+ @parser::members {
58
+
59
+ RESERVED = Set[
60
+ BREAK, DO, FUNCTION, NEW, THROW, UNTIL, CASE, EACH, GET,
61
+ NULL, TRUE, VAR, CATCH, ELSE, IF, RETURN, TRY, VOID,
62
+ CONTINUE, FALSE, IN, SET, TYPEOF, WHILE, DEFAULT, FINALLY,
63
+ INSTANCEOF, SWITCH, UNDEFINED, WITH, DELETE, FOR, LET, THIS,
64
+ UNLESS, YIELD
65
+ ]
66
+
67
+ def auto_semicolon?( error )
68
+ if NoViableAlternative === error
69
+ return( @auto_semicolon = error ) unless same_line?
70
+ end
71
+ return false
72
+ end
73
+
74
+ def recover( error = $! )
75
+ @auto_semicolon == error and return( @auto_semicolon = nil )
76
+ super
77
+ end
78
+
79
+ def report_error( error = $! )
80
+ auto_semicolon?( error ) and return
81
+ super
82
+ end
83
+
84
+ def newline?( from = 1 )
85
+ to = from == -1 ? 1 : from + 1
86
+ start = @input.future?( from )
87
+ stop = @input.future?( to )
88
+
89
+ start.upto( stop ) do | i |
90
+ @input.at( i ).type == NEWLINE and return( true )
91
+ end
92
+
93
+ return( false )
94
+ end
95
+
96
+ def same_line?
97
+ stop = @input.future? || @input.length
98
+ start = @input.past? || 0
99
+
100
+ start.upto( stop ) do | i |
101
+ @input.at( i ).type == NEWLINE and return( false )
102
+ end
103
+
104
+ return( true )
105
+ end
106
+
107
+ def property_definition?
108
+ type = @input.peek
109
+ RESERVED.include?( type ) and type = ID
110
+
111
+ case @input.peek
112
+ when GET, SET then return true
113
+ when ID
114
+ case @input.peek( 2 )
115
+ when COLON, ARROW then return true
116
+ else return false
117
+ end
118
+ end
119
+ end
120
+
121
+ def prepend_tree( root, child )
122
+ child = @adaptor.rule_post_processing( child )
123
+ root.unshift( child )
124
+ root.start_index > child.start_index and root.start_index = child.start_index
125
+ root.stop_index < child.stop_index and root.stop_index = child.stop_index
126
+ return @adaptor.rule_post_processing( root )
127
+ end
128
+ }
129
+
130
+ @lexer::members {
131
+ attr_accessor :value_expected
132
+
133
+ NO_VALUE_FOLLOWS = Set[
134
+ ID, REGEX, STRING, NUMBER, THIS,
135
+ TRUE, FALSE, NULL, UNDEFINED,
136
+ RPAREN, RBRACK, RBRACE,
137
+ IVAR, DOC, GENERAL,
138
+ DSTRING, DDOC, DREGEX, DGENERAL
139
+ ]
140
+
141
+ def next_token
142
+ token = super
143
+ unless token.hidden?
144
+ @value_expected =
145
+ NO_VALUE_FOLLOWS.include?( token.type ) ? false : true
146
+ end
147
+ return( token )
148
+ end
149
+
150
+ def next_type
151
+ loop do
152
+ @state.token = nil
153
+ @state.channel = DEFAULT_CHANNEL
154
+ @state.token_start_position = @input.index
155
+ @state.token_start_column = @input.column
156
+ @state.token_start_line = @input.line
157
+ @state.text = nil
158
+ @input.peek == EOF and return EOF
159
+ begin
160
+ token!
161
+
162
+ case token = @state.token
163
+ when nil
164
+ return @state.type
165
+ when SKIP_TOKEN then next
166
+ else
167
+ return token.type
168
+ end
169
+ rescue ANTLR3::Error::NoViableAlternative => re
170
+ report_error( re )
171
+ recover( re )
172
+ rescue ANTLR3::Error::RecognitionError => re
173
+ report_error( re )
174
+ end
175
+ end
176
+ end
177
+
178
+ def at_interpolation?
179
+ input.peek == 0x23 or return false
180
+ case input.peek( 2 )
181
+ when 0x7b, 0x40, 0x25, 0x24
182
+ return true
183
+ end
184
+ return false
185
+ end
186
+
187
+ def tokenize_until_balanced( incr, decr, starting_depth = 1 )
188
+ tokens = []
189
+
190
+ depth = starting_depth
191
+ for tk in self
192
+ case tk.type
193
+ when incr then depth += 1
194
+ when decr
195
+ depth -= 1
196
+ depth.zero? and break
197
+ end
198
+ tokens << tk
199
+ end
200
+
201
+ depth.zero? or raise "hit the end of the file before finding a balance"
202
+ return tokens
203
+ end
204
+
205
+ def quick_balance( incr, decr, starting_depth = 1 )
206
+ lexer = self.class.new( input )
207
+ depth = starting_depth
208
+ while type = lexer.next_type and type != EOF
209
+ case type
210
+ when incr then depth += 1
211
+ when decr
212
+ depth -= 1
213
+ depth.zero? and return self
214
+ end
215
+ end
216
+ raise "hit the end of the file before finding a balance"
217
+ end
218
+
219
+ # TODO: handle EOF scenario
220
+ def scan_until_delimiter( delim )
221
+ while c = @input.peek
222
+ case c
223
+ when 0x5c #
224
+ @input.consume
225
+ when delim
226
+ @input.consume
227
+ return
228
+ when EOF
229
+ break
230
+ end
231
+ @input.consume
232
+ end
233
+ end
234
+
235
+ def scan
236
+ while type = next_type and type != EOF
237
+ yield( type )
238
+ end
239
+ end
240
+ }
241
+
242
+ @lexer::init {
243
+ @value_expected = true
244
+ }
245
+
246
+ /********************************************************************************
247
+ **************************** Top-Level Structure *****************************
248
+ ********************************************************************************/
249
+
250
+ program
251
+ : source_elements -> source_elements
252
+ | -> ^( UNDEFINED )
253
+ ;
254
+
255
+ source_elements
256
+ : statement ( statement )*
257
+ ;
258
+
259
+ block
260
+ : ( '{' )=> statement_block
261
+ | statement
262
+ ;
263
+
264
+ statement_block
265
+ : '{' statement_list? '}' -> ^( BLOCK statement_list? )
266
+ ;
267
+
268
+ statement_list
269
+ : statement+ -> statement+
270
+ ;
271
+
272
+ clause
273
+ : '(' expression_list ')' -> expression_list
274
+ ;
275
+
276
+ /********************************************************************************
277
+ ******************************** Statements **********************************
278
+ ********************************************************************************/
279
+
280
+ statement
281
+ : variable_statement
282
+ | const_statement
283
+ | empty_statement
284
+ | ( 'function' )=> function
285
+ | ( EJS )=> EJS^
286
+ | DIRECTIVE^
287
+ | class_statement
288
+ | macro
289
+ | ( ID ':' )=> labelled_statement
290
+ | ( 'let' )=> let_statement
291
+ | expression_statement
292
+ | if_statement
293
+ | while_statement
294
+ | do_while_statement
295
+ | for_loop
296
+ | continue_statement
297
+ | break_statement
298
+ | yield_statement
299
+ | return_statement
300
+ | with_statement
301
+ | switch_statement
302
+ | throw_statement
303
+ | try_statement
304
+ ;
305
+
306
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
307
+ // Simple Statements
308
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
309
+
310
+ empty_statement
311
+ : ';' ->
312
+ ;
313
+
314
+ expression_statement
315
+ : expression_list statement_end!
316
+ ;
317
+
318
+ labelled_statement
319
+ : ID ':' block
320
+ -> ^( LABEL ID block )
321
+ ;
322
+
323
+ statement_end
324
+ : ';'
325
+ | ( '}' )=>
326
+ | EOF
327
+ ;
328
+
329
+ blank
330
+ : -> ^( UNDEFINED )
331
+ ;
332
+
333
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
334
+ // Block-ish Statements
335
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
336
+
337
+ try_statement
338
+ : 'try'
339
+ ( statement_block -> statement_block )
340
+ ( f=finally_clause -> { prepend_tree( $f.tree, $tree ) }
341
+ | ( catch_clause -> { prepend_tree( $catch_clause.tree, $tree ) } )+
342
+ ( f2=finally_clause -> { prepend_tree( $f2.tree, $tree ) } )?
343
+ | -> ^( 'try' statement_block )
344
+ )
345
+ ;
346
+
347
+ catch_clause
348
+ : 'catch' '(' catch_selector ')' statement_block
349
+ -> ^( 'catch' catch_selector statement_block )
350
+ ;
351
+
352
+ catch_selector
353
+ @after {
354
+ case $tree.token.type
355
+ when IF then $tree.token.type = POST_IF
356
+ when UNLESS then $tree.token.type = POST_UNLESS
357
+ end
358
+ }
359
+ : ID
360
+ ( 'if'^ expression
361
+ | 'unless'^ expression
362
+ )?
363
+ ;
364
+
365
+ finally_clause
366
+ : 'finally' statement_block
367
+ -> ^( 'finally' statement_block )
368
+ ;
369
+
370
+ with_statement
371
+ : 'with' clause block -> ^( 'with' clause block )
372
+ ;
373
+
374
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
375
+ // Variable Declarations
376
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
377
+
378
+ variable_statement
379
+ : 'var'^ variable_declaration_list statement_end!
380
+ ;
381
+
382
+ const_statement
383
+ : 'const'^ variable_declaration_list statement_end!
384
+ ;
385
+
386
+ let_statement
387
+ : 'let'^ '('! variable_declaration_list ')'! block
388
+ ;
389
+
390
+ variable_declaration_list
391
+ : variable_declaration ( ','! variable_declaration )*
392
+ ;
393
+
394
+ variable_declaration
395
+ : declaration_target ( '='^ expression )?
396
+ ;
397
+
398
+ declaration_target
399
+ : '[' declaration_target ( ',' declaration_target )* ']' -> ^( ARRAY declaration_target+ )
400
+ | '{' declaration_key ( ',' declaration_key )* '}' -> ^( OBJECT declaration_key+ )
401
+ | variable_name -> variable_name
402
+ ;
403
+
404
+ declaration_key
405
+ : ( ID | STRING | NUMBER | reserved { $reserved.tree.token.type = ID } ) ':'^ declaration_target
406
+ ;
407
+
408
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
409
+ // Branching Statements
410
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
411
+
412
+ if_statement
413
+ : ( 'if'^ | 'unless'^ ) clause block ( 'else'! block )?
414
+ ;
415
+
416
+ browser_block
417
+ : '!' browser_name^ statement_block ( 'else'! block )?
418
+ ;
419
+
420
+ switch_statement
421
+ : 'switch' '(' expression_list ')'
422
+ '{'
423
+ ( case_clause )*
424
+ ( default_clause ( case_clause )* )?
425
+ '}'
426
+ -> ^( 'switch' expression_list case_clause* default_clause? )
427
+ ;
428
+
429
+ case_clause
430
+ : 'case'^ expression_list ':'! statement_list?
431
+ ;
432
+
433
+ default_clause
434
+ : 'default'^ ':'! statement_list?
435
+ ;
436
+
437
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
438
+ // While Loops
439
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
440
+
441
+ do_while_statement
442
+ : 'do' block
443
+ ( 'while' clause statement_end -> ^( 'while' clause block )
444
+ | 'until' clause statement_end -> ^( 'until' clause block )
445
+ )
446
+ -> ^( 'do' $do_while_statement )
447
+ ;
448
+
449
+ while_statement
450
+ : 'while'^ clause block
451
+ | 'until'^ clause block
452
+ ;
453
+
454
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
455
+ // For Loops
456
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
457
+
458
+ for_loop
459
+ : { @input.peek( 2 ) == EACH }?=> for_each_in_statement
460
+ | ( 'for' '(' ~( ')' | ';' | 'in' )* 'in' )=> for_in_statement
461
+ | for_statement
462
+ ;
463
+
464
+ for_statement
465
+ : 'for'^
466
+ '('!
467
+ ( for_statement_initialiser_part | blank ) ';'!
468
+ ( expression_list | blank ) ';'!
469
+ ( expression_list | blank )
470
+ ')'!
471
+ block
472
+ ;
473
+
474
+ for_statement_initialiser_part
475
+ scope InFor;
476
+ @before { $InFor::active = true }
477
+ @after { $InFor::active = false }
478
+ : expression_list
479
+ | ( 'var'^ | 'let'^ ) variable_declaration_list
480
+ ;
481
+
482
+ for_each_in_statement
483
+ : 'for' 'each' '(' for_in_statement_initialiser_part 'in' expression ')' block
484
+ -> ^( 'each' for_in_statement_initialiser_part expression block )
485
+ ;
486
+
487
+ for_in_statement
488
+ : f='for' '(' for_in_statement_initialiser_part 'in' expression ')' block
489
+ -> ^( FOR_IN[ $f ] for_in_statement_initialiser_part expression block )
490
+ ;
491
+
492
+ for_in_statement_initialiser_part
493
+ scope InFor;
494
+ @before {
495
+ $InFor::active = true
496
+ }
497
+ @after {
498
+ $InFor::active = false
499
+ }
500
+ : ( 'var'^ | 'let'^ ) declaration_target
501
+ | member
502
+ ;
503
+
504
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
505
+ // Flow Control
506
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
507
+
508
+ continue_statement
509
+ : 'continue'^ ( { same_line? }?=> ID )? statement_end!
510
+ ;
511
+
512
+ break_statement
513
+ : 'break'^ ( { same_line? }?=> ID )? statement_end!
514
+ ;
515
+
516
+ return_statement
517
+ : 'return'^ ( { same_line? }?=> expression_list )? statement_end!
518
+ ;
519
+
520
+ yield_statement
521
+ : 'yield'^ ( { same_line? }?=> expression_list )? statement_end!
522
+ ;
523
+
524
+ throw_statement
525
+ : 'throw'^ ( { same_line? }?=> expression_list )? statement_end!
526
+ ;
527
+
528
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
529
+ // Definition Statements
530
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
531
+
532
+ class_statement
533
+ : 'class'^ ID '{'! class_member* '}'!
534
+ | 'object'^ 'var'? ID '{'! class_member* '}'!
535
+ ;
536
+
537
+ class_member
538
+ : variable_statement
539
+ | 'def'^ variable_name function_parameters? statement_block
540
+ | 'get'^ ID function_parameters? block
541
+ | 'set'^ ID function_parameters? block
542
+ | variable_name '='^ expression
543
+ | ';'!
544
+ ;
545
+
546
+
547
+ /********************************************************************************
548
+ ******************************** Expression **********************************
549
+ ********************************************************************************/
550
+
551
+ expression_list
552
+ : expression ( ','^ expression )*
553
+ ;
554
+
555
+ expression
556
+ : ( member assignment_op )=> member assignment_op^ expression
557
+ | conditional
558
+ ;
559
+
560
+ assignment_op
561
+ : '='
562
+ | '*='
563
+ | SLASH_ASGN
564
+ | MOD_ASGN
565
+ | '+='
566
+ | '-='
567
+ | '<<='
568
+ | '>>='
569
+ | '>>>='
570
+ | '&='
571
+ | '^='
572
+ | '||='
573
+ | '|='
574
+ ;
575
+
576
+ conditional
577
+ : logical_or ( '?'^ t=expression ':'! f=expression )?
578
+ ;
579
+
580
+ logical_or
581
+ : logical_and ( '||'^ logical_and )*
582
+ ;
583
+
584
+ logical_and
585
+ : bit_or ( '&&'^ bit_or )*
586
+ ;
587
+
588
+ bit_or
589
+ : bit_xor ( '|'^ bit_xor )*
590
+ ;
591
+
592
+ bit_xor
593
+ : bit_and ( '^'^ bit_and )*
594
+ ;
595
+
596
+ bit_and
597
+ : equality ( '&'^ equality )*
598
+ ;
599
+
600
+ equality
601
+ : relation
602
+ (
603
+ ( '=='^ | '!='^ | '==='^ | '!=='^ )
604
+ relation
605
+ )*
606
+ ;
607
+
608
+ relation
609
+ : shift ( relation_op^ shift )*
610
+ ;
611
+
612
+ relation_op
613
+ : '<'
614
+ | '>'
615
+ | '<='
616
+ | '>='
617
+ | 'instanceof'
618
+ | { !( $InFor.last && $InFor::active ) }?=> 'in'
619
+ ;
620
+
621
+ shift
622
+ : add ( ( '<<'^ | '>>'^ | '>>>'^ ) add )*
623
+ ;
624
+
625
+ add
626
+ : mult ( ( '+'^ | '-'^ ) mult )*
627
+ ;
628
+
629
+ mult
630
+ : unary ( ( '*'^ | SLASH^ | MOD^ ) unary )*
631
+ ;
632
+
633
+ unary
634
+ : 'delete' unary -> ^( 'delete' unary )
635
+ | 'void' unary -> ^( 'void' unary )
636
+ | 'typeof' unary -> ^( 'typeof' unary )
637
+ | 'defined?' unary -> ^( 'defined?' unary )
638
+ | 'undefined?' unary -> ^( 'undefined?' unary )
639
+ | '++' unary -> ^( '++' unary )
640
+ | '--' unary -> ^( '--' unary )
641
+ | '+' unary -> ^( UPLUS[ '+' ] unary )
642
+ | '-' unary -> ^( UMINUS[ '-' ] unary )
643
+ | '~' unary -> ^( '~' unary )
644
+ | '!' unary -> ^( '!' unary )
645
+ | postfix -> postfix
646
+ ;
647
+
648
+ postfix
649
+ : member
650
+ ( { same_line? }?=>
651
+ ( '++' -> ^( POST_INCR[ '++' ] member )
652
+ | '--' -> ^( POST_DECR[ '--' ] member )
653
+ )
654
+ | -> member
655
+ )
656
+ ;
657
+
658
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
659
+ // Atomic Expressions
660
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
661
+
662
+ member
663
+ : ( receiver -> receiver )
664
+ ( accessor -> { prepend_tree( $accessor.tree, $tree ) }
665
+ | arguments -> ^( CALL $member arguments )
666
+ | { same_line? }?=>
667
+ iteration -> ^( ITER $member iteration )
668
+ )*
669
+ ;
670
+
671
+ accessor
672
+ : '[' expression ']' -> ^( AREF[ '[' ] expression ) //]
673
+ | '.'^ ( ID | STRING | NUMBER | reserved { $reserved.tree.token.type = ID } )
674
+ ;
675
+
676
+ receiver
677
+ : primary -> primary
678
+ | function -> function
679
+ | EJS -> EJS
680
+ | ( 'new' new_target arguments? )=>
681
+ 'new' new_target arguments? -> ^( 'new' new_target arguments? )
682
+ ;
683
+
684
+ new_target
685
+ : ( receiver -> receiver )
686
+ ( accessor -> { prepend_tree( $accessor.tree, $tree ) } )*
687
+ ;
688
+
689
+ arguments
690
+ : '(' ( argument ( ',' argument )* ','? )? ')' -> ^( ARGUMENTS argument* )
691
+ ;
692
+
693
+ argument
694
+ : { property_definition? }?=> property_definition
695
+ | expression
696
+ // dumb trick to keep ANTLR from complaining about assigning type in a parser rule
697
+ | a='&' { t = $a; t.type = FUNC_ARG }
698
+ ;
699
+
700
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
701
+ // Functions / Blocks
702
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
703
+
704
+ macro
705
+ : 'macro'^ variable_name function_parameters? block
706
+ ;
707
+
708
+ function
709
+ : ( function_literal -> function_literal )
710
+ ( catch_clause -> { prepend_tree( $catch_clause.tree, $tree ) } )*
711
+ ( finally_clause -> { prepend_tree( $finally_clause.tree, $tree ) } )?
712
+ ;
713
+
714
+ function_literal
715
+ : 'function'^ variable_name? function_parameters statement_block
716
+ | '->'^ variable_name? function_parameters? statement_block
717
+ ;
718
+
719
+
720
+ //ejs
721
+ // : 'ejs'^ variable_name? function_parameters ':'!? ( GENERAL | STRING | DOC )
722
+ // ;
723
+
724
+ iteration
725
+ @after { @adaptor.set_token_boundaries( $tree.last, $start, $stop ) }
726
+ : '{' iteration_parameters statement_list '}'
727
+ -> iteration_parameters ^( BLOCK['{'] statement_list )
728
+ | 'do' iteration_parameters statement_list 'end'
729
+ -> iteration_parameters ^( BLOCK['do'] statement_list )
730
+ ;
731
+
732
+ function_parameters
733
+ : '(' parameters? ')' -> ^( PARAMS parameters? )
734
+ ;
735
+
736
+ iteration_parameters
737
+ : '|' parameters? '|' -> ^( PARAMS parameters? )
738
+ | -> ^( PARAMS )
739
+ ;
740
+
741
+ parameters
742
+ : parameter ( ',' parameter )* -> parameter+
743
+ ;
744
+
745
+ parameter
746
+ : '*' variable_name -> ^( SPLAT['*'] variable_name )
747
+ | variable_name
748
+ ( '=' expression -> ^( '=' variable_name expression )
749
+ | -> variable_name
750
+ )
751
+ ;
752
+
753
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
754
+ // Literals
755
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
756
+
757
+ primary
758
+ : 'this'^
759
+ | IVAR^
760
+ | variable_name^
761
+ | 'null'^
762
+ | 'true'^
763
+ | 'false'^
764
+ | 'undefined'^
765
+ | NUMBER^
766
+ | STRING^
767
+ | DSTRING^
768
+ | DOC^
769
+ | DDOC^
770
+ | REGEX^
771
+ | GENERAL^
772
+ | DGENERAL^
773
+ | macro_expansion
774
+ | array_literal
775
+ | object_literal
776
+ | '('! expression_list ')'!
777
+ ;
778
+
779
+ macro_expansion
780
+ : '#'^ ID arguments
781
+ ;
782
+
783
+ array_literal
784
+ : '[' ']' -> ^( ARRAY )
785
+ | '[' list_item ( ',' list_item )* ']' -> ^( ARRAY list_item* )
786
+ ;
787
+
788
+ list_item
789
+ : { @input.peek( 2 ) == COLON }?=> property_name ':' expression -> ^( ':' property_name expression )
790
+ | ( ',' )=> -> ^( UNDEFINED )
791
+ | expression -> expression
792
+ ;
793
+
794
+ object_literal
795
+ : '{' '}' -> ^( OBJECT )
796
+ | '{' property_definition ( ',' property_definition )* '}'
797
+ -> ^( OBJECT property_definition+ )
798
+ ;
799
+
800
+ property_definition
801
+ : 'get'^ ID function_parameters? block
802
+ | 'set'^ ID function_parameters? block
803
+ | ( ID | STRING | NUMBER | reserved { $reserved.tree.token.type = ID } )
804
+ ( ':'^ expression
805
+ | t='->'^ function_parameters? statement_block
806
+ )
807
+ ;
808
+
809
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
810
+ // Names and Words
811
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
812
+
813
+ property_name
814
+ : ID
815
+ | STRING
816
+ | NUMBER
817
+ | reserved { $reserved.tree.token.type = ID }
818
+ ;
819
+
820
+ variable_name
821
+ : ID
822
+ | t=pseudokeyword { $t.tree.token.type = ID }
823
+ ;
824
+
825
+ browser_name
826
+ : 'opera'
827
+ | 'firefox'
828
+ | 'chrome'
829
+ ;
830
+
831
+ pseudokeyword
832
+ : 'each'
833
+ | 'get'
834
+ | 'set'
835
+ | 'macro'
836
+ | 'opera'
837
+ | 'firefox'
838
+ | 'chrome'
839
+ | 'class'
840
+ | 'def'
841
+ | 'object'
842
+ ;
843
+
844
+ reserved
845
+ : 'break' | 'do' | 'function' | 'new' | 'throw' | 'until'
846
+ | 'case' | 'each' | 'get' | 'null' | 'true' | 'var'
847
+ | 'catch' | 'else' | 'if' | 'return' | 'try' | 'void'
848
+ | 'continue' | 'false' | 'in' | 'set' | 'typeof' | 'while'
849
+ | 'default' | 'finally' | 'instanceof' | 'switch' | 'undefined' | 'with'
850
+ | 'delete' | 'for' | 'let' | 'this' | 'unless' | 'yield'
851
+ | 'opera' | 'firefox' | 'chrome' | 'def' | 'class' | 'object'
852
+ ;
853
+
854
+ /********************************************************************************
855
+ *********************************** Lexer ************************************
856
+ ********************************************************************************/
857
+
858
+ MOD
859
+ : '%%' DIRECTIVE_LINE { $type = DIRECTIVE }
860
+ | { @value_expected }?=>
861
+ '%' ( ID ( ' ' | '\t' )* )? { $type = GENERAL } GENERALIZED_DELIMITER
862
+ ( 'a' .. 'z' )*
863
+ | '%' ( '=' { $type = MOD_ASGN } | { $type = MOD } )
864
+ ;
865
+
866
+ SLASH
867
+ : '//' ~( '\n' | '\r' )* { $type = LINE_COMMENT; $channel = HIDDEN }
868
+ | '/*' .* '*/' { $type = COMMENT; $channel = HIDDEN }
869
+ | { @value_expected }?=>
870
+ '/' { $type = REGEX }
871
+ ( ~( '/' | '*' | '\\' | '\r' | '\n' | '#' )
872
+ | '\\' .
873
+ | { at_interpolation? }?=> INTERPOLATION { $type = DREGEX }
874
+ | '#'
875
+ )
876
+ ( ~( '/' | '\\' | '\r' | '\n' | '#' )
877
+ | '\\' .
878
+ | { at_interpolation? }?=> INTERPOLATION { $type = DREGEX }
879
+ | '#'
880
+ )*
881
+ '/'
882
+ ( 'a' .. 'z' )*
883
+ | { !@value_expected }?=> '/' ( '=' { $type = SLASH_ASGN } | { $type = SLASH } )
884
+ ;
885
+
886
+ DOC
887
+ : '`'
888
+ ( ~( '`' | '\\' | '#' )
889
+ | '\\' .
890
+ | { at_interpolation? }?=> INTERPOLATION { $type = DDOC }
891
+ | '#'
892
+ )*
893
+ '`'
894
+ ;
895
+
896
+ STRING
897
+ : '\'' ( ~( '\'' | '\\' ) | '\\' . )* '\''
898
+ | '"'
899
+ ( ~( '"' | '\\' | '#' )
900
+ | '\\' .
901
+ | { at_interpolation? }?=> INTERPOLATION { $type = DSTRING }
902
+ | '#'
903
+ )*
904
+ '"'
905
+ ;
906
+
907
+ NUMBER
908
+ : ('0'..'9')+ '.' ('0'..'9')* ( ('e' | 'E') ('+' | '-')? ('0'..'9')+ )?
909
+ | '.'? ('0'..'9')+ ( ('e' | 'E') ('+' | '-')? ('0'..'9')+ )?
910
+ | '0' ('x' | 'X') ( '0'..'9' | 'a'..'f' | 'A'..'F' )+
911
+ ;
912
+
913
+ NEWLINE
914
+ : ( '\n' | '\r' )+ { $channel = HIDDEN }
915
+ ;
916
+
917
+ IVAR
918
+ : '@' ( '$' | '_' | 'a'..'z' | 'A'..'Z' )
919
+ ( 'a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '$' )*
920
+ ;
921
+
922
+ ID
923
+ : ( '$' | '_' | 'a'..'z' | 'A'..'Z' )
924
+ ( 'a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '$' )*
925
+ ;
926
+
927
+ WS // Tab, vertical tab, form feed, space, non-breaking space and any other unicode "space separator".
928
+ : ( '\t' | '\f' | ' ' | '\u00A0' )+ { $channel = HIDDEN }
929
+ ;
930
+
931
+ EJS
932
+ : 'ejs' IGNORABLE_NL* ID? IGNORABLE_NL*
933
+ '(' { quick_balance( LPAREN, RPAREN ) }
934
+ IGNORABLE_NL*
935
+ '%'? NESTED_BRACES
936
+ ;
937
+
938
+
939
+ fragment
940
+ IGNORABLE
941
+ : '//' ~( '\n' | '\r' )* ( '\r'? '\n' )?
942
+ | '/*' .* '*/'
943
+ | ( '\t' | '\f' | ' ' | '\u00A0' | '\\' '\r'? '\n' )+
944
+ ;
945
+
946
+ fragment
947
+ IGNORABLE_NL
948
+ : '//' ~( '\n' | '\r' )* ( '\r'? '\n' )?
949
+ | '/*' .* '*/'
950
+ | ( '\t' | '\f' | ' ' | '\u00A0' | '\n' | '\r' )+
951
+ ;
952
+
953
+
954
+ fragment
955
+ DIRECTIVE_LINE
956
+ : IGNORABLE*
957
+ ( HIDE
958
+ | REQUIRE
959
+ )
960
+ IGNORABLE*
961
+ ( '\r'? '\n' )?
962
+ ;
963
+
964
+
965
+ fragment
966
+ HIDE
967
+ : 'hide' IGNORABLE*
968
+ '{' { quick_balance( LBRACE, RBRACE ) }
969
+ ;
970
+
971
+ fragment
972
+ REQUIRE
973
+ : ( 'require' | 'include' )
974
+ IGNORABLE*
975
+ (
976
+ ( NESTED_PARENTHESES
977
+ | NESTED_BRACKETS
978
+ | NESTED_BRACES
979
+ | NESTED_ANGLES
980
+ | '"' ( ~( '"' | '\\' ) | '\\' . )* '"'
981
+ | '`' ( ~( '`' | '\\' ) | '\\' . )* '`'
982
+ | '\'' ( ~( '\'' | '\\' ) | '\\' . )* '\''
983
+ )
984
+ | ~( '\r' | '\n' | '(' | '[' | '{' | '<' | '"' | '\'' | '`' )
985
+ ( ~( '\r' | '\n' | ' ' | '\t' | '\f' | '\\' ) | '\\' . )*
986
+ )
987
+ ;
988
+
989
+ fragment
990
+ GENERALIZED_DELIMITER
991
+ : NESTED_PARENTHESES
992
+ | NESTED_BRACKETS
993
+ | NESTED_BRACES
994
+ | NESTED_ANGLES
995
+ | ( '!' | '@' | '~' | '`' | '^' | '&' | '*'
996
+ | '-' | '+' | '=' | '|' | ':' | ';' | '.'
997
+ | ',' | '?' | '/' | '"' | '\''
998
+ )
999
+ { scan_until_delimiter( @input.peek( -1 ) ) }
1000
+ ;
1001
+
1002
+ fragment
1003
+ NESTED_PARENTHESES
1004
+ : '(' ( ~( '(' | ')' | '\\' ) | '\\' . | NESTED_PARENTHESES )* ')'
1005
+ ;
1006
+
1007
+ fragment
1008
+ NESTED_BRACKETS
1009
+ : '[' ( ~( '[' | ']' | '\\' ) | '\\' . | NESTED_BRACKETS )* ']'
1010
+ ;
1011
+
1012
+ fragment
1013
+ NESTED_BRACES
1014
+ : '{' ( ~( '{' | '}' | '\\' ) | '\\' . | NESTED_BRACES )* '}'
1015
+ ;
1016
+
1017
+ fragment
1018
+ NESTED_ANGLES
1019
+ : '<' ( ~( '<' | '>' | '\\' ) | '\\' . | NESTED_ANGLES )* '>'
1020
+ ;
1021
+
1022
+ fragment
1023
+ INTERPOLATION
1024
+ : '#'
1025
+ ( '{' { quick_balance( LBRACE, RBRACE ) }
1026
+ | ( '@' | '%' ) ID
1027
+ | '$' ( '$' | '_' | 'a'..'z' | 'A'..'Z' | '0' .. '9' )*
1028
+ )
1029
+ ;