-
Notifications
You must be signed in to change notification settings - Fork 3
/
KerboScript.bnf
181 lines (163 loc) · 7.84 KB
/
KerboScript.bnf
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
{
parserClass="ksp.kos.ideaplugin.parser.KerboScriptParser"
parserUtilClass="ksp.kos.ideaplugin.parser.KerboScriptParserUtil"
extends("atom|declare_identifier_clause|declare_parameter_clause|declare_function_clause|run_stmt")="ksp.kos.ideaplugin.psi.impl.KerboScriptNamedElementImpl"
implements("atom|declare_identifier_clause|declare_parameter_clause|declare_function_clause|run_stmt")="ksp.kos.ideaplugin.psi.KerboScriptNamedElement"
extends("instruction_block")="ksp.kos.ideaplugin.psi.impl.KerboScriptScopeImpl"
implements("instruction_block")="ksp.kos.ideaplugin.psi.KerboScriptScope"
psiClassPrefix="KerboScript"
psiImplClassSuffix="Impl"
psiPackage="ksp.kos.ideaplugin.psi"
psiImplPackage="ksp.kos.ideaplugin.psi.impl"
elementTypeHolderClass="ksp.kos.ideaplugin.psi.KerboScriptTypes"
elementTypeClass="ksp.kos.ideaplugin.psi.KerboScriptElementType"
tokenTypeClass="ksp.kos.ideaplugin.psi.KerboScriptTokenType"
extends(".*_stmt|directive|instruction_block")=instruction
extends("lazyglobal_directive")=directive
extends("function_trailer|array_trailer")=suffixterm_trailer
extends("varidentifier")=suffix
extends("[a-z]*_expr|factor|suffix|suffixterm|atom|.*number")=expr
}
// Rules
// ===================================================
Start ::= (instruction)*
instruction_block ::= CURLYOPEN instruction* CURLYCLOSE EOI?
instruction ::= set_stmt |
if_stmt |
until_stmt |
fromloop_stmt |
unlock_stmt |
print_stmt |
on_stmt |
toggle_stmt |
wait_stmt |
when_stmt |
stage_stmt |
clear_stmt |
add_stmt |
remove_stmt |
log_stmt |
break_stmt |
preserve_stmt |
declare_stmt |
return_stmt |
switch_stmt |
copy_stmt |
rename_stmt |
delete_stmt |
edit_stmt |
run_stmt |
compile_stmt |
list_stmt |
reboot_stmt |
shutdown_stmt |
for_stmt |
unset_stmt |
instruction_block |
identifier_led_stmt | // any statement that starts with an identifier.
directive // allow directives anywhere for now, let the compiler decide if it's in the wrong place, not the parser.
// ------------ directives --------------------
lazyglobal_directive ::= ATSIGN LAZYGLOBAL onoff_trailer EOI
directive ::= lazyglobal_directive // Add to this list later if we make other directives.
// ------------ statements --------------------
set_stmt ::= SET varidentifier TO expr EOI
if_stmt ::= IF expr instruction (ELSE instruction)? EOI?
until_stmt ::= UNTIL expr instruction EOI?
fromloop_stmt ::= FROM instruction_block UNTIL expr STEP instruction_block DO instruction EOI?
unlock_stmt ::= UNLOCK (IDENTIFIER | ALL) EOI
print_stmt ::= PRINT expr (AT BRACKETOPEN expr COMMA expr BRACKETCLOSE)? EOI
on_stmt ::= ON varidentifier instruction EOI?
toggle_stmt ::= TOGGLE varidentifier EOI
wait_stmt ::= WAIT UNTIL? expr EOI
when_stmt ::= WHEN expr THEN instruction EOI?
onoff_stmt ::= varidentifier onoff_trailer EOI
onoff_trailer ::= (ON | OFF)
stage_stmt ::= STAGE EOI
clear_stmt ::= CLEARSCREEN EOI
add_stmt ::= ADD expr EOI
remove_stmt ::= REMOVE expr EOI
log_stmt ::= LOG expr TO expr EOI
break_stmt ::= BREAK EOI
preserve_stmt ::= PRESERVE EOI
declare_identifier_clause ::= IDENTIFIER (TO|IS) expr EOI
declare_parameter_clause ::= PARAMETER IDENTIFIER ((TO|IS) expr)? (COMMA IDENTIFIER ((TO|IS) expr)?)* EOI
declare_function_clause ::= FUNCTION IDENTIFIER instruction_block EOI?
declare_lock_clause ::= LOCK IDENTIFIER TO expr EOI
declare_stmt ::= // declare|global|local are all optional for function and parameter,
// but mandatory for declaring an identifier. This was the only
// way to get the LL(1) parser to understand that without barfing on
// ambiguity.
(
declare_parameter_clause |
declare_function_clause |
declare_lock_clause |
(
(
(DECLARE (LOCAL|GLOBAL)?) |
(LOCAL|GLOBAL)
)
(
declare_parameter_clause |
declare_function_clause |
declare_identifier_clause |
declare_lock_clause
)
)
)
return_stmt ::= RETURN expr? EOI
switch_stmt ::= SWITCH TO expr EOI
copy_stmt ::= COPY expr (FROM | TO) expr EOI
rename_stmt ::= RENAME (VOLUME | FILE)? expr TO expr EOI
delete_stmt ::= DELETE expr (FROM expr)? EOI
edit_stmt ::= EDIT expr EOI
run_stmt ::= RUN (ONCE)? (FILEIDENT|IDENTIFIER) (BRACKETOPEN arglist BRACKETCLOSE)? (ON expr)? EOI
compile_stmt ::= COMPILE expr (TO expr)? EOI
list_stmt ::= LIST (IDENTIFIER (IN IDENTIFIER)?)? EOI
reboot_stmt ::= REBOOT EOI
shutdown_stmt ::= SHUTDOWN EOI
for_stmt ::= FOR IDENTIFIER IN varidentifier instruction EOI?
unset_stmt ::= UNSET (IDENTIFIER | ALL) EOI
// ---------- expressions ---------------------------
arglist ::= expr (COMMA expr)*
expr ::= and_expr (OR and_expr)*
and_expr ::= compare_expr (AND compare_expr)*
compare_expr ::= arith_expr (COMPARATOR arith_expr)*
arith_expr ::= multdiv_expr (PLUSMINUS multdiv_expr)*
multdiv_expr ::= unary_expr ((MULT|DIV) unary_expr)*
unary_expr ::= (PLUSMINUS|NOT|DEFINED)? factor
factor ::= suffix (POWER suffix)*
suffix ::= suffixterm (suffix_trailer)*
suffix_trailer ::= (COLON suffixterm)
suffixterm ::= atom suffixterm_trailer*
suffixterm_trailer ::= (function_trailer | array_trailer)
function_trailer ::= (BRACKETOPEN arglist? BRACKETCLOSE)
array_trailer ::= ( (ARRAYINDEX (IDENTIFIER | INTEGER)) | (SQUAREOPEN expr SQUARECLOSE) )
atom ::= ( sci_number |
TRUEFALSE |
IDENTIFIER |
FILEIDENT |
BRACKETOPEN expr BRACKETCLOSE
) | STRING
sci_number ::= number (E PLUSMINUS? INTEGER)?
number ::= (INTEGER | DOUBLE)
// varidentifier:
// --------------
// The subset of expressions that are legal as the lefthand side of an assignment statement:
// This isn't 100% right. Technically this allows the following syntax:
// SET functionCall() to val.
// Which shouldn't be allowed. But fixing it in the grammar file makes TinyPG's LL(1) parser's
// little head spin in a sea of ambiguous confusion, so it will have to be dealt with by the
// compiler checking if the lefthand side of an assignment statement ended up being a
// function call, and if so raise a syntax exception.
varidentifier ::= suffix
// identifier_led_stmt
// -------------------
// Any of the expressions which might start with an identifier and might be used as
// an actual statement on their own (function calls, etc). These had to be pulled
// out of the normal expression tree because they cause LL(1) ambiguities at the
// topmost level in the definition of the instruction rule if it just allowed all
// generic expressions there. It had to be limited to only allowing the types of
// expressions which are led by an identifier and are guaranteed to have SOMETHING
// after the identifier - parens, colons, etc:
identifier_led_stmt ::= identifier_led_expr EOI
identifier_led_expr ::= suffix (onoff_trailer)?