jejune 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ ;