diff options
| author | Li Jin <dragon-fly@qq.com> | 2020-01-30 16:06:32 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2020-01-30 16:06:32 +0800 |
| commit | c62d9eb35a310e7663234526ce4b9fe3519ca7cf (patch) | |
| tree | 56b4b418aadab90989e3e29e29e8ab7e04806e8d /src/MoonP/moon_parser.cpp | |
| parent | 240b1ec4a49128c00a787e6d0928865995b1d02e (diff) | |
| download | yuescript-c62d9eb35a310e7663234526ce4b9fe3519ca7cf.tar.gz yuescript-c62d9eb35a310e7663234526ce4b9fe3519ca7cf.tar.bz2 yuescript-c62d9eb35a310e7663234526ce4b9fe3519ca7cf.zip | |
Separate MoonParser from MoonCompiler, make moonc compile multiple file in threads.
Diffstat (limited to '')
| -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 |
