diff options
Diffstat (limited to 'src/MoonP/moon_parser.cpp')
-rw-r--r-- | src/MoonP/moon_parser.cpp | 526 |
1 files changed, 526 insertions, 0 deletions
diff --git a/src/MoonP/moon_parser.cpp b/src/MoonP/moon_parser.cpp new file mode 100644 index 0000000..7b5183e --- /dev/null +++ b/src/MoonP/moon_parser.cpp | |||
@@ -0,0 +1,526 @@ | |||
1 | /* Copyright (c) 2020 Jin Li, http://www.luvfight.me | ||
2 | |||
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
4 | |||
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
6 | |||
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ | ||
8 | |||
9 | #include "MoonP/moon_parser.h" | ||
10 | |||
11 | namespace pl = parserlib; | ||
12 | |||
13 | namespace MoonP { | ||
14 | |||
15 | std::unordered_set<std::string> State::luaKeywords = { | ||
16 | "and", "break", "do", "else", "elseif", | ||
17 | "end", "false", "for", "function", "if", | ||
18 | "in", "local", "nil", "not", "or", | ||
19 | "repeat", "return", "then", "true", "until", | ||
20 | "while" | ||
21 | }; | ||
22 | |||
23 | std::unordered_set<std::string> State::keywords = { | ||
24 | "and", "break", "do", "else", "elseif", | ||
25 | "end", "false", "for", "function", "if", | ||
26 | "in", "local", "nil", "not", "or", | ||
27 | "repeat", "return", "then", "true", "until", | ||
28 | "while", // Lua keywords | ||
29 | "class", "continue", "export", "extends", "from", | ||
30 | "import", "switch", "unless", "using", "when", | ||
31 | "with" // Moon keywords | ||
32 | }; | ||
33 | |||
34 | rule plain_space = *set(" \t"); | ||
35 | rule Break = nl(-expr('\r') >> '\n'); | ||
36 | rule Any = Break | any(); | ||
37 | rule White = *(set(" \t") | Break); | ||
38 | rule Stop = Break | eof(); | ||
39 | rule Comment = "--" >> *(not_(set("\r\n")) >> Any) >> and_(Stop); | ||
40 | rule Indent = *set(" \t"); | ||
41 | rule Space = plain_space >> -Comment; | ||
42 | rule SomeSpace = +set(" \t") >> -Comment; | ||
43 | rule SpaceBreak = Space >> Break; | ||
44 | rule EmptyLine = SpaceBreak; | ||
45 | rule AlphaNum = range('a', 'z') | range('A', 'Z') | range('0', '9') | '_'; | ||
46 | rule Name = (range('a', 'z') | range('A', 'Z') | '_') >> *AlphaNum; | ||
47 | rule Num = | ||
48 | ( | ||
49 | "0x" >> | ||
50 | +(range('0', '9') | range('a', 'f') | range('A', 'F')) >> | ||
51 | -(-set("uU") >> set("lL") >> set("lL")) | ||
52 | ) | ( | ||
53 | +range('0', '9') >> -set("uU") >> set("lL") >> set("lL") | ||
54 | ) | ( | ||
55 | ( | ||
56 | (+range('0', '9') >> -('.' >> +range('0', '9'))) | | ||
57 | ('.' >> +range('0', '9')) | ||
58 | ) >> -(set("eE") >> -expr('-') >> +range('0', '9')) | ||
59 | ); | ||
60 | rule Cut = false_(); | ||
61 | rule Seperator = true_(); | ||
62 | |||
63 | #define sym(str) (Space >> str) | ||
64 | #define symx(str) expr(str) | ||
65 | #define ensure(patt, finally) (((patt) >> (finally)) | ((finally) >> (Cut))) | ||
66 | #define key(str) (Space >> str >> not_(AlphaNum)) | ||
67 | |||
68 | rule Variable = pl::user(Name, [](const item_t& item) { | ||
69 | State* st = reinterpret_cast<State*>(item.user_data); | ||
70 | for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast<char>(*it); | ||
71 | auto it = State::keywords.find(st->buffer); | ||
72 | st->buffer.clear(); | ||
73 | return it == State::keywords.end(); | ||
74 | }); | ||
75 | |||
76 | rule LuaKeyword = pl::user(Name, [](const item_t& item) { | ||
77 | State* st = reinterpret_cast<State*>(item.user_data); | ||
78 | for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast<char>(*it); | ||
79 | auto it = State::luaKeywords.find(st->buffer); | ||
80 | st->buffer.clear(); | ||
81 | return it != State::luaKeywords.end(); | ||
82 | }); | ||
83 | |||
84 | rule self = expr('@'); | ||
85 | rule self_name = '@' >> Name; | ||
86 | rule self_class = expr("@@"); | ||
87 | rule self_class_name = "@@" >> Name; | ||
88 | |||
89 | rule SelfName = Space >> (self_class_name | self_class | self_name | self); | ||
90 | rule KeyName = SelfName | Space >> Name; | ||
91 | rule VarArg = Space >> "..."; | ||
92 | |||
93 | rule check_indent = pl::user(Indent, [](const item_t& item) { | ||
94 | int indent = 0; | ||
95 | for (input_it i = item.begin; i != item.end; ++i) { | ||
96 | switch (*i) { | ||
97 | case ' ': indent++; break; | ||
98 | case '\t': indent += 4; break; | ||
99 | } | ||
100 | } | ||
101 | State* st = reinterpret_cast<State*>(item.user_data); | ||
102 | return st->indents.top() == indent; | ||
103 | }); | ||
104 | rule CheckIndent = and_(check_indent); | ||
105 | |||
106 | rule advance = pl::user(Indent, [](const item_t& item) { | ||
107 | int indent = 0; | ||
108 | for (input_it i = item.begin; i != item.end; ++i) { | ||
109 | switch (*i) { | ||
110 | case ' ': indent++; break; | ||
111 | case '\t': indent += 4; break; | ||
112 | } | ||
113 | } | ||
114 | State* st = reinterpret_cast<State*>(item.user_data); | ||
115 | int top = st->indents.top(); | ||
116 | if (top != -1 && indent > top) { | ||
117 | st->indents.push(indent); | ||
118 | return true; | ||
119 | } | ||
120 | return false; | ||
121 | }); | ||
122 | rule Advance = and_(advance); | ||
123 | |||
124 | rule push_indent = pl::user(Indent, [](const item_t& item) { | ||
125 | int indent = 0; | ||
126 | for (input_it i = item.begin; i != item.end; ++i) { | ||
127 | switch (*i) { | ||
128 | case ' ': indent++; break; | ||
129 | case '\t': indent += 4; break; | ||
130 | } | ||
131 | } | ||
132 | State* st = reinterpret_cast<State*>(item.user_data); | ||
133 | st->indents.push(indent); | ||
134 | return true; | ||
135 | }); | ||
136 | rule PushIndent = and_(push_indent); | ||
137 | |||
138 | rule PreventIndent = pl::user(true_(), [](const item_t& item) { | ||
139 | State* st = reinterpret_cast<State*>(item.user_data); | ||
140 | st->indents.push(-1); | ||
141 | return true; | ||
142 | }); | ||
143 | |||
144 | rule PopIndent = pl::user(true_(), [](const item_t& item) { | ||
145 | State* st = reinterpret_cast<State*>(item.user_data); | ||
146 | st->indents.pop(); | ||
147 | return true; | ||
148 | }); | ||
149 | |||
150 | extern rule Block; | ||
151 | |||
152 | rule InBlock = Advance >> Block >> PopIndent; | ||
153 | |||
154 | extern rule NameList; | ||
155 | |||
156 | rule local_flag = expr('*') | expr('^'); | ||
157 | rule Local = key("local") >> ((Space >> local_flag) | NameList); | ||
158 | |||
159 | rule colon_import_name = sym('\\') >> Space >> Variable; | ||
160 | rule ImportName = colon_import_name | Space >> Variable; | ||
161 | rule ImportNameList = Seperator >> *SpaceBreak >> ImportName >> *((+SpaceBreak | sym(',') >> *SpaceBreak) >> ImportName); | ||
162 | |||
163 | extern rule Exp; | ||
164 | |||
165 | rule Import = key("import") >> ImportNameList >> *SpaceBreak >> key("from") >> Exp; | ||
166 | rule BreakLoop = (expr("break") | expr("continue")) >> not_(AlphaNum); | ||
167 | |||
168 | extern rule ExpListLow, ExpList, Assign; | ||
169 | |||
170 | rule Return = key("return") >> -ExpListLow; | ||
171 | rule WithExp = ExpList >> -Assign; | ||
172 | |||
173 | extern rule DisableDo, PopDo, Body; | ||
174 | |||
175 | rule With = key("with") >> DisableDo >> ensure(WithExp, PopDo) >> -key("do") >> Body; | ||
176 | rule SwitchCase = key("when") >> ExpList >> -key("then") >> Body; | ||
177 | rule SwitchElse = key("else") >> Body; | ||
178 | |||
179 | rule SwitchBlock = *EmptyLine >> | ||
180 | Advance >> Seperator >> | ||
181 | SwitchCase >> | ||
182 | *(+SpaceBreak >> SwitchCase) >> | ||
183 | -(+SpaceBreak >> SwitchElse) >> | ||
184 | PopIndent; | ||
185 | |||
186 | rule Switch = key("switch") >> | ||
187 | DisableDo >> ensure(Exp, PopDo) >> | ||
188 | -key("do") >> -Space >> Break >> SwitchBlock; | ||
189 | |||
190 | rule IfCond = Exp >> -Assign; | ||
191 | rule IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> key("elseif") >> IfCond >> -key("then") >> Body; | ||
192 | rule IfElse = -(Break >> *EmptyLine >> CheckIndent) >> key("else") >> Body; | ||
193 | rule If = key("if") >> Seperator >> IfCond >> -key("then") >> Body >> *IfElseIf >> -IfElse; | ||
194 | rule Unless = key("unless") >> Seperator >> IfCond >> -key("then") >> Body >> *IfElseIf >> -IfElse; | ||
195 | |||
196 | rule While = key("while") >> DisableDo >> ensure(Exp, PopDo) >> -key("do") >> Body; | ||
197 | |||
198 | rule for_step_value = sym(',') >> Exp; | ||
199 | rule for_args = Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; | ||
200 | |||
201 | rule For = key("for") >> DisableDo >> | ||
202 | ensure(for_args, PopDo) >> | ||
203 | -key("do") >> Body; | ||
204 | |||
205 | extern rule AssignableNameList; | ||
206 | |||
207 | extern rule star_exp; | ||
208 | |||
209 | rule for_in = star_exp | ExpList; | ||
210 | |||
211 | rule ForEach = key("for") >> AssignableNameList >> key("in") >> | ||
212 | DisableDo >> ensure(for_in, PopDo) >> | ||
213 | -key("do") >> Body; | ||
214 | |||
215 | rule Do = pl::user(key("do") >> Body, [](const item_t& item) | ||
216 | { | ||
217 | State* st = reinterpret_cast<State*>(item.user_data); | ||
218 | return st->doStack.empty() || st->doStack.top(); | ||
219 | }); | ||
220 | |||
221 | rule DisableDo = pl::user(true_(), [](const item_t& item) | ||
222 | { | ||
223 | State* st = reinterpret_cast<State*>(item.user_data); | ||
224 | st->doStack.push(false); | ||
225 | return true; | ||
226 | }); | ||
227 | |||
228 | rule PopDo = pl::user(true_(), [](const item_t& item) | ||
229 | { | ||
230 | State* st = reinterpret_cast<State*>(item.user_data); | ||
231 | st->doStack.pop(); | ||
232 | return true; | ||
233 | }); | ||
234 | |||
235 | extern rule CompInner; | ||
236 | |||
237 | rule Comprehension = sym('[') >> Exp >> CompInner >> sym(']'); | ||
238 | rule comp_value = sym(',') >> Exp; | ||
239 | rule TblComprehension = sym('{') >> (Exp >> -comp_value) >> CompInner >> sym('}'); | ||
240 | |||
241 | extern rule CompForEach, CompFor, CompClause; | ||
242 | |||
243 | rule CompInner = Seperator >> (CompForEach | CompFor) >> *CompClause; | ||
244 | rule star_exp = sym('*') >> Exp; | ||
245 | rule CompForEach = key("for") >> AssignableNameList >> key("in") >> (star_exp | Exp); | ||
246 | rule CompFor = key("for") >> Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; | ||
247 | rule CompClause = CompFor | CompForEach | key("when") >> Exp; | ||
248 | |||
249 | extern rule TableBlock; | ||
250 | |||
251 | rule Assign = sym('=') >> Seperator >> (With | If | Switch | TableBlock | Exp >> *((sym(',') | sym(';')) >> Exp)); | ||
252 | |||
253 | rule update_op = | ||
254 | expr("..") | | ||
255 | expr("+") | | ||
256 | expr("-") | | ||
257 | expr("*") | | ||
258 | expr("/") | | ||
259 | expr("%") | | ||
260 | expr("or") | | ||
261 | expr("and") | | ||
262 | expr("&") | | ||
263 | expr("|") | | ||
264 | expr(">>") | | ||
265 | expr("<<"); | ||
266 | |||
267 | rule Update = Space >> update_op >> expr("=") >> Exp; | ||
268 | |||
269 | rule BinaryOperator = | ||
270 | (expr("or") >> not_(AlphaNum)) | | ||
271 | (expr("and") >> not_(AlphaNum)) | | ||
272 | expr("<=") | | ||
273 | expr(">=") | | ||
274 | expr("~=") | | ||
275 | expr("!=") | | ||
276 | expr("==") | | ||
277 | expr("..") | | ||
278 | expr("<<") | | ||
279 | expr(">>") | | ||
280 | expr("//") | | ||
281 | set("+-*/%^><|&"); | ||
282 | |||
283 | extern rule AssignableChain; | ||
284 | |||
285 | rule Assignable = AssignableChain | Space >> Variable | SelfName; | ||
286 | |||
287 | extern rule Value; | ||
288 | |||
289 | rule exp_op_value = Space >> BinaryOperator >> *SpaceBreak >> Value; | ||
290 | rule Exp = Value >> *exp_op_value; | ||
291 | |||
292 | extern rule Chain, Callable, InvokeArgs; | ||
293 | |||
294 | rule ChainValue = Seperator >> (Chain | Callable) >> -InvokeArgs; | ||
295 | |||
296 | extern rule KeyValue, String, SimpleValue; | ||
297 | |||
298 | rule simple_table = Seperator >> KeyValue >> *(sym(',') >> KeyValue); | ||
299 | rule Value = SimpleValue | simple_table | ChainValue | String; | ||
300 | |||
301 | extern rule LuaString; | ||
302 | |||
303 | rule single_string_inner = expr("\\'") | "\\\\" | not_(expr('\'')) >> Any; | ||
304 | rule SingleString = symx('\'') >> *single_string_inner >> sym('\''); | ||
305 | rule interp = symx("#{") >> Exp >> sym('}'); | ||
306 | rule double_string_plain = expr("\\\"") | "\\\\" | not_(expr('"')) >> Any; | ||
307 | rule double_string_inner = +(not_(interp) >> double_string_plain); | ||
308 | rule double_string_content = double_string_inner | interp; | ||
309 | rule DoubleString = symx('"') >> Seperator >> *double_string_content >> sym('"'); | ||
310 | rule String = Space >> (DoubleString | SingleString | LuaString); | ||
311 | |||
312 | rule lua_string_open = '[' >> *expr('=') >> '['; | ||
313 | rule lua_string_close = ']' >> *expr('=') >> ']'; | ||
314 | |||
315 | rule LuaStringOpen = pl::user(lua_string_open, [](const item_t& item) | ||
316 | { | ||
317 | size_t count = std::distance(item.begin, item.end); | ||
318 | State* st = reinterpret_cast<State*>(item.user_data); | ||
319 | st->stringOpen = count; | ||
320 | return true; | ||
321 | }); | ||
322 | |||
323 | rule LuaStringClose = pl::user(lua_string_close, [](const item_t& item) | ||
324 | { | ||
325 | size_t count = std::distance(item.begin, item.end); | ||
326 | State* st = reinterpret_cast<State*>(item.user_data); | ||
327 | return st->stringOpen == count; | ||
328 | }); | ||
329 | |||
330 | rule LuaStringContent = *(not_(LuaStringClose) >> (Break | Any)); | ||
331 | |||
332 | rule LuaString = pl::user(LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose, [](const item_t& item) | ||
333 | { | ||
334 | State* st = reinterpret_cast<State*>(item.user_data); | ||
335 | st->stringOpen = -1; | ||
336 | return true; | ||
337 | }); | ||
338 | |||
339 | rule Parens = sym('(') >> *SpaceBreak >> Exp >> *SpaceBreak >> sym(')'); | ||
340 | rule Callable = Space >> Variable | SelfName | VarArg | Parens; | ||
341 | rule FnArgsExpList = Exp >> *((Break | sym(',')) >> White >> Exp); | ||
342 | |||
343 | rule FnArgs = (symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym(')')) | | ||
344 | (sym('!') >> not_(expr('='))); | ||
345 | |||
346 | extern rule ChainItems, DotChainItem, ColonChain; | ||
347 | |||
348 | rule chain_call = (Callable | String) >> ChainItems; | ||
349 | rule chain_item = and_(set(".\\")) >> ChainItems; | ||
350 | rule chain_dot_chain = DotChainItem >> -ChainItems; | ||
351 | |||
352 | rule Chain = chain_call | chain_item | | ||
353 | Space >> (chain_dot_chain | ColonChain); | ||
354 | |||
355 | rule AssignableChain = Seperator >> Chain; | ||
356 | |||
357 | extern rule ChainItem; | ||
358 | |||
359 | rule chain_with_colon = +ChainItem >> -ColonChain; | ||
360 | rule ChainItems = chain_with_colon | ColonChain; | ||
361 | |||
362 | extern rule Invoke, Slice; | ||
363 | |||
364 | rule Index = symx('[') >> Exp >> sym(']'); | ||
365 | rule ChainItem = Invoke | DotChainItem | Slice | Index; | ||
366 | rule DotChainItem = symx('.') >> Name; | ||
367 | rule ColonChainItem = symx('\\') >> (LuaKeyword | Name); | ||
368 | rule invoke_chain = Invoke >> -ChainItems; | ||
369 | rule ColonChain = ColonChainItem >> -invoke_chain; | ||
370 | |||
371 | rule default_value = true_(); | ||
372 | rule Slice = | ||
373 | symx('[') >> | ||
374 | (Exp | default_value) >> | ||
375 | sym(',') >> | ||
376 | (Exp | default_value) >> | ||
377 | (sym(',') >> Exp | default_value) >> | ||
378 | sym(']'); | ||
379 | |||
380 | rule Invoke = Seperator >> ( | ||
381 | FnArgs | | ||
382 | SingleString | | ||
383 | DoubleString | | ||
384 | and_(expr('[')) >> LuaString); | ||
385 | |||
386 | extern rule TableValueList, TableLitLine; | ||
387 | |||
388 | rule TableValue = KeyValue | Exp; | ||
389 | |||
390 | rule table_lit_lines = SpaceBreak >> TableLitLine >> *(-sym(',') >> SpaceBreak >> TableLitLine) >> -sym(','); | ||
391 | |||
392 | rule TableLit = | ||
393 | sym('{') >> Seperator >> | ||
394 | -TableValueList >> | ||
395 | -sym(',') >> | ||
396 | -table_lit_lines >> | ||
397 | White >> sym('}'); | ||
398 | |||
399 | rule TableValueList = TableValue >> *(sym(',') >> TableValue); | ||
400 | |||
401 | rule TableLitLine = | ||
402 | ( | ||
403 | PushIndent >> (TableValueList >> PopIndent | PopIndent) | ||
404 | ) | ( | ||
405 | Space | ||
406 | ); | ||
407 | |||
408 | extern rule KeyValueLine; | ||
409 | |||
410 | rule TableBlockInner = Seperator >> KeyValueLine >> *(+(SpaceBreak) >> KeyValueLine); | ||
411 | rule TableBlock = +(SpaceBreak) >> Advance >> ensure(TableBlockInner, PopIndent); | ||
412 | |||
413 | extern rule Statement; | ||
414 | |||
415 | rule class_member_list = Seperator >> KeyValue >> *(sym(',') >> KeyValue); | ||
416 | rule ClassLine = CheckIndent >> (class_member_list | Statement) >> -sym(','); | ||
417 | rule ClassBlock = +(SpaceBreak) >> Advance >>Seperator >> ClassLine >> *(+(SpaceBreak) >> ClassLine) >> PopIndent; | ||
418 | |||
419 | rule ClassDecl = | ||
420 | key("class") >> not_(expr(':')) >> | ||
421 | -Assignable >> | ||
422 | -(key("extends") >> PreventIndent >> ensure(Exp, PopIndent)) >> | ||
423 | -ClassBlock; | ||
424 | |||
425 | rule export_values = NameList >> -(sym('=') >> ExpListLow); | ||
426 | rule export_op = expr('*') | expr('^'); | ||
427 | rule Export = key("export") >> (ClassDecl | (Space >> export_op) | export_values); | ||
428 | |||
429 | rule variable_pair = sym(':') >> not_(SomeSpace) >> Space >> Variable; | ||
430 | |||
431 | rule normal_pair = | ||
432 | ( | ||
433 | KeyName | | ||
434 | sym('[') >> Exp >> sym(']') | | ||
435 | Space >> DoubleString | | ||
436 | Space >> SingleString | ||
437 | ) >> | ||
438 | symx(':') >> | ||
439 | (Exp | TableBlock | +(SpaceBreak) >> Exp); | ||
440 | |||
441 | rule KeyValue = variable_pair | normal_pair; | ||
442 | |||
443 | rule KeyValueList = KeyValue >> *(sym(',') >> KeyValue); | ||
444 | rule KeyValueLine = CheckIndent >> KeyValueList >> -sym(','); | ||
445 | |||
446 | rule FnArgDef = (Space >> Variable | SelfName) >> -(sym('=') >> Exp); | ||
447 | |||
448 | rule FnArgDefList = Seperator >> | ||
449 | ( | ||
450 | ( | ||
451 | FnArgDef >> | ||
452 | *((sym(',') | Break) >> White >> FnArgDef) >> | ||
453 | -((sym(',') | Break) >> White >> VarArg) | ||
454 | ) | ( | ||
455 | VarArg | ||
456 | ) | ||
457 | ); | ||
458 | |||
459 | rule outer_var_shadow = key("using") >> (NameList | Space >> expr("nil")); | ||
460 | |||
461 | rule FnArgsDef = sym('(') >> White >> -FnArgDefList >> -outer_var_shadow >> White >> sym(')'); | ||
462 | rule fn_arrow = expr("->") | expr("=>"); | ||
463 | rule FunLit = -FnArgsDef >> Space >> fn_arrow >> -Body; | ||
464 | |||
465 | rule NameList = Seperator >> Space >> Variable >> *(sym(',') >> Space >> Variable); | ||
466 | rule NameOrDestructure = Space >> Variable | TableLit; | ||
467 | rule AssignableNameList = Seperator >> NameOrDestructure >> *(sym(',') >> NameOrDestructure); | ||
468 | |||
469 | rule ExpList = Seperator >> Exp >> *(sym(',') >> Exp); | ||
470 | rule ExpListLow = Seperator >> Exp >> *((sym(',') | sym(';')) >> Exp); | ||
471 | |||
472 | rule ArgLine = CheckIndent >> Exp >> *(sym(',') >> Exp); | ||
473 | rule ArgBlock = ArgLine >> *(sym(',') >> SpaceBreak >> ArgLine) >> PopIndent; | ||
474 | |||
475 | rule invoke_args_with_table = | ||
476 | sym(',') >> | ||
477 | ( | ||
478 | TableBlock | | ||
479 | SpaceBreak >> Advance >> ArgBlock >> -TableBlock | ||
480 | ); | ||
481 | |||
482 | rule InvokeArgs = | ||
483 | not_(expr('-')) >> Seperator >> | ||
484 | ( | ||
485 | Exp >> *(sym(',') >> Exp) >> -(invoke_args_with_table | TableBlock) | | ||
486 | TableBlock | ||
487 | ); | ||
488 | |||
489 | rule const_value = (expr("nil") | expr("true") | expr("false")) >> not_(AlphaNum); | ||
490 | rule minus_exp = expr('-') >> not_(SomeSpace) >> Exp; | ||
491 | rule sharp_exp = expr('#') >> Exp; | ||
492 | rule tilde_exp = expr('~') >> Exp; | ||
493 | rule not_exp = expr("not") >> not_(AlphaNum) >> Exp; | ||
494 | rule unary_exp = minus_exp | sharp_exp | tilde_exp | not_exp; | ||
495 | |||
496 | rule SimpleValue = | ||
497 | (Space >> const_value) | | ||
498 | If | Unless | Switch | With | ClassDecl | ForEach | For | While | Do | | ||
499 | (Space >> unary_exp) | | ||
500 | TblComprehension | TableLit | Comprehension | FunLit | | ||
501 | (Space >> Num); | ||
502 | |||
503 | rule ExpListAssign = ExpList >> -(Update | Assign); | ||
504 | |||
505 | rule if_else_line = key("if") >> Exp >> (key("else") >> Exp | default_value); | ||
506 | rule unless_line = key("unless") >> Exp; | ||
507 | |||
508 | rule statement_appendix = (if_else_line | unless_line | CompInner) >> Space; | ||
509 | rule Statement = | ||
510 | ( | ||
511 | Import | While | For | ForEach | | ||
512 | Return | Local | Export | Space >> BreakLoop | | ||
513 | ExpListAssign | ||
514 | ) >> Space >> | ||
515 | -statement_appendix; | ||
516 | |||
517 | rule Body = -Space >> Break >> *EmptyLine >> InBlock | Statement; | ||
518 | |||
519 | rule empty_line_stop = Space >> and_(Stop); | ||
520 | rule Line = CheckIndent >> Statement | empty_line_stop; | ||
521 | rule Block = Seperator >> Line >> *(+Break >> Line); | ||
522 | |||
523 | rule Shebang = expr("#!") >> *(not_(Stop) >> Any); | ||
524 | rule File = White >> -Shebang >> Block >> eof(); | ||
525 | |||
526 | } // namespace MoonP | ||