diff options
Diffstat (limited to 'src/MoonP/moon_parser.cpp')
-rw-r--r-- | src/MoonP/moon_parser.cpp | 972 |
1 files changed, 510 insertions, 462 deletions
diff --git a/src/MoonP/moon_parser.cpp b/src/MoonP/moon_parser.cpp index baea9bf..60096af 100644 --- a/src/MoonP/moon_parser.cpp +++ b/src/MoonP/moon_parser.cpp | |||
@@ -12,7 +12,7 @@ namespace pl = parserlib; | |||
12 | 12 | ||
13 | namespace MoonP { | 13 | namespace MoonP { |
14 | 14 | ||
15 | std::unordered_set<std::string> State::luaKeywords = { | 15 | std::unordered_set<std::string> LuaKeywords = { |
16 | "and", "break", "do", "else", "elseif", | 16 | "and", "break", "do", "else", "elseif", |
17 | "end", "false", "for", "function", "if", | 17 | "end", "false", "for", "function", "if", |
18 | "in", "local", "nil", "not", "or", | 18 | "in", "local", "nil", "not", "or", |
@@ -20,7 +20,7 @@ std::unordered_set<std::string> State::luaKeywords = { | |||
20 | "while" | 20 | "while" |
21 | }; | 21 | }; |
22 | 22 | ||
23 | std::unordered_set<std::string> State::keywords = { | 23 | std::unordered_set<std::string> Keywords = { |
24 | "and", "break", "do", "else", "elseif", | 24 | "and", "break", "do", "else", "elseif", |
25 | "end", "false", "for", "function", "if", | 25 | "end", "false", "for", "function", "if", |
26 | "in", "local", "nil", "not", "or", | 26 | "in", "local", "nil", "not", "or", |
@@ -31,513 +31,561 @@ std::unordered_set<std::string> State::keywords = { | |||
31 | "when", "with" // Moon keywords | 31 | "when", "with" // Moon keywords |
32 | }; | 32 | }; |
33 | 33 | ||
34 | rule plain_space = *set(" \t"); | 34 | MoonParser::MoonParser() { |
35 | rule Break = nl(-expr('\r') >> '\n'); | 35 | plain_space = *set(" \t"); |
36 | rule Any = Break | any(); | 36 | Break = nl(-expr('\r') >> '\n'); |
37 | rule White = *(set(" \t") | Break); | 37 | Any = Break | any(); |
38 | rule Stop = Break | eof(); | 38 | White = *(set(" \t") | Break); |
39 | rule Comment = "--" >> *(not_(set("\r\n")) >> Any) >> and_(Stop); | 39 | Stop = Break | eof(); |
40 | rule multi_line_open = expr("--[["); | 40 | Comment = "--" >> *(not_(set("\r\n")) >> Any) >> and_(Stop); |
41 | rule multi_line_close = expr("]]"); | 41 | multi_line_open = expr("--[["); |
42 | rule multi_line_content = *(not_(multi_line_close) >> Any); | 42 | multi_line_close = expr("]]"); |
43 | rule MultiLineComment = multi_line_open >> multi_line_content >> multi_line_close; | 43 | multi_line_content = *(not_(multi_line_close) >> Any); |
44 | rule Indent = plain_space; | 44 | MultiLineComment = multi_line_open >> multi_line_content >> multi_line_close; |
45 | rule EscapeNewLine = expr('\\') >> plain_space >> -Comment >> Break; | 45 | Indent = plain_space; |
46 | rule Space = *(set(" \t") | MultiLineComment | EscapeNewLine) >> -Comment; | 46 | EscapeNewLine = expr('\\') >> plain_space >> -Comment >> Break; |
47 | rule SomeSpace = +set(" \t") >> -Comment; | 47 | Space = *(set(" \t") | MultiLineComment | EscapeNewLine) >> -Comment; |
48 | rule SpaceBreak = Space >> Break; | 48 | SomeSpace = +set(" \t") >> -Comment; |
49 | rule EmptyLine = SpaceBreak; | 49 | SpaceBreak = Space >> Break; |
50 | rule AlphaNum = range('a', 'z') | range('A', 'Z') | range('0', '9') | '_'; | 50 | EmptyLine = SpaceBreak; |
51 | rule Name = (range('a', 'z') | range('A', 'Z') | '_') >> *AlphaNum; | 51 | AlphaNum = range('a', 'z') | range('A', 'Z') | range('0', '9') | '_'; |
52 | rule Num = | 52 | Name = (range('a', 'z') | range('A', 'Z') | '_') >> *AlphaNum; |
53 | ( | 53 | Num = |
54 | "0x" >> | ||
55 | +(range('0', '9') | range('a', 'f') | range('A', 'F')) >> | ||
56 | -(-set("uU") >> set("lL") >> set("lL")) | ||
57 | ) | ( | ||
58 | +range('0', '9') >> -set("uU") >> set("lL") >> set("lL") | ||
59 | ) | ( | ||
60 | ( | 54 | ( |
61 | (+range('0', '9') >> -('.' >> +range('0', '9'))) | | 55 | "0x" >> |
62 | ('.' >> +range('0', '9')) | 56 | +(range('0', '9') | range('a', 'f') | range('A', 'F')) >> |
63 | ) >> -(set("eE") >> -expr('-') >> +range('0', '9')) | 57 | -(-set("uU") >> set("lL") >> set("lL")) |
64 | ); | 58 | ) | ( |
65 | rule Cut = false_(); | 59 | +range('0', '9') >> -set("uU") >> set("lL") >> set("lL") |
66 | rule Seperator = true_(); | 60 | ) | ( |
67 | 61 | ( | |
68 | #define sym(str) (Space >> str) | 62 | (+range('0', '9') >> -('.' >> +range('0', '9'))) | |
69 | #define symx(str) expr(str) | 63 | ('.' >> +range('0', '9')) |
70 | #define ensure(patt, finally) (((patt) >> (finally)) | ((finally) >> (Cut))) | 64 | ) >> -(set("eE") >> -expr('-') >> +range('0', '9')) |
71 | #define key(str) (Space >> str >> not_(AlphaNum)) | 65 | ); |
72 | 66 | Cut = false_(); | |
73 | rule Variable = pl::user(Name, [](const item_t& item) { | 67 | Seperator = true_(); |
74 | State* st = reinterpret_cast<State*>(item.user_data); | 68 | |
75 | for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast<char>(*it); | 69 | #define sym(str) (Space >> str) |
76 | auto it = State::keywords.find(st->buffer); | 70 | #define symx(str) expr(str) |
77 | st->buffer.clear(); | 71 | #define ensure(patt, finally) (((patt) >> (finally)) | ((finally) >> (Cut))) |
78 | return it == State::keywords.end(); | 72 | #define key(str) (Space >> str >> not_(AlphaNum)) |
79 | }); | 73 | |
80 | 74 | Variable = pl::user(Name, [](const item_t& item) { | |
81 | rule LuaKeyword = pl::user(Name, [](const item_t& item) { | 75 | State* st = reinterpret_cast<State*>(item.user_data); |
82 | State* st = reinterpret_cast<State*>(item.user_data); | 76 | for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast<char>(*it); |
83 | for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast<char>(*it); | 77 | auto it = Keywords.find(st->buffer); |
84 | auto it = State::luaKeywords.find(st->buffer); | 78 | st->buffer.clear(); |
85 | st->buffer.clear(); | 79 | return it == Keywords.end(); |
86 | return it != State::luaKeywords.end(); | 80 | }); |
87 | }); | 81 | |
88 | 82 | LuaKeyword = pl::user(Name, [](const item_t& item) { | |
89 | rule self = expr('@'); | 83 | State* st = reinterpret_cast<State*>(item.user_data); |
90 | rule self_name = '@' >> Name; | 84 | for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast<char>(*it); |
91 | rule self_class = expr("@@"); | 85 | auto it = LuaKeywords.find(st->buffer); |
92 | rule self_class_name = "@@" >> Name; | 86 | st->buffer.clear(); |
93 | 87 | return it != LuaKeywords.end(); | |
94 | rule SelfName = Space >> (self_class_name | self_class | self_name | self); | 88 | }); |
95 | rule KeyName = SelfName | Space >> Name; | 89 | |
96 | rule VarArg = Space >> "..."; | 90 | self = expr('@'); |
97 | 91 | self_name = '@' >> Name; | |
98 | rule check_indent = pl::user(Indent, [](const item_t& item) { | 92 | self_class = expr("@@"); |
99 | int indent = 0; | 93 | self_class_name = "@@" >> Name; |
100 | for (input_it i = item.begin; i != item.end; ++i) { | 94 | |
101 | switch (*i) { | 95 | SelfName = Space >> (self_class_name | self_class | self_name | self); |
102 | case ' ': indent++; break; | 96 | KeyName = SelfName | Space >> Name; |
103 | case '\t': indent += 4; break; | 97 | VarArg = Space >> "..."; |
98 | |||
99 | check_indent = pl::user(Indent, [](const item_t& item) { | ||
100 | int indent = 0; | ||
101 | for (input_it i = item.begin; i != item.end; ++i) { | ||
102 | switch (*i) { | ||
103 | case ' ': indent++; break; | ||
104 | case '\t': indent += 4; break; | ||
105 | } | ||
104 | } | 106 | } |
105 | } | 107 | State* st = reinterpret_cast<State*>(item.user_data); |
106 | State* st = reinterpret_cast<State*>(item.user_data); | 108 | return st->indents.top() == indent; |
107 | return st->indents.top() == indent; | 109 | }); |
108 | }); | 110 | CheckIndent = and_(check_indent); |
109 | rule CheckIndent = and_(check_indent); | 111 | |
110 | 112 | advance = pl::user(Indent, [](const item_t& item) { | |
111 | rule advance = pl::user(Indent, [](const item_t& item) { | 113 | int indent = 0; |
112 | int indent = 0; | 114 | for (input_it i = item.begin; i != item.end; ++i) { |
113 | for (input_it i = item.begin; i != item.end; ++i) { | 115 | switch (*i) { |
114 | switch (*i) { | 116 | case ' ': indent++; break; |
115 | case ' ': indent++; break; | 117 | case '\t': indent += 4; break; |
116 | case '\t': indent += 4; break; | 118 | } |
117 | } | 119 | } |
118 | } | 120 | State* st = reinterpret_cast<State*>(item.user_data); |
119 | State* st = reinterpret_cast<State*>(item.user_data); | 121 | int top = st->indents.top(); |
120 | int top = st->indents.top(); | 122 | if (top != -1 && indent > top) { |
121 | if (top != -1 && indent > top) { | 123 | st->indents.push(indent); |
124 | return true; | ||
125 | } | ||
126 | return false; | ||
127 | }); | ||
128 | Advance = and_(advance); | ||
129 | |||
130 | push_indent = pl::user(Indent, [](const item_t& item) { | ||
131 | int indent = 0; | ||
132 | for (input_it i = item.begin; i != item.end; ++i) { | ||
133 | switch (*i) { | ||
134 | case ' ': indent++; break; | ||
135 | case '\t': indent += 4; break; | ||
136 | } | ||
137 | } | ||
138 | State* st = reinterpret_cast<State*>(item.user_data); | ||
122 | st->indents.push(indent); | 139 | st->indents.push(indent); |
123 | return true; | 140 | return true; |
124 | } | 141 | }); |
125 | return false; | 142 | PushIndent = and_(push_indent); |
126 | }); | ||
127 | rule Advance = and_(advance); | ||
128 | |||
129 | rule push_indent = pl::user(Indent, [](const item_t& item) { | ||
130 | int indent = 0; | ||
131 | for (input_it i = item.begin; i != item.end; ++i) { | ||
132 | switch (*i) { | ||
133 | case ' ': indent++; break; | ||
134 | case '\t': indent += 4; break; | ||
135 | } | ||
136 | } | ||
137 | State* st = reinterpret_cast<State*>(item.user_data); | ||
138 | st->indents.push(indent); | ||
139 | return true; | ||
140 | }); | ||
141 | rule PushIndent = and_(push_indent); | ||
142 | |||
143 | rule PreventIndent = pl::user(true_(), [](const item_t& item) { | ||
144 | State* st = reinterpret_cast<State*>(item.user_data); | ||
145 | st->indents.push(-1); | ||
146 | return true; | ||
147 | }); | ||
148 | |||
149 | rule PopIndent = pl::user(true_(), [](const item_t& item) { | ||
150 | State* st = reinterpret_cast<State*>(item.user_data); | ||
151 | st->indents.pop(); | ||
152 | return true; | ||
153 | }); | ||
154 | |||
155 | extern rule Block; | ||
156 | |||
157 | rule InBlock = Advance >> Block >> PopIndent; | ||
158 | |||
159 | extern rule NameList; | ||
160 | |||
161 | rule local_flag = expr('*') | expr('^'); | ||
162 | rule Local = key("local") >> ((Space >> local_flag) | NameList); | ||
163 | |||
164 | rule colon_import_name = sym('\\') >> Space >> Variable; | ||
165 | rule ImportName = colon_import_name | Space >> Variable; | ||
166 | rule ImportNameList = Seperator >> *SpaceBreak >> ImportName >> *((+SpaceBreak | sym(',') >> *SpaceBreak) >> ImportName); | ||
167 | |||
168 | extern rule Exp, TableLit; | ||
169 | |||
170 | rule import_literal_inner = (range('a', 'z') | range('A', 'Z') | set("_-")) >> *(AlphaNum | '-'); | ||
171 | rule import_literal_chain = Seperator >> import_literal_inner >> *(expr('.') >> import_literal_inner); | ||
172 | rule ImportLiteral = sym('\'') >> import_literal_chain >> symx('\'') | sym('"') >> import_literal_chain >> symx('"'); | ||
173 | |||
174 | rule ImportFrom = ImportNameList >> *SpaceBreak >> key("from") >> Exp; | ||
175 | rule ImportAs = ImportLiteral >> -(key("as") >> (Space >> Variable | TableLit)); | ||
176 | |||
177 | rule Import = key("import") >> (ImportAs | ImportFrom); | ||
178 | rule BreakLoop = (expr("break") | expr("continue")) >> not_(AlphaNum); | ||
179 | |||
180 | extern rule ExpListLow, ExpList, Assign; | ||
181 | |||
182 | rule Return = key("return") >> -ExpListLow; | ||
183 | rule WithExp = ExpList >> -Assign; | ||
184 | |||
185 | extern rule DisableDo, PopDo, Body; | ||
186 | |||
187 | rule With = key("with") >> DisableDo >> ensure(WithExp, PopDo) >> -key("do") >> Body; | ||
188 | rule SwitchCase = key("when") >> ExpList >> -key("then") >> Body; | ||
189 | rule SwitchElse = key("else") >> Body; | ||
190 | |||
191 | rule SwitchBlock = *EmptyLine >> | ||
192 | Advance >> Seperator >> | ||
193 | SwitchCase >> | ||
194 | *(+SpaceBreak >> SwitchCase) >> | ||
195 | -(+SpaceBreak >> SwitchElse) >> | ||
196 | PopIndent; | ||
197 | |||
198 | rule Switch = key("switch") >> | ||
199 | DisableDo >> ensure(Exp, PopDo) >> | ||
200 | -key("do") >> -Space >> Break >> SwitchBlock; | ||
201 | |||
202 | rule IfCond = Exp >> -Assign; | ||
203 | rule IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> key("elseif") >> IfCond >> -key("then") >> Body; | ||
204 | rule IfElse = -(Break >> *EmptyLine >> CheckIndent) >> key("else") >> Body; | ||
205 | rule If = key("if") >> Seperator >> IfCond >> -key("then") >> Body >> *IfElseIf >> -IfElse; | ||
206 | rule Unless = key("unless") >> Seperator >> IfCond >> -key("then") >> Body >> *IfElseIf >> -IfElse; | ||
207 | |||
208 | rule While = key("while") >> DisableDo >> ensure(Exp, PopDo) >> -key("do") >> Body; | ||
209 | |||
210 | rule for_step_value = sym(',') >> Exp; | ||
211 | rule for_args = Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; | ||
212 | |||
213 | rule For = key("for") >> DisableDo >> | ||
214 | ensure(for_args, PopDo) >> | ||
215 | -key("do") >> Body; | ||
216 | |||
217 | extern rule AssignableNameList; | ||
218 | 143 | ||
219 | extern rule star_exp; | 144 | PreventIndent = pl::user(true_(), [](const item_t& item) { |
220 | 145 | State* st = reinterpret_cast<State*>(item.user_data); | |
221 | rule for_in = star_exp | ExpList; | 146 | st->indents.push(-1); |
222 | 147 | return true; | |
223 | rule ForEach = key("for") >> AssignableNameList >> key("in") >> | 148 | }); |
224 | DisableDo >> ensure(for_in, PopDo) >> | ||
225 | -key("do") >> Body; | ||
226 | |||
227 | rule Do = pl::user(key("do") >> Body, [](const item_t& item) | ||
228 | { | ||
229 | State* st = reinterpret_cast<State*>(item.user_data); | ||
230 | return st->doStack.empty() || st->doStack.top(); | ||
231 | }); | ||
232 | |||
233 | rule DisableDo = pl::user(true_(), [](const item_t& item) | ||
234 | { | ||
235 | State* st = reinterpret_cast<State*>(item.user_data); | ||
236 | st->doStack.push(false); | ||
237 | return true; | ||
238 | }); | ||
239 | 149 | ||
240 | rule PopDo = pl::user(true_(), [](const item_t& item) | 150 | PopIndent = pl::user(true_(), [](const item_t& item) { |
241 | { | 151 | State* st = reinterpret_cast<State*>(item.user_data); |
242 | State* st = reinterpret_cast<State*>(item.user_data); | 152 | st->indents.pop(); |
243 | st->doStack.pop(); | 153 | return true; |
244 | return true; | 154 | }); |
245 | }); | ||
246 | 155 | ||
247 | extern rule CompInner; | 156 | InBlock = Advance >> Block >> PopIndent; |
248 | 157 | ||
249 | rule Comprehension = sym('[') >> Exp >> CompInner >> sym(']'); | 158 | local_flag = expr('*') | expr('^'); |
250 | rule comp_value = sym(',') >> Exp; | 159 | Local = key("local") >> ((Space >> local_flag) | NameList); |
251 | rule TblComprehension = sym('{') >> (Exp >> -comp_value) >> CompInner >> sym('}'); | ||
252 | 160 | ||
253 | extern rule CompForEach, CompFor, CompClause; | 161 | colon_import_name = sym('\\') >> Space >> Variable; |
162 | ImportName = colon_import_name | Space >> Variable; | ||
163 | ImportNameList = Seperator >> *SpaceBreak >> ImportName >> *((+SpaceBreak | sym(',') >> *SpaceBreak) >> ImportName); | ||
254 | 164 | ||
255 | rule CompInner = Seperator >> (CompForEach | CompFor) >> *CompClause; | 165 | import_literal_inner = (range('a', 'z') | range('A', 'Z') | set("_-")) >> *(AlphaNum | '-'); |
256 | rule star_exp = sym('*') >> Exp; | 166 | import_literal_chain = Seperator >> import_literal_inner >> *(expr('.') >> import_literal_inner); |
257 | rule CompForEach = key("for") >> AssignableNameList >> key("in") >> (star_exp | Exp); | 167 | ImportLiteral = sym('\'') >> import_literal_chain >> symx('\'') | sym('"') >> import_literal_chain >> symx('"'); |
258 | rule CompFor = key("for") >> Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; | ||
259 | rule CompClause = CompFor | CompForEach | key("when") >> Exp; | ||
260 | 168 | ||
261 | extern rule TableBlock; | 169 | ImportFrom = ImportNameList >> *SpaceBreak >> key("from") >> Exp; |
170 | ImportAs = ImportLiteral >> -(key("as") >> (Space >> Variable | TableLit)); | ||
262 | 171 | ||
263 | rule Assign = sym('=') >> Seperator >> (With | If | Switch | TableBlock | Exp >> *((sym(',') | sym(';')) >> Exp)); | 172 | Import = key("import") >> (ImportAs | ImportFrom); |
173 | BreakLoop = (expr("break") | expr("continue")) >> not_(AlphaNum); | ||
264 | 174 | ||
265 | rule update_op = | 175 | Return = key("return") >> -ExpListLow; |
266 | expr("..") | | 176 | WithExp = ExpList >> -Assign; |
267 | expr("+") | | ||
268 | expr("-") | | ||
269 | expr("*") | | ||
270 | expr("/") | | ||
271 | expr("%") | | ||
272 | expr("or") | | ||
273 | expr("and") | | ||
274 | expr("&") | | ||
275 | expr("|") | | ||
276 | expr(">>") | | ||
277 | expr("<<"); | ||
278 | 177 | ||
279 | rule Update = Space >> update_op >> expr("=") >> Exp; | 178 | With = key("with") >> DisableDo >> ensure(WithExp, PopDo) >> -key("do") >> Body; |
179 | SwitchCase = key("when") >> ExpList >> -key("then") >> Body; | ||
180 | SwitchElse = key("else") >> Body; | ||
280 | 181 | ||
281 | rule BinaryOperator = | 182 | SwitchBlock = *EmptyLine >> |
282 | (expr("or") >> not_(AlphaNum)) | | 183 | Advance >> Seperator >> |
283 | (expr("and") >> not_(AlphaNum)) | | 184 | SwitchCase >> |
284 | expr("<=") | | 185 | *(+SpaceBreak >> SwitchCase) >> |
285 | expr(">=") | | 186 | -(+SpaceBreak >> SwitchElse) >> |
286 | expr("~=") | | 187 | PopIndent; |
287 | expr("!=") | | ||
288 | expr("==") | | ||
289 | expr("..") | | ||
290 | expr("<<") | | ||
291 | expr(">>") | | ||
292 | expr("//") | | ||
293 | set("+-*/%^><|&"); | ||
294 | |||
295 | rule BackcallOperator = expr("|>"); | ||
296 | |||
297 | extern rule AssignableChain; | ||
298 | |||
299 | rule Assignable = AssignableChain | Space >> Variable | SelfName; | ||
300 | |||
301 | extern rule Value; | ||
302 | |||
303 | rule exp_op_value = Space >> (BackcallOperator | BinaryOperator) >> *SpaceBreak >> Value; | ||
304 | rule Exp = Value >> *exp_op_value; | ||
305 | 188 | ||
306 | extern rule Chain, Callable, InvokeArgs, existential_op; | 189 | Switch = key("switch") >> |
190 | DisableDo >> ensure(Exp, PopDo) >> | ||
191 | -key("do") >> -Space >> Break >> SwitchBlock; | ||
307 | 192 | ||
308 | rule ChainValue = Seperator >> (Chain | Callable) >> -existential_op >> -InvokeArgs; | 193 | IfCond = Exp >> -Assign; |
194 | IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> key("elseif") >> IfCond >> -key("then") >> Body; | ||
195 | IfElse = -(Break >> *EmptyLine >> CheckIndent) >> key("else") >> Body; | ||
196 | If = key("if") >> Seperator >> IfCond >> -key("then") >> Body >> *IfElseIf >> -IfElse; | ||
197 | Unless = key("unless") >> Seperator >> IfCond >> -key("then") >> Body >> *IfElseIf >> -IfElse; | ||
309 | 198 | ||
310 | extern rule KeyValue, String, SimpleValue; | 199 | While = key("while") >> DisableDo >> ensure(Exp, PopDo) >> -key("do") >> Body; |
311 | |||
312 | rule simple_table = Seperator >> KeyValue >> *(sym(',') >> KeyValue); | ||
313 | rule Value = SimpleValue | simple_table | ChainValue | String; | ||
314 | |||
315 | extern rule LuaString; | ||
316 | 200 | ||
317 | rule single_string_inner = expr("\\'") | "\\\\" | not_(expr('\'')) >> Any; | 201 | for_step_value = sym(',') >> Exp; |
318 | rule SingleString = symx('\'') >> *single_string_inner >> symx('\''); | 202 | for_args = Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; |
319 | rule interp = symx("#{") >> Exp >> sym('}'); | ||
320 | rule double_string_plain = expr("\\\"") | "\\\\" | not_(expr('"')) >> Any; | ||
321 | rule double_string_inner = +(not_(interp) >> double_string_plain); | ||
322 | rule double_string_content = double_string_inner | interp; | ||
323 | rule DoubleString = symx('"') >> Seperator >> *double_string_content >> symx('"'); | ||
324 | rule String = Space >> (DoubleString | SingleString | LuaString); | ||
325 | |||
326 | rule lua_string_open = '[' >> *expr('=') >> '['; | ||
327 | rule lua_string_close = ']' >> *expr('=') >> ']'; | ||
328 | |||
329 | rule LuaStringOpen = pl::user(lua_string_open, [](const item_t& item) | ||
330 | { | ||
331 | size_t count = std::distance(item.begin, item.end); | ||
332 | State* st = reinterpret_cast<State*>(item.user_data); | ||
333 | st->stringOpen = count; | ||
334 | return true; | ||
335 | }); | ||
336 | |||
337 | rule LuaStringClose = pl::user(lua_string_close, [](const item_t& item) | ||
338 | { | ||
339 | size_t count = std::distance(item.begin, item.end); | ||
340 | State* st = reinterpret_cast<State*>(item.user_data); | ||
341 | return st->stringOpen == count; | ||
342 | }); | ||
343 | 203 | ||
344 | rule LuaStringContent = *(not_(LuaStringClose) >> Any); | 204 | For = key("for") >> DisableDo >> |
205 | ensure(for_args, PopDo) >> | ||
206 | -key("do") >> Body; | ||
345 | 207 | ||
346 | rule LuaString = pl::user(LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose, [](const item_t& item) | 208 | for_in = star_exp | ExpList; |
347 | { | ||
348 | State* st = reinterpret_cast<State*>(item.user_data); | ||
349 | st->stringOpen = -1; | ||
350 | return true; | ||
351 | }); | ||
352 | |||
353 | rule Parens = sym('(') >> *SpaceBreak >> Exp >> *SpaceBreak >> sym(')'); | ||
354 | rule Callable = Space >> Variable | SelfName | VarArg | Parens; | ||
355 | rule FnArgsExpList = Exp >> *((Break | sym(',')) >> White >> Exp); | ||
356 | |||
357 | rule FnArgs = (symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym(')')) | | ||
358 | (sym('!') >> not_(expr('='))); | ||
359 | |||
360 | extern rule ChainItems, DotChainItem, ColonChain; | ||
361 | |||
362 | rule existential_op = expr('?'); | ||
363 | rule chain_call = (Callable | String) >> -existential_op >> ChainItems; | ||
364 | rule chain_item = and_(set(".\\")) >> ChainItems; | ||
365 | rule chain_dot_chain = DotChainItem >> -existential_op >> -ChainItems; | ||
366 | |||
367 | rule Chain = chain_call | chain_item | | ||
368 | Space >> (chain_dot_chain | ColonChain); | ||
369 | |||
370 | rule AssignableChain = Seperator >> Chain; | ||
371 | 209 | ||
372 | extern rule ChainItem; | 210 | ForEach = key("for") >> AssignableNameList >> key("in") >> |
211 | DisableDo >> ensure(for_in, PopDo) >> | ||
212 | -key("do") >> Body; | ||
373 | 213 | ||
374 | rule chain_with_colon = +ChainItem >> -ColonChain; | 214 | Do = pl::user(key("do") >> Body, [](const item_t& item) |
375 | rule ChainItems = chain_with_colon | ColonChain; | 215 | { |
216 | State* st = reinterpret_cast<State*>(item.user_data); | ||
217 | return st->doStack.empty() || st->doStack.top(); | ||
218 | }); | ||
376 | 219 | ||
377 | extern rule Invoke, Slice; | 220 | DisableDo = pl::user(true_(), [](const item_t& item) |
221 | { | ||
222 | State* st = reinterpret_cast<State*>(item.user_data); | ||
223 | st->doStack.push(false); | ||
224 | return true; | ||
225 | }); | ||
378 | 226 | ||
379 | rule Index = symx('[') >> Exp >> sym(']'); | 227 | PopDo = pl::user(true_(), [](const item_t& item) |
380 | rule ChainItem = Invoke >> -existential_op | DotChainItem >> -existential_op | Slice | Index >> -existential_op; | 228 | { |
381 | rule DotChainItem = symx('.') >> Name; | 229 | State* st = reinterpret_cast<State*>(item.user_data); |
382 | rule ColonChainItem = symx('\\') >> (LuaKeyword | Name); | 230 | st->doStack.pop(); |
383 | rule invoke_chain = Invoke >> -existential_op >> -ChainItems; | 231 | return true; |
384 | rule ColonChain = ColonChainItem >> -existential_op >> -invoke_chain; | 232 | }); |
233 | |||
234 | Comprehension = sym('[') >> Exp >> CompInner >> sym(']'); | ||
235 | comp_value = sym(',') >> Exp; | ||
236 | TblComprehension = sym('{') >> (Exp >> -comp_value) >> CompInner >> sym('}'); | ||
237 | |||
238 | CompInner = Seperator >> (CompForEach | CompFor) >> *CompClause; | ||
239 | star_exp = sym('*') >> Exp; | ||
240 | CompForEach = key("for") >> AssignableNameList >> key("in") >> (star_exp | Exp); | ||
241 | CompFor = key("for") >> Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; | ||
242 | CompClause = CompFor | CompForEach | key("when") >> Exp; | ||
243 | |||
244 | Assign = sym('=') >> Seperator >> (With | If | Switch | TableBlock | Exp >> *((sym(',') | sym(';')) >> Exp)); | ||
245 | |||
246 | update_op = | ||
247 | expr("..") | | ||
248 | expr("+") | | ||
249 | expr("-") | | ||
250 | expr("*") | | ||
251 | expr("/") | | ||
252 | expr("%") | | ||
253 | expr("or") | | ||
254 | expr("and") | | ||
255 | expr("&") | | ||
256 | expr("|") | | ||
257 | expr(">>") | | ||
258 | expr("<<"); | ||
259 | |||
260 | Update = Space >> update_op >> expr("=") >> Exp; | ||
261 | |||
262 | BinaryOperator = | ||
263 | (expr("or") >> not_(AlphaNum)) | | ||
264 | (expr("and") >> not_(AlphaNum)) | | ||
265 | expr("<=") | | ||
266 | expr(">=") | | ||
267 | expr("~=") | | ||
268 | expr("!=") | | ||
269 | expr("==") | | ||
270 | expr("..") | | ||
271 | expr("<<") | | ||
272 | expr(">>") | | ||
273 | expr("//") | | ||
274 | set("+-*/%^><|&"); | ||
275 | |||
276 | BackcallOperator = expr("|>"); | ||
277 | |||
278 | Assignable = AssignableChain | Space >> Variable | SelfName; | ||
279 | |||
280 | exp_op_value = Space >> (BackcallOperator | BinaryOperator) >> *SpaceBreak >> Value; | ||
281 | Exp = Value >> *exp_op_value; | ||
282 | |||
283 | ChainValue = Seperator >> (Chain | Callable) >> -existential_op >> -InvokeArgs; | ||
284 | |||
285 | simple_table = Seperator >> KeyValue >> *(sym(',') >> KeyValue); | ||
286 | Value = SimpleValue | simple_table | ChainValue | String; | ||
287 | |||
288 | single_string_inner = expr("\\'") | "\\\\" | not_(expr('\'')) >> Any; | ||
289 | SingleString = symx('\'') >> *single_string_inner >> symx('\''); | ||
290 | interp = symx("#{") >> Exp >> sym('}'); | ||
291 | double_string_plain = expr("\\\"") | "\\\\" | not_(expr('"')) >> Any; | ||
292 | double_string_inner = +(not_(interp) >> double_string_plain); | ||
293 | double_string_content = double_string_inner | interp; | ||
294 | DoubleString = symx('"') >> Seperator >> *double_string_content >> symx('"'); | ||
295 | String = Space >> (DoubleString | SingleString | LuaString); | ||
296 | |||
297 | lua_string_open = '[' >> *expr('=') >> '['; | ||
298 | lua_string_close = ']' >> *expr('=') >> ']'; | ||
299 | |||
300 | LuaStringOpen = pl::user(lua_string_open, [](const item_t& item) { | ||
301 | size_t count = std::distance(item.begin, item.end); | ||
302 | State* st = reinterpret_cast<State*>(item.user_data); | ||
303 | st->stringOpen = count; | ||
304 | return true; | ||
305 | }); | ||
385 | 306 | ||
386 | rule default_value = true_(); | 307 | LuaStringClose = pl::user(lua_string_close, [](const item_t& item) { |
387 | rule Slice = | 308 | size_t count = std::distance(item.begin, item.end); |
388 | symx('[') >> | 309 | State* st = reinterpret_cast<State*>(item.user_data); |
389 | (Exp | default_value) >> | 310 | return st->stringOpen == count; |
390 | sym(',') >> | 311 | }); |
391 | (Exp | default_value) >> | ||
392 | (sym(',') >> Exp | default_value) >> | ||
393 | sym(']'); | ||
394 | 312 | ||
395 | rule Invoke = Seperator >> ( | 313 | LuaStringContent = *(not_(LuaStringClose) >> Any); |
396 | FnArgs | | ||
397 | SingleString | | ||
398 | DoubleString | | ||
399 | and_(expr('[')) >> LuaString); | ||
400 | 314 | ||
401 | extern rule TableValueList, TableLitLine; | 315 | LuaString = pl::user(LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose, [](const item_t& item) { |
316 | State* st = reinterpret_cast<State*>(item.user_data); | ||
317 | st->stringOpen = -1; | ||
318 | return true; | ||
319 | }); | ||
402 | 320 | ||
403 | rule TableValue = KeyValue | Exp; | 321 | Parens = sym('(') >> *SpaceBreak >> Exp >> *SpaceBreak >> sym(')'); |
322 | Callable = Space >> Variable | SelfName | VarArg | Parens; | ||
323 | FnArgsExpList = Exp >> *((Break | sym(',')) >> White >> Exp); | ||
404 | 324 | ||
405 | rule table_lit_lines = SpaceBreak >> TableLitLine >> *(-sym(',') >> SpaceBreak >> TableLitLine) >> -sym(','); | 325 | FnArgs = (symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym(')')) | |
326 | (sym('!') >> not_(expr('='))); | ||
406 | 327 | ||
407 | rule TableLit = | 328 | existential_op = expr('?'); |
408 | sym('{') >> Seperator >> | 329 | chain_call = (Callable | String) >> -existential_op >> ChainItems; |
409 | -TableValueList >> | 330 | chain_item = and_(set(".\\")) >> ChainItems; |
410 | -sym(',') >> | 331 | chain_dot_chain = DotChainItem >> -existential_op >> -ChainItems; |
411 | -table_lit_lines >> | ||
412 | White >> sym('}'); | ||
413 | |||
414 | rule TableValueList = TableValue >> *(sym(',') >> TableValue); | ||
415 | |||
416 | rule TableLitLine = | ||
417 | ( | ||
418 | PushIndent >> (TableValueList >> PopIndent | PopIndent) | ||
419 | ) | ( | ||
420 | Space | ||
421 | ); | ||
422 | 332 | ||
423 | extern rule KeyValueLine; | 333 | Chain = chain_call | chain_item | |
334 | Space >> (chain_dot_chain | ColonChain); | ||
424 | 335 | ||
425 | rule TableBlockInner = Seperator >> KeyValueLine >> *(+(SpaceBreak) >> KeyValueLine); | 336 | AssignableChain = Seperator >> Chain; |
426 | rule TableBlock = +(SpaceBreak) >> Advance >> ensure(TableBlockInner, PopIndent); | ||
427 | 337 | ||
428 | extern rule Statement; | 338 | chain_with_colon = +ChainItem >> -ColonChain; |
429 | 339 | ChainItems = chain_with_colon | ColonChain; | |
430 | rule class_member_list = Seperator >> KeyValue >> *(sym(',') >> KeyValue); | ||
431 | rule ClassLine = CheckIndent >> (class_member_list | Statement) >> -sym(','); | ||
432 | rule ClassBlock = +(SpaceBreak) >> Advance >>Seperator >> ClassLine >> *(+(SpaceBreak) >> ClassLine) >> PopIndent; | ||
433 | 340 | ||
434 | rule ClassDecl = | 341 | Index = symx('[') >> Exp >> sym(']'); |
435 | key("class") >> not_(expr(':')) >> | 342 | ChainItem = Invoke >> -existential_op | DotChainItem >> -existential_op | Slice | Index >> -existential_op; |
436 | -Assignable >> | 343 | DotChainItem = symx('.') >> Name; |
437 | -(key("extends") >> PreventIndent >> ensure(Exp, PopIndent)) >> | 344 | ColonChainItem = symx('\\') >> (LuaKeyword | Name); |
438 | -ClassBlock; | 345 | invoke_chain = Invoke >> -existential_op >> -ChainItems; |
346 | ColonChain = ColonChainItem >> -existential_op >> -invoke_chain; | ||
439 | 347 | ||
440 | rule export_values = NameList >> -(sym('=') >> ExpListLow); | 348 | default_value = true_(); |
441 | rule export_op = expr('*') | expr('^'); | 349 | Slice = |
442 | rule Export = key("export") >> (ClassDecl | (Space >> export_op) | export_values); | 350 | symx('[') >> |
351 | (Exp | default_value) >> | ||
352 | sym(',') >> | ||
353 | (Exp | default_value) >> | ||
354 | (sym(',') >> Exp | default_value) >> | ||
355 | sym(']'); | ||
443 | 356 | ||
444 | rule variable_pair = sym(':') >> not_(SomeSpace) >> Space >> Variable; | 357 | Invoke = Seperator >> ( |
358 | FnArgs | | ||
359 | SingleString | | ||
360 | DoubleString | | ||
361 | and_(expr('[')) >> LuaString); | ||
445 | 362 | ||
446 | rule normal_pair = | 363 | TableValue = KeyValue | Exp; |
447 | ( | ||
448 | KeyName | | ||
449 | sym('[') >> Exp >> sym(']') | | ||
450 | Space >> DoubleString | | ||
451 | Space >> SingleString | ||
452 | ) >> | ||
453 | symx(':') >> | ||
454 | (Exp | TableBlock | +(SpaceBreak) >> Exp); | ||
455 | 364 | ||
456 | rule KeyValue = variable_pair | normal_pair; | 365 | table_lit_lines = SpaceBreak >> TableLitLine >> *(-sym(',') >> SpaceBreak >> TableLitLine) >> -sym(','); |
457 | 366 | ||
458 | rule KeyValueList = KeyValue >> *(sym(',') >> KeyValue); | 367 | TableLit = |
459 | rule KeyValueLine = CheckIndent >> KeyValueList >> -sym(','); | 368 | sym('{') >> Seperator >> |
369 | -TableValueList >> | ||
370 | -sym(',') >> | ||
371 | -table_lit_lines >> | ||
372 | White >> sym('}'); | ||
460 | 373 | ||
461 | rule FnArgDef = (Space >> Variable | SelfName) >> -(sym('=') >> Exp); | 374 | TableValueList = TableValue >> *(sym(',') >> TableValue); |
462 | 375 | ||
463 | rule FnArgDefList = Seperator >> | 376 | TableLitLine = ( |
464 | ( | 377 | PushIndent >> (TableValueList >> PopIndent | PopIndent) |
465 | ( | ||
466 | FnArgDef >> | ||
467 | *((sym(',') | Break) >> White >> FnArgDef) >> | ||
468 | -((sym(',') | Break) >> White >> VarArg) | ||
469 | ) | ( | 378 | ) | ( |
470 | VarArg | 379 | Space |
471 | ) | ||
472 | ); | ||
473 | |||
474 | rule outer_var_shadow = key("using") >> (NameList | Space >> expr("nil")); | ||
475 | |||
476 | rule FnArgsDef = sym('(') >> White >> -FnArgDefList >> -outer_var_shadow >> White >> sym(')'); | ||
477 | rule fn_arrow = expr("->") | expr("=>"); | ||
478 | rule FunLit = -FnArgsDef >> Space >> fn_arrow >> -Body; | ||
479 | |||
480 | rule NameList = Seperator >> Space >> Variable >> *(sym(',') >> Space >> Variable); | ||
481 | rule NameOrDestructure = Space >> Variable | TableLit; | ||
482 | rule AssignableNameList = Seperator >> NameOrDestructure >> *(sym(',') >> NameOrDestructure); | ||
483 | |||
484 | rule Backcall = -FnArgsDef >> Space >> symx("<-") >> Space >> ChainValue; | ||
485 | |||
486 | rule ExpList = Seperator >> Exp >> *(sym(',') >> Exp); | ||
487 | rule ExpListLow = Seperator >> Exp >> *((sym(',') | sym(';')) >> Exp); | ||
488 | |||
489 | rule ArgLine = CheckIndent >> Exp >> *(sym(',') >> Exp); | ||
490 | rule ArgBlock = ArgLine >> *(sym(',') >> SpaceBreak >> ArgLine) >> PopIndent; | ||
491 | |||
492 | rule invoke_args_with_table = | ||
493 | sym(',') >> | ||
494 | ( | ||
495 | TableBlock | | ||
496 | SpaceBreak >> Advance >> ArgBlock >> -TableBlock | ||
497 | ); | 380 | ); |
498 | 381 | ||
499 | rule InvokeArgs = | 382 | TableBlockInner = Seperator >> KeyValueLine >> *(+(SpaceBreak) >> KeyValueLine); |
500 | not_(expr('-')) >> Seperator >> | 383 | TableBlock = +(SpaceBreak) >> Advance >> ensure(TableBlockInner, PopIndent); |
501 | ( | 384 | |
502 | Exp >> *(sym(',') >> Exp) >> -(invoke_args_with_table | TableBlock) | | 385 | class_member_list = Seperator >> KeyValue >> *(sym(',') >> KeyValue); |
503 | TableBlock | 386 | ClassLine = CheckIndent >> (class_member_list | Statement) >> -sym(','); |
387 | ClassBlock = +(SpaceBreak) >> Advance >>Seperator >> ClassLine >> *(+(SpaceBreak) >> ClassLine) >> PopIndent; | ||
388 | |||
389 | ClassDecl = | ||
390 | key("class") >> not_(expr(':')) >> | ||
391 | -Assignable >> | ||
392 | -(key("extends") >> PreventIndent >> ensure(Exp, PopIndent)) >> | ||
393 | -ClassBlock; | ||
394 | |||
395 | export_values = NameList >> -(sym('=') >> ExpListLow); | ||
396 | export_op = expr('*') | expr('^'); | ||
397 | Export = key("export") >> (ClassDecl | (Space >> export_op) | export_values); | ||
398 | |||
399 | variable_pair = sym(':') >> not_(SomeSpace) >> Space >> Variable; | ||
400 | |||
401 | normal_pair = ( | ||
402 | KeyName | | ||
403 | sym('[') >> Exp >> sym(']') | | ||
404 | Space >> DoubleString | | ||
405 | Space >> SingleString | ||
406 | ) >> | ||
407 | symx(':') >> | ||
408 | (Exp | TableBlock | +(SpaceBreak) >> Exp); | ||
409 | |||
410 | KeyValue = variable_pair | normal_pair; | ||
411 | |||
412 | KeyValueList = KeyValue >> *(sym(',') >> KeyValue); | ||
413 | KeyValueLine = CheckIndent >> KeyValueList >> -sym(','); | ||
414 | |||
415 | FnArgDef = (Space >> Variable | SelfName) >> -(sym('=') >> Exp); | ||
416 | |||
417 | FnArgDefList = Seperator >> ( | ||
418 | ( | ||
419 | FnArgDef >> | ||
420 | *((sym(',') | Break) >> White >> FnArgDef) >> | ||
421 | -((sym(',') | Break) >> White >> VarArg) | ||
422 | ) | ( | ||
423 | VarArg | ||
424 | ) | ||
504 | ); | 425 | ); |
505 | 426 | ||
506 | rule const_value = (expr("nil") | expr("true") | expr("false")) >> not_(AlphaNum); | 427 | outer_var_shadow = key("using") >> (NameList | Space >> expr("nil")); |
507 | rule minus_exp = expr('-') >> not_(SomeSpace) >> Exp; | 428 | |
508 | rule sharp_exp = expr('#') >> Exp; | 429 | FnArgsDef = sym('(') >> White >> -FnArgDefList >> -outer_var_shadow >> White >> sym(')'); |
509 | rule tilde_exp = expr('~') >> Exp; | 430 | fn_arrow = expr("->") | expr("=>"); |
510 | rule not_exp = expr("not") >> not_(AlphaNum) >> Exp; | 431 | FunLit = -FnArgsDef >> Space >> fn_arrow >> -Body; |
511 | rule unary_exp = minus_exp | sharp_exp | tilde_exp | not_exp; | 432 | |
512 | 433 | NameList = Seperator >> Space >> Variable >> *(sym(',') >> Space >> Variable); | |
513 | rule SimpleValue = | 434 | NameOrDestructure = Space >> Variable | TableLit; |
514 | (Space >> const_value) | | 435 | AssignableNameList = Seperator >> NameOrDestructure >> *(sym(',') >> NameOrDestructure); |
515 | If | Unless | Switch | With | ClassDecl | ForEach | For | While | Do | | 436 | |
516 | (Space >> unary_exp) | | 437 | Backcall = -FnArgsDef >> Space >> symx("<-") >> Space >> ChainValue; |
517 | TblComprehension | TableLit | Comprehension | FunLit | | 438 | |
518 | (Space >> Num); | 439 | ExpList = Seperator >> Exp >> *(sym(',') >> Exp); |
519 | 440 | ExpListLow = Seperator >> Exp >> *((sym(',') | sym(';')) >> Exp); | |
520 | rule ExpListAssign = ExpList >> -(Update | Assign); | 441 | |
521 | 442 | ArgLine = CheckIndent >> Exp >> *(sym(',') >> Exp); | |
522 | rule if_else_line = key("if") >> Exp >> -Assign >> (key("else") >> Exp | default_value); | 443 | ArgBlock = ArgLine >> *(sym(',') >> SpaceBreak >> ArgLine) >> PopIndent; |
523 | rule unless_line = key("unless") >> Exp; | 444 | |
524 | 445 | invoke_args_with_table = | |
525 | rule statement_appendix = (if_else_line | unless_line | CompInner) >> Space; | 446 | sym(',') >> |
526 | rule Statement = | 447 | ( |
527 | ( | 448 | TableBlock | |
528 | Import | While | For | ForEach | | 449 | SpaceBreak >> Advance >> ArgBlock >> -TableBlock |
529 | Return | Local | Export | Space >> BreakLoop | | 450 | ); |
530 | Backcall | ExpListAssign | 451 | |
531 | ) >> Space >> | 452 | InvokeArgs = |
532 | -statement_appendix; | 453 | not_(expr('-')) >> Seperator >> |
533 | 454 | ( | |
534 | rule Body = -Space >> Break >> *EmptyLine >> InBlock | Statement; | 455 | Exp >> *(sym(',') >> Exp) >> -(invoke_args_with_table | TableBlock) | |
535 | 456 | TableBlock | |
536 | rule empty_line_stop = Space >> and_(Stop); | 457 | ); |
537 | rule Line = CheckIndent >> Statement | empty_line_stop; | 458 | |
538 | rule Block = Seperator >> Line >> *(+Break >> Line); | 459 | const_value = (expr("nil") | expr("true") | expr("false")) >> not_(AlphaNum); |
539 | 460 | minus_exp = expr('-') >> not_(SomeSpace) >> Exp; | |
540 | rule Shebang = expr("#!") >> *(not_(Stop) >> Any); | 461 | sharp_exp = expr('#') >> Exp; |
541 | rule File = White >> -Shebang >> Block >> eof(); | 462 | tilde_exp = expr('~') >> Exp; |
463 | not_exp = expr("not") >> not_(AlphaNum) >> Exp; | ||
464 | unary_exp = minus_exp | sharp_exp | tilde_exp | not_exp; | ||
465 | |||
466 | SimpleValue = | ||
467 | (Space >> const_value) | | ||
468 | If | Unless | Switch | With | ClassDecl | ForEach | For | While | Do | | ||
469 | (Space >> unary_exp) | | ||
470 | TblComprehension | TableLit | Comprehension | FunLit | | ||
471 | (Space >> Num); | ||
472 | |||
473 | ExpListAssign = ExpList >> -(Update | Assign); | ||
474 | |||
475 | if_else_line = key("if") >> Exp >> -Assign >> (key("else") >> Exp | default_value); | ||
476 | unless_line = key("unless") >> Exp; | ||
477 | |||
478 | statement_appendix = (if_else_line | unless_line | CompInner) >> Space; | ||
479 | Statement = ( | ||
480 | Import | While | For | ForEach | | ||
481 | Return | Local | Export | Space >> BreakLoop | | ||
482 | Backcall | ExpListAssign | ||
483 | ) >> Space >> | ||
484 | -statement_appendix; | ||
485 | |||
486 | Body = -Space >> Break >> *EmptyLine >> InBlock | Statement; | ||
487 | |||
488 | empty_line_stop = Space >> and_(Stop); | ||
489 | Line = CheckIndent >> Statement | empty_line_stop; | ||
490 | Block = Seperator >> Line >> *(+Break >> Line); | ||
491 | |||
492 | Shebang = expr("#!") >> *(not_(Stop) >> Any); | ||
493 | File = White >> -Shebang >> Block >> eof(); | ||
494 | } | ||
495 | |||
496 | ParseInfo MoonParser::parse(const std::string& codes, rule& r) { | ||
497 | ParseInfo res; | ||
498 | try { | ||
499 | res.input = std::make_unique<input>(); | ||
500 | *(res.input) = _converter.from_bytes(codes); | ||
501 | } catch (const std::range_error&) { | ||
502 | res.error = "Invalid text encoding."sv; | ||
503 | return res; | ||
504 | } | ||
505 | error_list errors; | ||
506 | try { | ||
507 | State state; | ||
508 | res.node.set(pl::parse(*(res.input), r, errors, &state)); | ||
509 | } catch (const std::logic_error& err) { | ||
510 | res.error = err.what(); | ||
511 | return res; | ||
512 | } | ||
513 | if (!errors.empty()) { | ||
514 | std::ostringstream buf; | ||
515 | for (error_list::iterator it = errors.begin(); it != errors.end(); ++it) { | ||
516 | const error& err = *it; | ||
517 | switch (err.m_type) { | ||
518 | case ERROR_TYPE::ERROR_SYNTAX_ERROR: | ||
519 | buf << res.errorMessage("Syntax error."sv, &err); | ||
520 | break; | ||
521 | case ERROR_TYPE::ERROR_INVALID_EOF: | ||
522 | buf << res.errorMessage("Invalid EOF."sv, &err); | ||
523 | break; | ||
524 | } | ||
525 | } | ||
526 | res.error = buf.str(); | ||
527 | } | ||
528 | return res; | ||
529 | } | ||
530 | |||
531 | std::string MoonParser::toString(ast_node* node) { | ||
532 | return _converter.to_bytes(std::wstring(node->m_begin.m_it, node->m_end.m_it)); | ||
533 | } | ||
534 | |||
535 | std::string MoonParser::toString(input::iterator begin, input::iterator end) { | ||
536 | return _converter.to_bytes(std::wstring(begin, end)); | ||
537 | } | ||
538 | |||
539 | input MoonParser::encode(std::string_view input) { | ||
540 | return _converter.from_bytes(std::string(input)); | ||
541 | } | ||
542 | |||
543 | std::string MoonParser::decode(const input& input) { | ||
544 | return _converter.to_bytes(input); | ||
545 | } | ||
546 | |||
547 | namespace Utils { | ||
548 | void replace(std::string& str, std::string_view from, std::string_view to) { | ||
549 | size_t start_pos = 0; | ||
550 | while((start_pos = str.find(from, start_pos)) != std::string::npos) { | ||
551 | str.replace(start_pos, from.size(), to); | ||
552 | start_pos += to.size(); | ||
553 | } | ||
554 | } | ||
555 | } | ||
556 | |||
557 | std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc) const { | ||
558 | const int ASCII = 255; | ||
559 | int length = loc->m_begin.m_line; | ||
560 | auto begin = input->begin(); | ||
561 | auto end = input->end(); | ||
562 | int count = 0; | ||
563 | for (auto it = input->begin(); it != input->end(); ++it) { | ||
564 | if (*it == '\n') { | ||
565 | if (count + 1 == length) { | ||
566 | end = it; | ||
567 | break; | ||
568 | } else { | ||
569 | begin = it + 1; | ||
570 | } | ||
571 | count++; | ||
572 | } | ||
573 | } | ||
574 | auto line = Converter{}.to_bytes(std::wstring(begin, end)); | ||
575 | int oldCol = loc->m_begin.m_col; | ||
576 | int col = std::max(0, oldCol - 1); | ||
577 | auto it = begin; | ||
578 | for (int i = 0; i < oldCol; ++i) { | ||
579 | if (*it > ASCII) { | ||
580 | ++col; | ||
581 | } | ||
582 | ++it; | ||
583 | } | ||
584 | Utils::replace(line, "\t"sv, " "sv); | ||
585 | std::ostringstream buf; | ||
586 | buf << loc->m_begin.m_line << ": "sv << msg << | ||
587 | '\n' << line << '\n' << std::string(col, ' ') << "^"sv; | ||
588 | return buf.str(); | ||
589 | } | ||
542 | 590 | ||
543 | } // namespace MoonP | 591 | } // namespace MoonP |