-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgrammar.template.js
124 lines (95 loc) · 3.73 KB
/
grammar.template.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
module.exports = grammar({
name: 'Howl',
word: $ => $.id,
rules: {
Σ : $ => repeat($._e),
_e : $ => choice( $.modifiers, $.cat, $.op, $.prim, $.bt, $.flow,
$.return, $.key, $.comment, $.z, $._lit, $.id, $.type ),
_lit: $ => choice( $.null, $.bool, $.char, $.real, $.int, $.note, $.str ),
modifiers: $ => prec.right(repeat1($.mod)),
mod : $ => choice(
'public', 'internal', 'protected', 'private', 'static',
'abstract', 'const', 'extern', 'override', 'partial',
'readonly', 'sealed', 'unsafe', 'virtual', 'volatile',
'explicit', 'implicit',
__Mod__),
cat : $ => choice(
'class', 'interface', 'struct', 'enum', 'var', 'delegate',
__Cat__),
op : $ => choice('+', '-',
__Op__),
return : $ => choice('return', __%return%__),
flow: $ => choice(
'async', 'await', 'by', 'if', 'else', 'foreach', 'in', 'for',
'do', 'while', 'switch', 'case', 'break', 'yield',
'try', 'catch', 'finally', 'continue', 'from', 'where',
'select', 'throw', 'join', 'goto', 'lock', 'orderby',
__Flow__),
key: $ => choice(
'add', 'checked', 'into', 'nameof', 'new', 'using', 'value',
'global', 'let',
'operator', 'params', 'this', 'typeof', 'default', 'equals',
'long', 'out', 'ref', 'sizeof', 'descending',
'ascending', 'dynamic', 'fixed', 'group', 'is', 'get', 'set',
'on', 'remove', 'stackalloc', 'unchecked', 'as', 'base',
__Key__
),
prim: $ => choice(
'int', 'bool', 'string', 'float', 'char', 'double', 'byte',
'decimal', 'sbyte', 'short', 'uint', 'ushort', 'object',
'ulong',
__Pr__
),
// [any letter][any letter or digit],
// similar to /[a-zA-Z_][a-zA-Z_0-9]*/ but with foreign
// characters added.
id : $ => token(seq(
optional('@'),
/[\u00C0-\u1FFF\u2C00-\uD7FFa-z_][\u00C0-\u1FFF\u2C00-\uD7FF\w]*/,
)),
// Similar to id but these identifiers starting with [A-Z] are
// assumed to represent type names
type : $ => token(seq(
optional('@'),
/[A-Z][a-zA-Z_0-9]*/,
)),
comment: $ => token(choice(
seq( '//', /.*/ ),
seq( '/*', repeat(choice(/[^*]/, /\*[^/]/ )), '*/' ) )),
// Match 'common' special characters, ie punctuation,
// operators, brackets... in the ASCII range
z: $ => choice(/[!-@]/, /[\x5b-\x60]/, /[\x7b-\x7d]/),
str : $ => token(seq('"', repeat(choice( /[^"]/, '""' )), '"' )),
note : $ => token(seq('⎨', repeat(choice( /[^"]/, '""' )), '⎬' )),
bool: $ => choice('true', 'false', __%true%__, __%false%__),
bt: $ => choice(__%done()%__, __%cont()%__, __%fail()%__),
char: $ => seq(
"'", choice(token.immediate(/[^'\\]/), $.escape_sequence), "'"
),
escape_sequence: $ => token(choice(
/\\x[0-9a-fA-F][0-9a-fA-F]?[0-9a-fA-F]?[0-9a-fA-F]?/,
/\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]/,
/\\U[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]/,
/\\[^xuU]/,
)),
int: $ => token(seq(
choice(
(/[0-9_]+/), // Decimal
(/0[xX][0-9a-fA-F_]+/), // Hex
(/0[bB][01_]+/) // Binary
), optional(/u|U|l|L|ul|UL|uL|Ul|lu|LU|Lu|lU/)
)),
null: $ => choice('null', __%null%__),
real: $ => {
const suffix = /[fFdDmM]/;
const exponent = /[eE][+-]?[0-9_]+/;
return token(choice(
seq( (/[0-9_]+/), '.', (/[0-9_]+/), optional(exponent),
optional(suffix) ),
seq( '.', (/[0-9_]+/), optional(exponent), optional(suffix) ),
seq( (/[0-9_]+/), exponent, optional(suffix) ),
seq( (/[0-9_]+/), suffix )
))
},
} // end-rules
});