diff options
Diffstat (limited to '')
| -rw-r--r--[-rwxr-xr-x] | src/yuescript/yue_parser.cpp | 50 |
1 files changed, 30 insertions, 20 deletions
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 07fcd27..b134ee2 100755..100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
| @@ -71,6 +71,11 @@ YueParser::YueParser() { | |||
| 71 | Cut = false_(); | 71 | Cut = false_(); |
| 72 | Seperator = true_(); | 72 | Seperator = true_(); |
| 73 | 73 | ||
| 74 | invalid_empty_block = pl::user(true_(), [](const item_t& item) { | ||
| 75 | throw ParserError("must be followed by a statement or an indented block", *item.begin, *item.end); | ||
| 76 | return false; | ||
| 77 | }); | ||
| 78 | |||
| 74 | #define sym(str) (Space >> str) | 79 | #define sym(str) (Space >> str) |
| 75 | #define symx(str) expr(str) | 80 | #define symx(str) expr(str) |
| 76 | #define ensure(patt, finally) ((patt) >> (finally) | (finally) >> Cut) | 81 | #define ensure(patt, finally) ((patt) >> (finally) | (finally) >> Cut) |
| @@ -79,12 +84,13 @@ YueParser::YueParser() { | |||
| 79 | #define disable_chain(patt) (DisableChain >> ((patt) >> EnableChain | EnableChain >> Cut)) | 84 | #define disable_chain(patt) (DisableChain >> ((patt) >> EnableChain | EnableChain >> Cut)) |
| 80 | #define disable_do_chain_arg_table_block(patt) (DisableDoChainArgTableBlock >> ((patt) >> EnableDoChainArgTableBlock | EnableDoChainArgTableBlock >> Cut)) | 85 | #define disable_do_chain_arg_table_block(patt) (DisableDoChainArgTableBlock >> ((patt) >> EnableDoChainArgTableBlock | EnableDoChainArgTableBlock >> Cut)) |
| 81 | #define disable_arg_table_block(patt) (DisableArgTableBlock >> ((patt) >> EnableArgTableBlock | EnableArgTableBlock >> Cut)) | 86 | #define disable_arg_table_block(patt) (DisableArgTableBlock >> ((patt) >> EnableArgTableBlock | EnableArgTableBlock >> Cut)) |
| 82 | #define plain_body_with(str) (-(Space >> key(str)) >> InBlock | Space >> key(str) >> Space >> Statement) | 87 | #define body_with(str) (Space >> (key(str) >> Space >> (InBlock | Statement) | InBlock | invalid_empty_block)) |
| 83 | #define plain_body (InBlock | Space >> Statement) | 88 | #define opt_body_with(str) (Space >> (key(str) >> Space >> (InBlock | Statement) | InBlock)) |
| 89 | #define body (Space >> (InBlock | Statement | invalid_empty_block)) | ||
| 84 | 90 | ||
| 85 | Variable = pl::user(Name, [](const item_t& item) { | 91 | Variable = pl::user(Name, [](const item_t& item) { |
| 86 | State* st = reinterpret_cast<State*>(item.user_data); | 92 | State* st = reinterpret_cast<State*>(item.user_data); |
| 87 | for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast<char>(*it); | 93 | for (auto it = item.begin->m_it; it != item.end->m_it; ++it) st->buffer += static_cast<char>(*it); |
| 88 | auto isValid = Keywords.find(st->buffer) == Keywords.end(); | 94 | auto isValid = Keywords.find(st->buffer) == Keywords.end(); |
| 89 | if (isValid) { | 95 | if (isValid) { |
| 90 | if (st->buffer == st->moduleName) { | 96 | if (st->buffer == st->moduleName) { |
| @@ -98,7 +104,7 @@ YueParser::YueParser() { | |||
| 98 | 104 | ||
| 99 | LabelName = pl::user(Name, [](const item_t& item) { | 105 | LabelName = pl::user(Name, [](const item_t& item) { |
| 100 | State* st = reinterpret_cast<State*>(item.user_data); | 106 | State* st = reinterpret_cast<State*>(item.user_data); |
| 101 | for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast<char>(*it); | 107 | for (auto it = item.begin->m_it; it != item.end->m_it; ++it) st->buffer += static_cast<char>(*it); |
| 102 | auto isValid = LuaKeywords.find(st->buffer) == LuaKeywords.end(); | 108 | auto isValid = LuaKeywords.find(st->buffer) == LuaKeywords.end(); |
| 103 | st->buffer.clear(); | 109 | st->buffer.clear(); |
| 104 | return isValid; | 110 | return isValid; |
| @@ -106,7 +112,7 @@ YueParser::YueParser() { | |||
| 106 | 112 | ||
| 107 | LuaKeyword = pl::user(Name, [](const item_t& item) { | 113 | LuaKeyword = pl::user(Name, [](const item_t& item) { |
| 108 | State* st = reinterpret_cast<State*>(item.user_data); | 114 | State* st = reinterpret_cast<State*>(item.user_data); |
| 109 | for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast<char>(*it); | 115 | for (auto it = item.begin->m_it; it != item.end->m_it; ++it) st->buffer += static_cast<char>(*it); |
| 110 | auto it = LuaKeywords.find(st->buffer); | 116 | auto it = LuaKeywords.find(st->buffer); |
| 111 | st->buffer.clear(); | 117 | st->buffer.clear(); |
| 112 | return it != LuaKeywords.end(); | 118 | return it != LuaKeywords.end(); |
| @@ -123,7 +129,7 @@ YueParser::YueParser() { | |||
| 123 | 129 | ||
| 124 | check_indent = pl::user(Indent, [](const item_t& item) { | 130 | check_indent = pl::user(Indent, [](const item_t& item) { |
| 125 | int indent = 0; | 131 | int indent = 0; |
| 126 | for (input_it i = item.begin; i != item.end; ++i) { | 132 | for (input_it i = item.begin->m_it; i != item.end->m_it; ++i) { |
| 127 | switch (*i) { | 133 | switch (*i) { |
| 128 | case ' ': indent++; break; | 134 | case ' ': indent++; break; |
| 129 | case '\t': indent += 4; break; | 135 | case '\t': indent += 4; break; |
| @@ -136,7 +142,7 @@ YueParser::YueParser() { | |||
| 136 | 142 | ||
| 137 | advance = pl::user(Indent, [](const item_t& item) { | 143 | advance = pl::user(Indent, [](const item_t& item) { |
| 138 | int indent = 0; | 144 | int indent = 0; |
| 139 | for (input_it i = item.begin; i != item.end; ++i) { | 145 | for (input_it i = item.begin->m_it; i != item.end->m_it; ++i) { |
| 140 | switch (*i) { | 146 | switch (*i) { |
| 141 | case ' ': indent++; break; | 147 | case ' ': indent++; break; |
| 142 | case '\t': indent += 4; break; | 148 | case '\t': indent += 4; break; |
| @@ -154,7 +160,7 @@ YueParser::YueParser() { | |||
| 154 | 160 | ||
| 155 | push_indent = pl::user(Indent, [](const item_t& item) { | 161 | push_indent = pl::user(Indent, [](const item_t& item) { |
| 156 | int indent = 0; | 162 | int indent = 0; |
| 157 | for (input_it i = item.begin; i != item.end; ++i) { | 163 | for (input_it i = item.begin->m_it; i != item.end->m_it; ++i) { |
| 158 | switch (*i) { | 164 | switch (*i) { |
| 159 | case ' ': indent++; break; | 165 | case ' ': indent++; break; |
| 160 | case '\t': indent += 4; break; | 166 | case '\t': indent += 4; break; |
| @@ -232,9 +238,9 @@ YueParser::YueParser() { | |||
| 232 | 238 | ||
| 233 | WithExp = ExpList >> -Assign; | 239 | WithExp = ExpList >> -Assign; |
| 234 | 240 | ||
| 235 | With = Space >> key("with") >> -existential_op >> disable_do_chain_arg_table_block(WithExp) >> plain_body_with("do"); | 241 | With = Space >> key("with") >> -existential_op >> disable_do_chain_arg_table_block(WithExp) >> body_with("do"); |
| 236 | SwitchCase = Space >> key("when") >> disable_chain(disable_arg_table_block(SwitchList)) >> plain_body_with("then"); | 242 | SwitchCase = Space >> key("when") >> disable_chain(disable_arg_table_block(SwitchList)) >> body_with("then"); |
| 237 | SwitchElse = Space >> key("else") >> plain_body; | 243 | SwitchElse = Space >> key("else") >> body; |
| 238 | 244 | ||
| 239 | SwitchBlock = *EmptyLine >> | 245 | SwitchBlock = *EmptyLine >> |
| 240 | Advance >> Seperator >> | 246 | Advance >> Seperator >> |
| @@ -251,24 +257,24 @@ YueParser::YueParser() { | |||
| 251 | 257 | ||
| 252 | assignment = ExpList >> Assign; | 258 | assignment = ExpList >> Assign; |
| 253 | IfCond = disable_chain(disable_arg_table_block(assignment | Exp)); | 259 | IfCond = disable_chain(disable_arg_table_block(assignment | Exp)); |
| 254 | IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("elseif") >> IfCond >> plain_body_with("then"); | 260 | IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("elseif") >> IfCond >> body_with("then"); |
| 255 | IfElse = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("else") >> plain_body; | 261 | IfElse = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("else") >> body; |
| 256 | IfType = (expr("if") | expr("unless")) >> not_(AlphaNum); | 262 | IfType = (expr("if") | expr("unless")) >> not_(AlphaNum); |
| 257 | If = Space >> IfType >> IfCond >> plain_body_with("then") >> *IfElseIf >> -IfElse; | 263 | If = Space >> IfType >> IfCond >> opt_body_with("then") >> *IfElseIf >> -IfElse; |
| 258 | 264 | ||
| 259 | WhileType = (expr("while") | expr("until")) >> not_(AlphaNum); | 265 | WhileType = (expr("while") | expr("until")) >> not_(AlphaNum); |
| 260 | While = WhileType >> disable_do_chain_arg_table_block(Exp) >> plain_body_with("do"); | 266 | While = WhileType >> disable_do_chain_arg_table_block(Exp) >> opt_body_with("do"); |
| 261 | Repeat = key("repeat") >> Body >> Break >> *EmptyLine >> CheckIndent >> Space >> key("until") >> Exp; | 267 | Repeat = key("repeat") >> Body >> Break >> *EmptyLine >> CheckIndent >> Space >> key("until") >> Exp; |
| 262 | 268 | ||
| 263 | for_step_value = sym(',') >> Exp; | 269 | for_step_value = sym(',') >> Exp; |
| 264 | for_args = Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; | 270 | for_args = Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; |
| 265 | 271 | ||
| 266 | For = key("for") >> disable_do_chain_arg_table_block(for_args) >> plain_body_with("do"); | 272 | For = key("for") >> disable_do_chain_arg_table_block(for_args) >> opt_body_with("do"); |
| 267 | 273 | ||
| 268 | for_in = star_exp | ExpList; | 274 | for_in = star_exp | ExpList; |
| 269 | 275 | ||
| 270 | ForEach = key("for") >> AssignableNameList >> Space >> key("in") >> | 276 | ForEach = key("for") >> AssignableNameList >> Space >> key("in") >> |
| 271 | disable_do_chain_arg_table_block(for_in) >> plain_body_with("do"); | 277 | disable_do_chain_arg_table_block(for_in) >> opt_body_with("do"); |
| 272 | 278 | ||
| 273 | Do = pl::user(Space >> key("do"), [](const item_t& item) { | 279 | Do = pl::user(Space >> key("do"), [](const item_t& item) { |
| 274 | State* st = reinterpret_cast<State*>(item.user_data); | 280 | State* st = reinterpret_cast<State*>(item.user_data); |
| @@ -413,14 +419,14 @@ YueParser::YueParser() { | |||
| 413 | lua_string_close = ']' >> *expr('=') >> ']'; | 419 | lua_string_close = ']' >> *expr('=') >> ']'; |
| 414 | 420 | ||
| 415 | LuaStringOpen = pl::user(lua_string_open, [](const item_t& item) { | 421 | LuaStringOpen = pl::user(lua_string_open, [](const item_t& item) { |
| 416 | size_t count = std::distance(item.begin, item.end); | 422 | size_t count = std::distance(item.begin->m_it, item.end->m_it); |
| 417 | State* st = reinterpret_cast<State*>(item.user_data); | 423 | State* st = reinterpret_cast<State*>(item.user_data); |
| 418 | st->stringOpen = count; | 424 | st->stringOpen = count; |
| 419 | return true; | 425 | return true; |
| 420 | }); | 426 | }); |
| 421 | 427 | ||
| 422 | LuaStringClose = pl::user(lua_string_close, [](const item_t& item) { | 428 | LuaStringClose = pl::user(lua_string_close, [](const item_t& item) { |
| 423 | size_t count = std::distance(item.begin, item.end); | 429 | size_t count = std::distance(item.begin->m_it, item.end->m_it); |
| 424 | State* st = reinterpret_cast<State*>(item.user_data); | 430 | State* st = reinterpret_cast<State*>(item.user_data); |
| 425 | return st->stringOpen == count; | 431 | return st->stringOpen == count; |
| 426 | }); | 432 | }); |
| @@ -655,7 +661,8 @@ YueParser::YueParser() { | |||
| 655 | Import | While | Repeat | For | ForEach | | 661 | Import | While | Repeat | For | ForEach | |
| 656 | Return | Local | Global | Export | Macro | | 662 | Return | Local | Global | Export | Macro | |
| 657 | MacroInPlace | BreakLoop | Label | Goto | ShortTabAppending | | 663 | MacroInPlace | BreakLoop | Label | Goto | ShortTabAppending | |
| 658 | LocalAttrib | Backcall | PipeBody | ExpListAssign | 664 | LocalAttrib | Backcall | PipeBody | ExpListAssign | |
| 665 | statement_appendix >> invalid_empty_block | ||
| 659 | ) >> Space >> | 666 | ) >> Space >> |
| 660 | -statement_appendix >> -statement_sep; | 667 | -statement_appendix >> -statement_sep; |
| 661 | 668 | ||
| @@ -699,6 +706,9 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) { | |||
| 699 | res.exportDefault = state.exportDefault; | 706 | res.exportDefault = state.exportDefault; |
| 700 | res.exportMacro = state.exportMacro; | 707 | res.exportMacro = state.exportMacro; |
| 701 | } | 708 | } |
| 709 | } catch (const ParserError& err) { | ||
| 710 | res.error = res.errorMessage(err.what(), &err.loc); | ||
| 711 | return res; | ||
| 702 | } catch (const std::logic_error& err) { | 712 | } catch (const std::logic_error& err) { |
| 703 | res.error = err.what(); | 713 | res.error = err.what(); |
| 704 | return res; | 714 | return res; |
