aboutsummaryrefslogtreecommitdiff
path: root/MoonParser/main.cpp
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2017-07-05 14:30:02 +0800
committerLi Jin <dragon-fly@qq.com>2017-07-05 14:30:02 +0800
commit2dc481058998344b7f97721d47987be3ac053768 (patch)
tree9afd61edfc6d3f079262a3086ebef8cb70943a31 /MoonParser/main.cpp
parent2d074d650ead2142857ff9f8b192b061d1506eca (diff)
downloadyuescript-2dc481058998344b7f97721d47987be3ac053768.tar.gz
yuescript-2dc481058998344b7f97721d47987be3ac053768.tar.bz2
yuescript-2dc481058998344b7f97721d47987be3ac053768.zip
Learn PEGTL a little.
Diffstat (limited to 'MoonParser/main.cpp')
-rw-r--r--MoonParser/main.cpp1399
1 files changed, 1399 insertions, 0 deletions
diff --git a/MoonParser/main.cpp b/MoonParser/main.cpp
new file mode 100644
index 0000000..332b1b4
--- /dev/null
+++ b/MoonParser/main.cpp
@@ -0,0 +1,1399 @@
1//
2// main.cpp
3// PegtlStudy
4//
5// Created by Li Jin on 2017/6/16.
6// Copyright © 2017年 Li Jin. All rights reserved.
7//
8
9#include <iostream>
10#include <unordered_set>
11#include <vector>
12#include <queue>
13#include <stack>
14#include "pegtl.hpp"
15#include "pegtl/analyze.hpp"
16#include "slice.h"
17using namespace silly;
18
19using namespace tao::pegtl;
20
21namespace helloworld // with operator precedence climbing
22{
23 struct Stack
24 {
25 Stack()
26 {
27 pushStack();
28 }
29 void pushValue(int value)
30 {
31 _values.back().push(value);
32 }
33 void pushOp(char op)
34 {
35 _ops.back().push(op);
36 }
37 void pushStack()
38 {
39 _values.emplace_back();
40 _ops.emplace_back();
41 }
42 int getPriority(char op)
43 {
44 switch (op)
45 {
46 case '+': return 1;
47 case '-': return 1;
48 case '*': return 2;
49 case '/': return 2;
50 }
51 return 0;
52 }
53 /*
54 def compute_expr(tokenizer, min_prec):
55 atom_lhs = tokenizer.get_next_token()
56
57 while True:
58 cur = tokenizer.cur_token
59 if (cur is None or OPINFO_MAP[cur.value].prec < min_prec):
60 break
61
62 op = cur.value
63 prec, assoc = OPINFO_MAP[op]
64 next_min_prec = prec + 1 if assoc == 'LEFT' else prec
65
66 atom_rhs = compute_expr(tokenizer, next_min_prec)
67
68 atom_lhs = compute_op(op, atom_lhs, atom_rhs)
69
70 return atom_lhs
71 */
72 int parseNext(int minPrecedence)
73 {
74 int lhs = _values.back().front();
75 _values.back().pop();
76
77 while (true)
78 {
79 if (_ops.back().empty())
80 {
81 break;
82 }
83 char op = _ops.back().front();
84 if (getPriority(op) < minPrecedence)
85 {
86 break;
87 }
88 _ops.back().pop();
89 int nextMinPrecedence = getPriority(op) + 1;
90 int rhs = parseNext(nextMinPrecedence);
91 switch (op)
92 {
93 case '+':
94 std::cout << lhs << " + " << rhs << " = " << lhs+rhs << '\n';
95 lhs = lhs + rhs;
96 break;
97 case '-':
98 std::cout << lhs << " - " << rhs << " = " << lhs-rhs << '\n';
99 lhs = lhs - rhs;
100 break;
101 case '*':
102 std::cout << lhs << " * " << rhs << " = " << lhs*rhs << '\n';
103 lhs = lhs * rhs;
104 break;
105 case '/':
106 std::cout << lhs << " / " << rhs << " = " << lhs/rhs << '\n';
107 lhs = lhs / rhs;
108 break;
109 }
110 }
111 return lhs;
112 }
113 void popStack()
114 {
115 int value = parseNext(0);
116 _values.pop_back();
117 if (_values.empty())
118 {
119 _values.emplace_back();
120 }
121 _ops.pop_back();
122 if (_ops.empty())
123 {
124 _ops.emplace_back();
125 }
126 pushValue(value);
127 }
128 int getValue() const
129 {
130 return _values.back().back();
131 }
132 private:
133 std::vector<std::queue<char>> _ops;
134 std::vector<std::queue<int>> _values;
135 };
136
137 struct number : seq<opt<one<'+', '-'>>, plus<digit>> { };
138
139 struct expr;
140
141 struct bracket : if_must<one<'('>, expr, one<')'>> { };
142
143 struct atomic : sor<number, bracket> { };
144
145 struct op : one<'+', '-', '*', '/'> { };
146
147 struct expr : list<atomic, op, space> { };
148
149 template<typename Rule>
150 struct action : nothing<Rule> { };
151
152 template<>
153 struct action<number>
154 {
155 template<typename Input>
156 static void apply(const Input& in, Stack& stack)
157 {
158 stack.pushValue(std::stoi(in.string()));
159 }
160 };
161
162 template<>
163 struct action<op>
164 {
165 template<typename Input>
166 static void apply(const Input& in, Stack& stack)
167 {
168 stack.pushOp(*in.begin());
169 }
170 };
171
172 template<>
173 struct action<one<'('>>
174 {
175 static void apply0(Stack& stack)
176 {
177 stack.pushStack();
178 }
179 };
180
181 template<>
182 struct action<expr>
183 {
184 template<typename Input>
185 static void apply(const Input& in, Stack& stack)
186 {
187 stack.popStack();
188 }
189 };
190
191} // namespace hello
192
193namespace moon
194{
195 struct State
196 {
197 State()
198 {
199 indents.push(0);
200 stringOpen = -1;
201 }
202 size_t stringOpen;
203 std::stack<int> indents;
204 std::stack<bool> doStack;
205 std::unordered_set<std::string> keywords =
206 {
207 "and", "while", "else", "using", "continue",
208 "local", "not", "then", "return", "from",
209 "extends", "for", "do", "or", "export",
210 "class", "in", "unless", "when", "elseif",
211 "switch", "break", "if", "with", "import"
212 };
213 };
214
215 struct White : star<one<' ', '\t', '\r', '\n'>> {};
216 struct plain_space : star<one<' ', '\t'>> {};
217 struct Break : seq<opt<one<'\r'>>, one<'\n'>> {};
218 struct Stop : sor<Break, eof> {};
219 struct Comment : seq<string<'-', '-'>, star<not_one<'\r', '\n'>>, Stop> {};
220 struct Indent : star<one<' ', '\t'>> {};
221 struct Space : seq<plain_space, opt<Comment>> {};
222 struct SomeSpace : seq<plus<blank>, opt<Comment>> {};
223 struct SpaceBreak : seq<Space, Break> {};
224 typedef SpaceBreak EmptyLine;
225 struct AlphaNum : ranges<'a', 'z', 'A', 'Z', '0', '9', '_', '_'> {};
226 struct _Name : seq<ranges<'a', 'z', 'A', 'Z', '_', '_'>, star<AlphaNum>> {};
227 struct SpaceName : seq<Space, _Name> {};
228 struct _Num : sor<
229 seq<
230 string<'0' ,'x'>,
231 plus<ranges<'0', '9', 'a', 'f', 'A', 'F'>>,
232 opt<seq<
233 opt<one<'u', 'U'>>, one<'l', 'L'>, one<'l', 'L'>
234 >>
235 >,
236 seq<
237 plus<range<'0', '9'>>,
238 seq<
239 opt<one<'u', 'U'>>, one<'l', 'L'>, one<'l', 'L'>
240 >
241 >,
242 seq<
243 sor<
244 seq<
245 plus<range<'0', '9'>>,
246 opt<seq<
247 one<'.'>, plus<range<'0', '9'>>
248 >>
249 >,
250 seq<
251 one<'.'>,
252 plus<range<'0', '9'>>
253 >
254 >,
255 opt<seq<
256 one<'e', 'E'>, opt<one<'-'>>, plus<range<'0', '9'>>
257 >>
258 >
259 > {};
260 struct Num : seq<Space, _Num> {};
261
262 struct Cut : failure {};
263
264 template<char... Cs> struct sym : seq<Space, string<Cs...>> {};
265 template<char... Cs> struct symx : string<Cs...> {};
266
267 template<typename patt, typename finally>
268 struct ensure : sor<seq<patt, finally>, seq<finally, Cut>> {};
269
270 template<char... Cs> struct key : seq<Space, string<Cs...>, not_at<AlphaNum>> {};
271 template<char... Cs> struct op : seq<Space, string<Cs...>, not_at<AlphaNum>> {};
272
273 struct Name
274 {
275 using analyze_t = analysis::generic<analysis::rule_type::ANY>;
276
277 template<apply_mode A, rewind_mode M,
278 template<typename...> class Action,
279 template<typename...> class Control,
280 typename Input>
281 static bool match(Input& in, const State& st)
282 {
283 const char* current = in.current();
284 if (SpaceName::match<A, M, Action, Control>(in, st))
285 {
286 auto name = slice::Slice(current, in.current() - current + 1);
287 name.trimSpace();
288 auto it = st.keywords.find(name);
289 if (it == st.keywords.end())
290 {
291 return true;
292 }
293 }
294 return false;
295 }
296 };
297
298 struct self : one<'@'> {};
299 struct self_name : seq<one<'@'>, _Name> {};
300 struct self_class : string<'@', '@'> {};
301 struct self_class_name : seq<string<'@', '@'>, _Name> {};
302
303 struct SelfName : seq<Space, sor<self_class_name, self_class, self_name, self>> {};
304 struct KeyName : sor<SelfName, SpaceName> {};
305 struct VarArg : seq<Space, string<'.', '.', '.'>> {};
306
307 struct CheckIndent
308 {
309 using analyze_t = analysis::generic<analysis::rule_type::ANY>;
310
311 template<apply_mode A, rewind_mode M,
312 template<typename...> class Action,
313 template<typename...> class Control,
314 typename Input>
315 static bool match(Input& in, const State& st)
316 {
317 const char* current = in.current();
318 if (Indent::match<A, M, Action, Control>(in, st))
319 {
320 int indent = 0;
321 for (const char* ch = current; ch < in.current(); ch++)
322 {
323 switch (*ch)
324 {
325 case ' ': indent++; break;
326 case '\t': indent += 4; break;
327 }
328 }
329 return st.indents.top() == indent;
330 }
331 return false;
332 }
333 };
334
335 struct Advance
336 {
337 using analyze_t = analysis::generic<analysis::rule_type::ANY>;
338
339 template<apply_mode A, rewind_mode M,
340 template<typename...> class Action,
341 template<typename...> class Control,
342 typename Input>
343 static bool match(Input& in, State& st)
344 {
345 const char* current = in.current();
346 if (Indent::match<A, M, Action, Control>(in))
347 {
348 int indent = 0;
349 for (const char* ch = current; ch < in.current(); ch++)
350 {
351 switch (*ch)
352 {
353 case ' ': indent++; break;
354 case '\t': indent += 4; break;
355 }
356 }
357 int top = st.indents.top();
358 if (top != -1 && indent > top)
359 {
360 st.indents.push(indent);
361 }
362 return true;
363 }
364 return false;
365 }
366 };
367
368 struct PushIndent
369 {
370 using analyze_t = analysis::generic<analysis::rule_type::ANY>;
371
372 template<apply_mode A, rewind_mode M,
373 template<typename...> class Action,
374 template<typename...> class Control,
375 typename Input>
376 static bool match(Input& in, State& st)
377 {
378 const char* current = in.current();
379 if (Indent::match<A, M, Action, Control>(in))
380 {
381 int indent = 0;
382 for (const char* ch = current; ch < in.current(); ch++)
383 {
384 switch (*ch)
385 {
386 case ' ': indent++; break;
387 case '\t': indent += 4; break;
388 }
389 }
390 st.indents.push(indent);
391 return true;
392 }
393 return false;
394 }
395 };
396
397 struct PreventIndent
398 {
399 using analyze_t = analysis::generic<analysis::rule_type::ANY>;
400
401 template<apply_mode A, rewind_mode M,
402 template<typename...> class Action,
403 template<typename...> class Control,
404 typename Input>
405 static bool match(Input& in, State& st)
406 {
407 st.indents.push(-1);
408 return true;
409 }
410 };
411
412 struct PopIndent
413 {
414 using analyze_t = analysis::generic<analysis::rule_type::ANY>;
415
416 template<apply_mode A, rewind_mode M,
417 template<typename...> class Action,
418 template<typename...> class Control,
419 typename Input>
420 static bool match(Input& in, State& st)
421 {
422 if (st.indents.size() > 1) st.indents.pop();
423 return true;
424 }
425 };
426
427 struct Block;
428
429 struct InBlock : seq<Advance, Block, PopIndent> {};
430
431 struct NameList;
432
433 struct Local : seq<key<'l', 'o', 'c', 'a', 'l'>, sor<sor<op<'*'>, op<'^'>>>, NameList> {};
434
435 struct colon_import_name : seq<one<'\\'>, Name> {};
436 struct ImportName : sor<colon_import_name, Name> {};
437 struct ImportNameList : seq<
438 star<SpaceBreak>,
439 ImportName,
440 star<
441 sor<plus<SpaceBreak>, seq<sym<','>, star<SpaceBreak>>>,
442 ImportName
443 >
444 > {};
445
446 struct Exp;
447
448 struct Import : seq<key<'i', 'm', 'p', 'o', 'r', 't'>, ImportNameList, star<SpaceBreak>, key<'f', 'r', 'o', 'm'>, Exp> {};
449
450 struct BreakLoop : sor<key<'b', 'r', 'e', 'a', 'k'>, key<'c', 'o', 'n', 't', 'i', 'n', 'u', 'e'>> {};
451
452 struct ExpListLow;
453
454 struct ExpList;
455 struct Assign;
456
457 struct Return : seq<key<'r', 'e', 't', 'u', 'r', 'n'>, sor<ExpListLow, success>> {};
458 struct WithExp : seq<ExpList, opt<Assign>> {};
459
460 struct DisableDo;
461 struct PopDo;
462 struct Body;
463
464 struct With : seq<key<'w', 'i', 't', 'h'>, DisableDo, ensure<WithExp, PopDo>, opt<key<'d', 'o'>>, Body> {};
465
466 struct SwitchCase : seq<key<'w', 'h', 'e', 'n'>, ExpList, opt<key<'t', 'h', 'e', 'n'>>, Body> {};
467 struct SwitchElse : seq<key<'e', 'l', 's', 'e'>, Body> {};
468 struct SwitchBlock : seq<
469 star<EmptyLine>,
470 Advance,
471 seq<
472 SwitchCase,
473 star<plus<Break>, SwitchCase>,
474 opt<plus<Break>, SwitchElse>
475 >,
476 PopIndent
477 > {};
478 struct Switch : seq<key<'s', 'w', 'i', 't', 'c', 'h'>, DisableDo, ensure<Exp, PopDo>, opt<key<'d', 'o'>>, opt<Space>, Break, SwitchBlock> {};
479
480 struct IfCond : seq<Exp, opt<Assign>> {};
481
482 struct IfElse : seq<
483 opt<Break, star<EmptyLine>, CheckIndent>,
484 string<'e', 'l', 's', 'e'>, Body
485 > {};
486 struct IfElseIf : seq<
487 opt<Break, star<EmptyLine>, CheckIndent>,
488 key<'e', 'l', 's', 'e', 'i', 'f'>, IfCond,
489 opt<key<'t', 'h', 'e', 'n'>>, Body
490 > {};
491
492 struct If : seq<key<'i', 'f'>, IfCond, opt<key<'t', 'h', 'e', 'n'>>, Body, star<IfElseIf>, opt<IfElse>> {};
493 struct Unless : seq<key<'u', 'n', 'l', 'e', 's', 's'>, IfCond, opt<key<'t', 'h', 'e', 'n'>>, Body, star<IfElseIf>, opt<IfElse>> {};
494
495 struct While : seq<key<'w', 'h', 'i', 'l', 'e'>, DisableDo, ensure<Exp, PopDo>, opt<key<'d','o'>>, Body> {};
496 struct For : seq<key<'f', 'o', 'r'>, DisableDo,
497 ensure<
498 seq<
499 Name, sym<'='>,
500 seq<Exp, sym<','>, Exp, opt<sym<','>, Exp>>
501 >,
502 PopDo
503 >,
504 opt<key<'d', 'o'>>, Body> {};
505
506 struct AssignableNameList;
507
508 struct ForEach : seq<
509 key<'f', 'o', 'r'>,
510 AssignableNameList,
511 key<'i', 'n'>,
512 DisableDo,
513 ensure<
514 sor<
515 seq<sym<'*'>, Exp>, ExpList
516 >,
517 PopDo
518 >
519 > {};
520
521 struct Do
522 {
523 using analyze_t = analysis::generic<analysis::rule_type::ANY>;
524
525 template<apply_mode A, rewind_mode M,
526 template<typename...> class Action,
527 template<typename...> class Control,
528 typename Input>
529 static bool match(Input& in, State& st)
530 {
531 if (seq<key<'d', 'o'>, Body>::match<A, M, Action, Control>(in, st))
532 {
533 if (st.doStack.empty() || st.doStack.top())
534 {
535 return true;
536 }
537 }
538 return false;
539 }
540 };
541
542 struct DisableDo
543 {
544 using analyze_t = analysis::generic<analysis::rule_type::ANY>;
545
546 template<apply_mode A, rewind_mode M,
547 template<typename...> class Action,
548 template<typename...> class Control,
549 typename Input>
550 static bool match(Input& in, State& st)
551 {
552 st.doStack.push(false);
553 return true;
554 }
555 };
556
557 struct PopDo
558 {
559 using analyze_t = analysis::generic<analysis::rule_type::ANY>;
560
561 template<apply_mode A, rewind_mode M,
562 template<typename...> class Action,
563 template<typename...> class Control,
564 typename Input>
565 static bool match(Input& in, State& st)
566 {
567 st.doStack.pop();
568 return true;
569 }
570 };
571
572 struct CompInner;
573
574 struct Comprehension : seq<sym<'['>, Exp, CompInner, sym<']'>> {};
575 struct TblComprehension : seq<sym<'{'>, seq<Exp, opt<sym<','>, Exp>>, CompInner, sym<'}'>> {};
576
577 struct CompForEach;
578 struct CompFor;
579 struct CompClause;
580
581 struct CompInner : seq<sor<CompForEach, CompFor>, star<CompClause>> {};
582 struct CompForEach : seq<
583 key<'f', 'o', 'r'>,
584 AssignableNameList,
585 key<'i', 'n'>,
586 sor<
587 seq<sym<'*'>, Exp>, Exp
588 >
589 > {};
590 struct CompFor : seq<key<'f', 'o', 'r'>, Name, sym<'='>, seq<Exp, sym<','>, Exp, opt<sym<','>, Exp>>> {};
591 struct CompClause : sor<CompFor, CompForEach, seq<key<'w', 'h', 'e', 'n'>, Exp>> {};
592
593 struct TableBlock;
594
595 struct Assign : seq<sym<'='>, sor<With, If, Switch, TableBlock, ExpListLow>> {};
596
597 struct Update : seq<sor<
598 sym<'.', '.', '='>,
599 sym<'+', '='>,
600 sym<'-', '='>,
601 sym<'*', '='>,
602 sym<'/', '='>,
603 sym<'%', '='>,
604 sym<'o', 'r', '='>,
605 sym<'a', 'n', 'd', '='>,
606 sym<'&', '='>,
607 sym<'|', '='>,
608 sym<'>', '>', '='>,
609 sym<'<', '<', '='>
610 >, Exp> {};
611
612 struct CharOperators : seq<Space, one<'+', '-', '*' ,'/', '%', '^', '>', '<', '|', '&'>> {};
613 struct WordOperators : sor<
614 op<'o', 'r'>,
615 op<'a', 'n', 'd'>,
616 op<'<', '='>,
617 op<'>', '='>,
618 op<'~', '='>,
619 op<'!', '='>,
620 op<'=', '='>,
621 op<'.', '.'>,
622 op<'<', '<'>,
623 op<'>', '>'>,
624 op<'/', '/'>> {};
625 struct BinaryOperator : seq<sor<CharOperators, WordOperators>, star<SpaceBreak>> {};
626
627 struct Chain;
628
629 struct Assignable : sor<Chain, Name, SelfName> {};
630
631 struct Value;
632
633 struct Exp : seq<Value, star<BinaryOperator, Value>> {};
634
635 struct Callable;
636 struct InvokeArgs;
637
638 struct ChainValue : seq<sor<Chain, Callable>, opt<InvokeArgs>> {};
639
640 struct KeyValueList;
641 struct String;
642 struct SimpleValue;
643
644 struct Value : sor<String, SimpleValue, KeyValueList, ChainValue> {};
645 struct SliceValue : Exp {};
646
647 struct LuaString;
648
649 struct single_string_inner : sor<string<'\\','\''>, string<'\\', '\\'>, not_one<'\''>> {};
650 struct SingleString : seq<symx<'\''>, star<single_string_inner>, sym<'\''>> {};
651 struct interp : seq<symx<'#', '{'>, Exp, sym<'}'>> {};
652 struct double_string_plain : sor<string<'\\','\"'>, string<'\\', '\\'>, not_one<'\"'>> {};
653 struct double_string_inner : plus<seq<not_at<interp>, double_string_plain>> {};
654 struct DoubleString : seq<symx<'\"'>, star<sor<double_string_inner, interp>>, sym<'\"'>> {};
655 struct String : sor<seq<Space, DoubleString>, seq<Space, SingleString>, LuaString> {};
656
657 struct lua_string_open : seq<one<'['>, star<one<'='>>, one<'['>> {};
658 struct lua_string_close : seq<one<']'>, star<one<'='>>, one<']'>> {};
659
660 struct LuaStringOpen
661 {
662 using analyze_t = analysis::generic<analysis::rule_type::ANY>;
663
664 template<apply_mode A, rewind_mode M,
665 template<typename...> class Action,
666 template<typename...> class Control,
667 typename Input>
668 static bool match(Input& in, State& st)
669 {
670 const char* current = in.current();
671 if (lua_string_open::match<A, M, Action, Control>(in, st))
672 {
673 st.stringOpen = in.current() - current + 1;
674 return true;
675 }
676 return false;
677 }
678 };
679
680 struct LuaStringClose
681 {
682 using analyze_t = analysis::generic<analysis::rule_type::ANY>;
683
684 template<apply_mode A, rewind_mode M,
685 template<typename...> class Action,
686 template<typename...> class Control,
687 typename Input>
688 static bool match(Input& in, State& st)
689 {
690 const char* current = in.current();
691 if (lua_string_close::match<A, M, Action, Control>(in, st))
692 {
693 return st.stringOpen == in.current() - current + 1;
694 }
695 return false;
696 }
697 };
698
699 struct LuaStringContent : star<not_at<LuaStringClose>, any> {};
700
701 struct LuaString
702 {
703 using analyze_t = analysis::generic<analysis::rule_type::ANY>;
704
705 template<apply_mode A, rewind_mode M,
706 template<typename...> class Action,
707 template<typename...> class Control,
708 typename Input>
709 static bool match(Input& in, State& st)
710 {
711 bool result = seq<LuaStringOpen, opt<Break>, LuaStringContent, LuaStringClose>::match<A, M, Action, Control>(in, st);
712 st.stringOpen = -1;
713 return result;
714 }
715 };
716
717 struct Parens : seq<sym<'('>, star<SpaceBreak>, Exp, star<SpaceBreak>, sym<')'>> {};
718 struct Callable : sor<Name, SelfName, VarArg, Parens> {};
719
720 struct FnArgsExpList : seq<Exp, star<sor<Break, one<','>>, White, Exp>> {};
721 struct FnArgs : sor<
722 seq<symx<'('>, star<SpaceBreak>, opt<FnArgsExpList>, star<SpaceBreak>, sym<')'>>,
723 seq<sym<'!'>, not_at<one<'='>>>
724 > {};
725
726 struct ChainItems;
727 struct DotChainItem;
728 struct ColonChain;
729
730 struct Chain : sor<
731 seq<sor<Callable, String, not_one<'.', '\\'>>, ChainItems>,
732 seq<Space,
733 sor<
734 seq<DotChainItem, opt<ChainItems>>,
735 ColonChain
736 >
737 >
738 > {};
739
740 struct ChainItem;
741
742 struct ChainItems : sor<
743 seq<plus<ChainItem>, opt<ColonChain>>,
744 ColonChain
745 > {};
746
747 struct Invoke;
748 struct Slice;
749
750 struct ChainItem : sor<
751 Invoke,
752 DotChainItem,
753 Slice,
754 seq<symx<'['>, Exp, sym<']'>>
755 > {};
756
757 struct DotChainItem : seq<symx<'.'>, _Name> {};
758 struct ColonChainItem : seq<symx<'\\'>, _Name> {};
759 struct ColonChain : seq<
760 ColonChainItem,
761 opt<Invoke, opt<ChainItems>>
762 > {};
763
764 struct SliceOne : success {};
765 struct SliceTwo : success {};
766 struct Slice : seq<
767 symx<'['>, sor<SliceValue, SliceOne>, sym<','>, sor<SliceValue, SliceTwo>, opt<sym<','>, SliceValue>, sym<']'>> {};
768
769 struct Invoke : sor<
770 FnArgs,
771 SingleString,
772 DoubleString,
773 seq<at<one<'['>>, LuaString>
774 > {};
775
776 struct KeyValue;
777 struct TableValueList;
778 struct TableLitLine;
779
780 struct TableValue : sor<KeyValue, Exp> {};
781 struct TableLit : seq<
782 sym<'{'>,
783 seq<
784 opt<TableValueList>, opt<sym<','>>,
785 opt<
786 SpaceBreak, TableLitLine,
787 star<opt<sym<','>>, SpaceBreak, TableLitLine>,
788 opt<sym<','>>
789 >
790 >,
791 White, sym<'}'>
792 > {};
793
794 struct TableValueList : seq<TableValue, star<sym<','>, TableValue>> {};
795 struct TableLitLine : sor<
796 seq<PushIndent, sor<seq<TableValueList, PopIndent>, seq<PopIndent, Cut>>>,
797 Space
798 > {};
799
800 struct KeyValueLine;
801
802 struct TableBlockInner : seq<KeyValueLine, star<plus<SpaceBreak>, KeyValueLine>> {};
803 struct TableBlock : seq<plus<SpaceBreak>, Advance, ensure<TableBlockInner, PopIndent>> {};
804
805 struct Statement;
806
807 struct ClassLine : seq<
808 CheckIndent,
809 seq<
810 sor<KeyValueList, Statement, Exp>,
811 opt<sym<','>>
812 >
813 > {};
814
815 struct ClassBlock : seq<plus<SpaceBreak>, Advance, ClassLine, star<plus<SpaceBreak>, ClassLine>, PopIndent> {};
816
817 struct class_no_derive : success {};
818 struct class_no_extend : success {};
819 struct class_no_body : success {};
820 struct ClassDecl : seq<
821 string<'c', 'l', 'a', 's', 's'>,
822 not_at<one<':'>>,
823 sor<Assignable, class_no_derive>,
824 opt<sor<string<'e', 'x', 't', 'e', 'n', 'd', 's'>, PreventIndent, ensure<Exp, PopIndent>, class_no_extend>>,
825 sor<ClassBlock, class_no_body>
826 > {};
827
828 struct Export : seq<
829 string<'e', 'x', 'p', 'o', 'r', 't'>,
830 sor<
831 ClassDecl,
832 op<'*'>,
833 op<'^'>,
834 seq<NameList, opt<sym<'='>, ExpListLow>>
835 >
836 > {};
837
838 struct KeyValue : sor<
839 seq<sym<':'>, not_at<SomeSpace>, Name>,
840 seq<
841 sor<
842 KeyName,
843 seq<sym<'['>, Exp, sym<']'>>,
844 seq<Space, DoubleString>,
845 seq<Space, SingleString>
846 >,
847 symx<':'>,
848 sor<
849 Exp, TableBlock, seq<plus<SpaceBreak>, Exp>
850 >
851 >
852 > {};
853
854 struct KeyValueList : seq<KeyValue, star<sym<','>, KeyValue>> {};
855 struct KeyValueLine : seq<CheckIndent, KeyValueList, opt<sym<','>>> {};
856
857 struct FnArgDef : seq<sor<Name, SelfName>, opt<sym<'='>, Exp>> {};
858
859 struct FnArgDefList : sor<
860 seq<
861 FnArgDef,
862 star<sor<sym<','>, Break>, White, FnArgDef>,
863 star<sor<sym<','>, Break>, White, VarArg>
864 >,
865 VarArg
866 > {};
867
868 struct outer_value_shadow : seq<string<'u', 's', 'i', 'n', 'g'>, sor<NameList, seq<Space, string<'n', 'i', 'l'>>>> {};
869 struct outer_value_no_shadowing : success {};
870 struct without_args_def : success {};
871
872 struct FnArgsDef : sor<
873 seq<sym<'('>, White, opt<FnArgDefList>,
874 sor<
875 outer_value_shadow,
876 outer_value_no_shadowing
877 >,
878 White, sym<')'>
879 >,
880 without_args_def
881 > {};
882
883 struct FunLit : seq<FnArgsDef, sor<sym<'-', '>'>, sym<'=', '>'>>, sor<Body, success>> {};
884
885 struct NameList : seq<Name, star<sym<','>, Name>> {};
886 struct NameOrDestructure : sor<Name, TableLit> {};
887 struct AssignableNameList : seq<NameOrDestructure, star<sym<','>, NameOrDestructure>> {};
888
889 struct ExpList : seq<Exp, star<sym<','>, Exp>> {};
890 struct ExpListLow : seq<Exp, star<sor<sym<','>, sym<';'>, Exp>>> {};
891
892 struct ArgLine : seq<CheckIndent, ExpList> {};
893 struct ArgBlock : seq<ArgLine, star<sym<','>, SpaceBreak, ArgLine>, PopIndent> {};
894
895 struct InvokeArgs : seq<
896 at<not_one<'-'>>,
897 sor<
898 seq<
899 ExpList,
900 opt<sor<
901 seq<
902 sym<','>,
903 sor<
904 TableBlock, seq<SpaceBreak, Advance, ArgBlock, opt<TableBlock>>
905 >
906 >,
907 TableBlock
908 >>
909 >,
910 TableBlock
911 >
912 > {};
913
914 struct SimpleValue : sor<
915 key<'n', 'i', 'l'>,
916 key<'t', 'r', 'u', 'e'>,
917 key<'f', 'a', 'l', 's', 'e'>,
918 If, Unless, Switch, With, ClassDecl, ForEach, For, While, Do,
919 seq<sym<'-'>, not_at<SomeSpace>, Exp>,
920 seq<sym<'#'>, Exp>,
921 seq<sym<'~'>, Exp>,
922 seq<key<'n', 'o', 't'>, Exp>,
923 TblComprehension,
924 TableLit,
925 Comprehension,
926 FunLit,
927 Num
928 > {};
929
930 struct Assignment : seq<
931 ExpList,
932 sor<Update, Assign>
933 > {};
934
935 struct Sentence : sor<
936 Import, While, With, For, ForEach,
937 Switch, Return, Local, Export, BreakLoop,
938 Assignment, ExpList
939 > {};
940
941 struct Statement : seq<
942 Sentence,
943 Space,
944 opt<
945 sor<
946 seq<
947 key<'i', 'f'>, Exp,
948 opt<
949 key<'e', 'l', 's', 'e'>, Exp
950 >,
951 Space
952 >,
953 seq<key<'u', 'n', 'l', 'e', 's', 's'>, Exp>,
954 CompInner
955 >,
956 Space
957 >
958 > {};
959
960 struct Body : sor<
961 seq<opt<Space>, Break, star<EmptyLine>, InBlock>,
962 Statement
963 > {};
964
965 struct Line : sor<
966 seq<CheckIndent, Statement>,
967 seq<Space, at<Stop>>
968 > {};
969
970 struct Block : seq<Line, star<plus<Break>, Line>> {};
971
972 struct BlockWithEnd : seq<Block, eolf> {};
973
974 template<typename Rule>
975 struct action : nothing<Rule> {};
976
977 template<>
978 struct action<Assignment>
979 {
980 template<typename Input>
981 static void apply(const Input& in, State&)
982 {
983 std::cout << "Assignment: " << in.string() << '\n';
984 }
985 };
986
987 template<>
988 struct action<Return>
989 {
990 template<typename Input>
991 static void apply(const Input& in, State&)
992 {
993 std::cout << "Return: " << in.string() << "\n\n";
994 }
995 };
996}
997
998int main()
999{
1000 analyze<moon::BlockWithEnd>();
1001 moon::State state;
1002 string_input<> inName(R"xoxo(
1003debug_grammar = false
1004lpeg = require "lpeg"
1005
1006lpeg.setmaxstack 10000 -- whoa
1007
1008err_msg = "Failed to parse:%s\n [%d] >> %s"
1009
1010import Stack from require "moonscript.data"
1011import trim, pos_to_line, get_line from require "moonscript.util"
1012import unpack from require "moonscript.util"
1013import wrap_env from require "moonscript.parse.env"
1014
1015{
1016 :R, :S, :V, :P, :C, :Ct, :Cmt, :Cg, :Cb, :Cc
1017} = lpeg
1018
1019{
1020 :White, :Break, :Stop, :Comment, :Space, :SomeSpace, :SpaceBreak, :EmptyLine,
1021 :AlphaNum, :Num, :Shebang, :L
1022 Name: _Name
1023} = require "moonscript.parse.literals"
1024
1025SpaceName = Space * _Name
1026Num = Space * (Num / (v) -> {"number", v})
1027
1028{
1029 :Indent, :Cut, :ensure, :extract_line, :mark, :pos, :flatten_or_mark,
1030 :is_assignable, :check_assignable, :format_assign, :format_single_assign,
1031 :sym, :symx, :simple_string, :wrap_func_arg, :join_chain,
1032 :wrap_decorator, :check_lua_string, :self_assign, :got
1033
1034} = require "moonscript.parse.util"
1035
1036
1037build_grammar = wrap_env debug_grammar, (root) ->
1038 _indent = Stack 0
1039 _do_stack = Stack 0
1040
1041 state = {
1042 -- last pos we saw, used to report error location
1043 last_pos: 0
1044 }
1045
1046 check_indent = (str, pos, indent) ->
1047 state.last_pos = pos
1048 _indent\top! == indent
1049
1050 advance_indent = (str, pos, indent) ->
1051 top = _indent\top!
1052 if top != -1 and indent > top
1053 _indent\push indent
1054 true
1055
1056 push_indent = (str, pos, indent) ->
1057 _indent\push indent
1058 true
1059
1060 pop_indent = ->
1061 assert _indent\pop!, "unexpected outdent"
1062 true
1063
1064 check_do = (str, pos, do_node) ->
1065 top = _do_stack\top!
1066 if top == nil or top
1067 return true, do_node
1068 false
1069
1070 disable_do = ->
1071 _do_stack\push false
1072 true
1073
1074 pop_do = ->
1075 assert _do_stack\pop! != nil, "unexpected do pop"
1076 true
1077
1078 DisableDo = Cmt "", disable_do
1079 PopDo = Cmt "", pop_do
1080
1081 keywords = {}
1082 key = (chars) ->
1083 keywords[chars] = true
1084 Space * chars * -AlphaNum
1085
1086 op = (chars) ->
1087 patt = Space * C chars
1088 -- it's a word, treat like keyword
1089 if chars\match "^%w*$"
1090 keywords[chars] = true
1091 patt *= -AlphaNum
1092
1093 patt
1094
1095 Name = Cmt(SpaceName, (str, pos, name) ->
1096 return false if keywords[name]
1097 true
1098 ) / trim
1099
1100 SelfName = Space * "@" * (
1101 "@" * (_Name / mark"self_class" + Cc"self.__class") +
1102 _Name / mark"self" +
1103 Cc"self" -- @ by itself
1104 )
1105
1106 KeyName = SelfName + Space * _Name / mark"key_literal"
1107 VarArg = Space * P"..." / trim
1108
1109 g = P {
1110 root or File
1111 File: Shebang^-1 * (Block + Ct"")
1112 Block: Ct(Line * (Break^1 * Line)^0)
1113 CheckIndent: Cmt(Indent, check_indent), -- validates line is in correct indent
1114 Line: (CheckIndent * Statement + Space * L(Stop))
1115
1116 Statement: pos(
1117 Import + While + With + For + ForEach + Switch + Return +
1118 Local + Export + BreakLoop +
1119 Ct(ExpList) * (Update + Assign)^-1 / format_assign
1120 ) * Space * ((
1121 -- statement decorators
1122 key"if" * Exp * (key"else" * Exp)^-1 * Space / mark"if" +
1123 key"unless" * Exp / mark"unless" +
1124 CompInner / mark"comprehension"
1125 ) * Space)^-1 / wrap_decorator
1126
1127 Body: Space^-1 * Break * EmptyLine^0 * InBlock + Ct(Statement) -- either a statement, or an indented block
1128
1129 Advance: L Cmt(Indent, advance_indent) -- Advances the indent, gives back whitespace for CheckIndent
1130 PushIndent: Cmt(Indent, push_indent)
1131 PreventIndent: Cmt(Cc(-1), push_indent)
1132 PopIndent: Cmt("", pop_indent)
1133 InBlock: Advance * Block * PopIndent
1134
1135 Local: key"local" * ((op"*" + op"^") / mark"declare_glob" + Ct(NameList) / mark"declare_with_shadows")
1136
1137 Import: key"import" * Ct(ImportNameList) * SpaceBreak^0 * key"from" * Exp / mark"import"
1138 ImportName: (sym"\\" * Ct(Cc"colon" * Name) + Name)
1139 ImportNameList: SpaceBreak^0 * ImportName * ((SpaceBreak^1 + sym"," * SpaceBreak^0) * ImportName)^0
1140
1141 BreakLoop: Ct(key"break"/trim) + Ct(key"continue"/trim)
1142
1143 Return: key"return" * (ExpListLow/mark"explist" + C"") / mark"return"
1144
1145 WithExp: Ct(ExpList) * Assign^-1 / format_assign
1146 With: key"with" * DisableDo * ensure(WithExp, PopDo) * key"do"^-1 * Body / mark"with"
1147
1148 Switch: key"switch" * DisableDo * ensure(Exp, PopDo) * key"do"^-1 * Space^-1 * Break * SwitchBlock / mark"switch"
1149
1150 SwitchBlock: EmptyLine^0 * Advance * Ct(SwitchCase * (Break^1 * SwitchCase)^0 * (Break^1 * SwitchElse)^-1) * PopIndent
1151 SwitchCase: key"when" * Ct(ExpList) * key"then"^-1 * Body / mark"case"
1152 SwitchElse: key"else" * Body / mark"else"
1153
1154 IfCond: Exp * Assign^-1 / format_single_assign
1155
1156 IfElse: (Break * EmptyLine^0 * CheckIndent)^-1 * key"else" * Body / mark"else"
1157 IfElseIf: (Break * EmptyLine^0 * CheckIndent)^-1 * key"elseif" * pos(IfCond) * key"then"^-1 * Body / mark"elseif"
1158
1159 If: key"if" * IfCond * key"then"^-1 * Body * IfElseIf^0 * IfElse^-1 / mark"if"
1160 Unless: key"unless" * IfCond * key"then"^-1 * Body * IfElseIf^0 * IfElse^-1 / mark"unless"
1161
1162 While: key"while" * DisableDo * ensure(Exp, PopDo) * key"do"^-1 * Body / mark"while"
1163
1164 For: key"for" * DisableDo * ensure(Name * sym"=" * Ct(Exp * sym"," * Exp * (sym"," * Exp)^-1), PopDo) *
1165 key"do"^-1 * Body / mark"for"
1166
1167 ForEach: key"for" * Ct(AssignableNameList) * key"in" * DisableDo * ensure(Ct(sym"*" * Exp / mark"unpack" + ExpList), PopDo) * key"do"^-1 * Body / mark"foreach"
1168
1169 Do: key"do" * Body / mark"do"
1170
1171 Comprehension: sym"[" * Exp * CompInner * sym"]" / mark"comprehension"
1172
1173 TblComprehension: sym"{" * Ct(Exp * (sym"," * Exp)^-1) * CompInner * sym"}" / mark"tblcomprehension"
1174
1175 CompInner: Ct((CompForEach + CompFor) * CompClause^0)
1176 CompForEach: key"for" * Ct(AssignableNameList) * key"in" * (sym"*" * Exp / mark"unpack" + Exp) / mark"foreach"
1177 CompFor: key "for" * Name * sym"=" * Ct(Exp * sym"," * Exp * (sym"," * Exp)^-1) / mark"for"
1178 CompClause: CompFor + CompForEach + key"when" * Exp / mark"when"
1179
1180 Assign: sym"=" * (Ct(With + If + Switch) + Ct(TableBlock + ExpListLow)) / mark"assign"
1181 Update: ((sym"..=" + sym"+=" + sym"-=" + sym"*=" + sym"/=" + sym"%=" + sym"or=" + sym"and=" + sym"&=" + sym"|=" + sym">>=" + sym"<<=") / trim) * Exp / mark"update"
1182
1183 CharOperators: Space * C(S"+-*/%^><|&")
1184 WordOperators: op"or" + op"and" + op"<=" + op">=" + op"~=" + op"!=" + op"==" + op".." + op"<<" + op">>" + op"//"
1185 BinaryOperator: (WordOperators + CharOperators) * SpaceBreak^0
1186
1187 Assignable: Cmt(Chain, check_assignable) + Name + SelfName
1188 Exp: Ct(Value * (BinaryOperator * Value)^0) / flatten_or_mark"exp"
1189
1190 SimpleValue:
1191 If + Unless +
1192 Switch +
1193 With +
1194 ClassDecl +
1195 ForEach + For + While +
1196 Cmt(Do, check_do) +
1197 sym"-" * -SomeSpace * Exp / mark"minus" +
1198 sym"#" * Exp / mark"length" +
1199 sym"~" * Exp / mark"bitnot" +
1200 key"not" * Exp / mark"not" +
1201 TblComprehension +
1202 TableLit +
1203 Comprehension +
1204 FunLit +
1205 Num
1206
1207 -- a function call or an object access
1208 ChainValue: (Chain + Callable) * Ct(InvokeArgs^-1) / join_chain
1209
1210 Value: pos(
1211 SimpleValue +
1212 Ct(KeyValueList) / mark"table" +
1213 ChainValue +
1214 String)
1215
1216 SliceValue: Exp
1217
1218 String: Space * DoubleString + Space * SingleString + LuaString
1219 SingleString: simple_string("'")
1220 DoubleString: simple_string('"', true)
1221
1222 LuaString: Cg(LuaStringOpen, "string_open") * Cb"string_open" * Break^-1 *
1223 C((1 - Cmt(C(LuaStringClose) * Cb"string_open", check_lua_string))^0) *
1224 LuaStringClose / mark"string"
1225
1226 LuaStringOpen: sym"[" * P"="^0 * "[" / trim
1227 LuaStringClose: "]" * P"="^0 * "]"
1228
1229 Callable: pos(Name / mark"ref") + SelfName + VarArg + Parens / mark"parens"
1230 Parens: sym"(" * SpaceBreak^0 * Exp * SpaceBreak^0 * sym")"
1231
1232 FnArgs: symx"(" * SpaceBreak^0 * Ct(FnArgsExpList^-1) * SpaceBreak^0 * sym")" + sym"!" * -P"=" * Ct""
1233 FnArgsExpList: Exp * ((Break + sym",") * White * Exp)^0
1234
1235 Chain: (Callable + String + -S".\\") * ChainItems / mark"chain" +
1236 Space * (DotChainItem * ChainItems^-1 + ColonChain) / mark"chain"
1237
1238 ChainItems: ChainItem^1 * ColonChain^-1 + ColonChain
1239
1240 ChainItem:
1241 Invoke +
1242 DotChainItem +
1243 Slice +
1244 symx"[" * Exp/mark"index" * sym"]"
1245
1246 DotChainItem: symx"." * _Name/mark"dot"
1247 ColonChainItem: symx"\\" * _Name / mark"colon"
1248 ColonChain: ColonChainItem * (Invoke * ChainItems^-1)^-1
1249
1250 Slice: symx"[" * (SliceValue + Cc(1)) * sym"," * (SliceValue + Cc"") *
1251 (sym"," * SliceValue)^-1 *sym"]" / mark"slice"
1252
1253 Invoke: FnArgs / mark"call" +
1254 SingleString / wrap_func_arg +
1255 DoubleString / wrap_func_arg +
1256 L(P"[") * LuaString / wrap_func_arg
1257
1258 TableValue: KeyValue + Ct(Exp)
1259
1260 TableLit: sym"{" * Ct(
1261 TableValueList^-1 * sym","^-1 *
1262 (SpaceBreak * TableLitLine * (sym","^-1 * SpaceBreak * TableLitLine)^0 * sym","^-1)^-1
1263 ) * White * sym"}" / mark"table"
1264
1265 TableValueList: TableValue * (sym"," * TableValue)^0
1266 TableLitLine: PushIndent * ((TableValueList * PopIndent) + (PopIndent * Cut)) + Space
1267
1268 -- the unbounded table
1269 TableBlockInner: Ct(KeyValueLine * (SpaceBreak^1 * KeyValueLine)^0)
1270 TableBlock: SpaceBreak^1 * Advance * ensure(TableBlockInner, PopIndent) / mark"table"
1271
1272 ClassDecl: key"class" * -P":" * (Assignable + Cc(nil)) * (key"extends" * PreventIndent * ensure(Exp, PopIndent) + C"")^-1 * (ClassBlock + Ct("")) / mark"class"
1273
1274 ClassBlock: SpaceBreak^1 * Advance *
1275 Ct(ClassLine * (SpaceBreak^1 * ClassLine)^0) * PopIndent
1276 ClassLine: CheckIndent * ((
1277 KeyValueList / mark"props" +
1278 Statement / mark"stm" +
1279 Exp / mark"stm"
1280 ) * sym","^-1)
1281
1282 Export: key"export" * (
1283 Cc"class" * ClassDecl +
1284 op"*" + op"^" +
1285 Ct(NameList) * (sym"=" * Ct(ExpListLow))^-1) / mark"export"
1286
1287 KeyValue: (sym":" * -SomeSpace * Name * lpeg.Cp!) / self_assign +
1288 Ct(
1289 (KeyName + sym"[" * Exp * sym"]" +Space * DoubleString + Space * SingleString) *
1290 symx":" *
1291 (Exp + TableBlock + SpaceBreak^1 * Exp)
1292 )
1293
1294 KeyValueList: KeyValue * (sym"," * KeyValue)^0
1295 KeyValueLine: CheckIndent * KeyValueList * sym","^-1
1296
1297 FnArgsDef: sym"(" * White * Ct(FnArgDefList^-1) *
1298 (key"using" * Ct(NameList + Space * "nil") + Ct"") *
1299 White * sym")" + Ct"" * Ct""
1300
1301 FnArgDefList: FnArgDef * ((sym"," + Break) * White * FnArgDef)^0 * ((sym"," + Break) * White * Ct(VarArg))^0 + Ct(VarArg)
1302 FnArgDef: Ct((Name + SelfName) * (sym"=" * Exp)^-1)
1303
1304 FunLit: FnArgsDef *
1305 (sym"->" * Cc"slim" + sym"=>" * Cc"fat") *
1306 (Body + Ct"") / mark"fndef"
1307
1308 NameList: Name * (sym"," * Name)^0
1309 NameOrDestructure: Name + TableLit
1310 AssignableNameList: NameOrDestructure * (sym"," * NameOrDestructure)^0
1311
1312 ExpList: Exp * (sym"," * Exp)^0
1313 ExpListLow: Exp * ((sym"," + sym";") * Exp)^0
1314
1315 -- open args
1316 InvokeArgs: -P"-" * (ExpList * (sym"," * (TableBlock + SpaceBreak * Advance * ArgBlock * TableBlock^-1) + TableBlock)^-1 + TableBlock)
1317 ArgBlock: ArgLine * (sym"," * SpaceBreak * ArgLine)^0 * PopIndent
1318 ArgLine: CheckIndent * ExpList
1319 }
1320
1321 g, state
1322
1323file_parser = ->
1324 g, state = build_grammar!
1325 file_grammar = White * g * White * -1
1326
1327 {
1328 match: (str) =>
1329 local tree
1330 _, err = xpcall (->
1331 tree = file_grammar\match str
1332 ), (err) ->
1333 debug.traceback err, 2
1334
1335 -- regular error, let it bubble up
1336 if type(err) == "string"
1337 return nil, err
1338
1339 unless tree
1340 local msg
1341 err_pos = state.last_pos
1342
1343 if err
1344 node, msg = unpack err
1345 msg = " " .. msg if msg
1346 err_pos = node[-1]
1347
1348 line_no = pos_to_line str, err_pos
1349 line_str = get_line(str, line_no) or ""
1350 return nil, err_msg\format msg or "", line_no, trim line_str
1351
1352 tree
1353 }
1354
1355{
1356 :extract_line
1357 :build_grammar
1358
1359 -- parse a string as a file
1360 -- returns tree, or nil and error message
1361 string: (str) -> file_parser!\match str
1362}
1363)xoxo", "abc");
1364 try
1365 {
1366 if (parse<must<moon::BlockWithEnd>, moon::action>(inName, state))
1367 {
1368 std::cout << "matched.\n";
1369 }
1370 else
1371 {
1372 std::cout << "not matched.\n";
1373 }
1374 }
1375 catch (parse_error e)
1376 {
1377 std::cout << e.what() << '\n';
1378 }
1379/*
1380 analyze<hello::expr>();
1381 const char* text = "1 + 2 + 3 * 4 / 2";
1382 string_input<> in(text, "abc");
1383 try
1384 {
1385 hello::Stack stack;
1386 if (parse<hello::expr, hello::action>(in, stack))
1387 {
1388 std::cout << text << " = " << stack.getValue() << '\n';
1389 }
1390 return 0;
1391 }
1392 catch (parse_error e)
1393 {
1394 std::cout << e.what() << '\n';
1395 return 1;
1396 }
1397*/
1398 return 0;
1399}