-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgrammar.js
127 lines (123 loc) · 3.63 KB
/
grammar.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
const { anySep1, commaSep, commaSep1, anySep } = require('./common/common')
const literal = require('./common/literal')
const expression = require('./common/expression')
const PREC = {
LOGICAL_OR: 1,
LOGICAL_AND: 2,
INCLUSIVE_OR: 3,
EXCLUSIVE_OR: 4,
BITWISE_AND: 5,
EQUAL: 6,
RELATIONAL: 7,
SHIFT: 9,
ADD: 10,
MULTIPLY: 11,
UNARY: 14,
}
module.exports = {
externals: $ => [$.raw_start, $._raw_char, $.raw_end],
rules: {
...literal.rules,
...expression.rules,
statement: $ =>
seq(
choice(
'endfor',
seq('elif', $.expression),
'else',
'endif',
'endblock',
'endwith',
'endfilter',
'endmacro',
'endcall',
'endset',
'endtrans',
'continue',
'break',
'debug',
'endautoescape',
$.do_statement,
$.include_statement,
$.import_statement,
$.set_statement,
$.for_statement,
$.if_expression,
$.with_statement,
$.call_statement,
$.set_statement,
$.extends_statement,
$.macro_statement,
$.filter_statement,
$.block_statement,
$.pluralize_statement,
$.trans_statement,
$.autoescape_statement,
),
),
do_statement: $ => seq('do', $.expression),
autoescape_statement: $ => seq('autoescape', optional($.boolean_literal)),
trans_statement: $ =>
seq('trans', commaSep(choice($.identifier, $.assignment_expression))),
pluralize_statement: $ => seq('pluralize', optional($.identifier)),
ternary_expression: $ =>
seq('if', $.expression, optional(seq('else', $.expression))),
block_statement: $ => seq('block', $.identifier),
filter_statement: $ => seq('filter', $.expression),
macro_statement: $ => seq('macro', $.function_call),
extends_statement: $ =>
prec.right(
seq(
'extends',
choice($.string_literal, $.identifier),
optional($.ternary_expression),
),
),
call_statement: $ =>
seq('call', optional(seq('(', $.identifier, ')')), $.function_call),
with_statement: $ => seq('with', repeat($.assignment_expression)),
import_statement: $ =>
seq(
optional($.import_from),
'import',
seq(choice(commaSep1($.identifier), $.string_literal)),
optional($.import_as),
optional($.import_attribute),
),
import_from: $ => seq('from', $.string_literal),
import_as: $ => seq('as', commaSep1($.identifier)),
import_attribute: $ => $.attribute_context,
include_statement: $ =>
seq(
'include',
choice($.string_literal, $.identifier, $.list_literal, $.tuple_literal),
repeat($.include_attribute),
),
include_attribute: $ => choice($.attribute_ignore, $.attribute_context),
attribute_ignore: $ => seq('ignore', 'missing'),
attribute_context: $ => seq(choice('with', 'without'), 'context'),
set_statement: $ =>
seq(
'set',
commaSep1($.expression),
alias('=', $.binary_operator),
$.expression,
optional($.ternary_expression),
),
for_statement: $ =>
seq(
'for',
$.in_expression,
optional($.ternary_expression),
optional('recursive'),
),
if_expression: $ => seq('if', $.expression),
_words: _ => prec.right(repeat1(choice(/[^\{]/, /\{[^\#\%]/))),
identifier: $ => /[a-zA-Z_][\w\d_]*/,
comment: $ =>
choice(
seq('##', /[^\r\n]*/, /\r?\n/),
seq('{#', repeat(choice(/[^#]+/, '#')), '#}'),
),
},
}