diff options
Diffstat (limited to 'src/yuescript/yue_parser.cpp')
-rw-r--r-- | src/yuescript/yue_parser.cpp | 63 |
1 files changed, 35 insertions, 28 deletions
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index d8fdc28..f215ee4 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
@@ -30,6 +30,17 @@ std::unordered_set<std::string> Keywords = { | |||
30 | "try"s, "unless"s, "using"s, "when"s, "with"s // Yue keywords | 30 | "try"s, "unless"s, "using"s, "when"s, "with"s // Yue keywords |
31 | }; | 31 | }; |
32 | 32 | ||
33 | class ParserError : public std::logic_error { | ||
34 | public: | ||
35 | explicit ParserError(std::string_view msg, const pos* begin) | ||
36 | : std::logic_error(std::string(msg)) | ||
37 | , line(begin->m_line) | ||
38 | , col(begin->m_col) { } | ||
39 | |||
40 | int line; | ||
41 | int col; | ||
42 | }; | ||
43 | |||
33 | // clang-format off | 44 | // clang-format off |
34 | YueParser::YueParser() { | 45 | YueParser::YueParser() { |
35 | plain_space = *set(" \t"); | 46 | plain_space = *set(" \t"); |
@@ -78,7 +89,7 @@ YueParser::YueParser() { | |||
78 | Seperator = true_(); | 89 | Seperator = true_(); |
79 | 90 | ||
80 | empty_block_error = pl::user(true_(), [](const item_t& item) { | 91 | empty_block_error = pl::user(true_(), [](const item_t& item) { |
81 | throw ParserError("must be followed by a statement or an indented block", *item.begin, *item.end); | 92 | throw ParserError("must be followed by a statement or an indented block"sv, item.begin); |
82 | return false; | 93 | return false; |
83 | }); | 94 | }); |
84 | 95 | ||
@@ -489,7 +500,7 @@ YueParser::YueParser() { | |||
489 | st->expLevel++; | 500 | st->expLevel++; |
490 | const int max_exp_level = 100; | 501 | const int max_exp_level = 100; |
491 | if (st->expLevel > max_exp_level) { | 502 | if (st->expLevel > max_exp_level) { |
492 | throw ParserError("nesting expressions exceeds 100 levels", *item.begin, *item.end); | 503 | throw ParserError("nesting expressions exceeds 100 levels"sv, item.begin); |
493 | } | 504 | } |
494 | return true; | 505 | return true; |
495 | }); | 506 | }); |
@@ -658,10 +669,10 @@ YueParser::YueParser() { | |||
658 | }) >> (pl::user(space >> ExportDefault >> space >> Exp, [](const item_t& item) { | 669 | }) >> (pl::user(space >> ExportDefault >> space >> Exp, [](const item_t& item) { |
659 | State* st = reinterpret_cast<State*>(item.user_data); | 670 | State* st = reinterpret_cast<State*>(item.user_data); |
660 | if (st->exportDefault) { | 671 | if (st->exportDefault) { |
661 | throw ParserError("export default has already been declared", *item.begin, *item.end); | 672 | throw ParserError("export default has already been declared"sv, item.begin); |
662 | } | 673 | } |
663 | if (st->exportCount > 1) { | 674 | if (st->exportCount > 1) { |
664 | throw ParserError("there are items already being exported", *item.begin, *item.end); | 675 | throw ParserError("there are items already being exported"sv, item.begin); |
665 | } | 676 | } |
666 | st->exportDefault = true; | 677 | st->exportDefault = true; |
667 | return true; | 678 | return true; |
@@ -669,7 +680,7 @@ YueParser::YueParser() { | |||
669 | | (not_(space >> ExportDefault) >> pl::user(true_(), [](const item_t& item) { | 680 | | (not_(space >> ExportDefault) >> pl::user(true_(), [](const item_t& item) { |
670 | State* st = reinterpret_cast<State*>(item.user_data); | 681 | State* st = reinterpret_cast<State*>(item.user_data); |
671 | if (st->exportDefault && st->exportCount > 1) { | 682 | if (st->exportDefault && st->exportCount > 1) { |
672 | throw ParserError("can not export any more items when 'export default' is declared", *item.begin, *item.end); | 683 | throw ParserError("can not export any more items when 'export default' is declared"sv, item.begin); |
673 | } | 684 | } |
674 | return true; | 685 | return true; |
675 | }) >> space >> ExpList >> -(space >> Assign)) | 686 | }) >> space >> ExpList >> -(space >> Assign)) |
@@ -762,7 +773,7 @@ YueParser::YueParser() { | |||
762 | ) | arg_table_block; | 773 | ) | arg_table_block; |
763 | 774 | ||
764 | leading_spaces_error = pl::user(+space_one >> '(' >> space >> Exp >> +(space >> ',' >> space >> Exp) >> space >> ')', [](const item_t& item) { | 775 | leading_spaces_error = pl::user(+space_one >> '(' >> space >> Exp >> +(space >> ',' >> space >> Exp) >> space >> ')', [](const item_t& item) { |
765 | throw ParserError("write invoke arguments in parentheses without leading spaces or just leading spaces without parentheses", *item.begin, *item.end); | 776 | throw ParserError("write invoke arguments in parentheses without leading spaces or just leading spaces without parentheses"sv, item.begin); |
766 | return false; | 777 | return false; |
767 | }); | 778 | }); |
768 | 779 | ||
@@ -776,12 +787,12 @@ YueParser::YueParser() { | |||
776 | ConstValue = (expr("nil") | "true" | "false") >> not_alpha_num; | 787 | ConstValue = (expr("nil") | "true" | "false") >> not_alpha_num; |
777 | 788 | ||
778 | braces_expression_error = pl::user(true_(), [](const item_t& item) { | 789 | braces_expression_error = pl::user(true_(), [](const item_t& item) { |
779 | throw ParserError("syntax error in brace expression", *item.begin, *item.end); | 790 | throw ParserError("syntax error in brace expression"sv, item.begin); |
780 | return false; | 791 | return false; |
781 | }); | 792 | }); |
782 | 793 | ||
783 | brackets_expression_error = pl::user(true_(), [](const item_t& item) { | 794 | brackets_expression_error = pl::user(true_(), [](const item_t& item) { |
784 | throw ParserError("syntax error in bracket expression", *item.begin, *item.end); | 795 | throw ParserError("syntax error in bracket expression"sv, item.begin); |
785 | return false; | 796 | return false; |
786 | }); | 797 | }); |
787 | 798 | ||
@@ -846,7 +857,7 @@ YueParser::YueParser() { | |||
846 | ) >> and_(line_break); | 857 | ) >> and_(line_break); |
847 | 858 | ||
848 | indentation_error = pl::user(not_(pipe_operator | eof()), [](const item_t& item) { | 859 | indentation_error = pl::user(not_(pipe_operator | eof()), [](const item_t& item) { |
849 | throw ParserError("unexpected indent", *item.begin, *item.end); | 860 | throw ParserError("unexpected indent"sv, item.begin); |
850 | return false; | 861 | return false; |
851 | }); | 862 | }); |
852 | 863 | ||
@@ -875,7 +886,7 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) { | |||
875 | res.codes = std::make_unique<input>(); | 886 | res.codes = std::make_unique<input>(); |
876 | } | 887 | } |
877 | } catch (const std::range_error&) { | 888 | } catch (const std::range_error&) { |
878 | res.error = "invalid text encoding"sv; | 889 | res.error = {"invalid text encoding"s, 1, 1}; |
879 | return res; | 890 | return res; |
880 | } | 891 | } |
881 | error_list errors; | 892 | error_list errors; |
@@ -888,26 +899,22 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) { | |||
888 | res.exportMacro = state.exportMacro; | 899 | res.exportMacro = state.exportMacro; |
889 | } | 900 | } |
890 | } catch (const ParserError& err) { | 901 | } catch (const ParserError& err) { |
891 | res.error = res.errorMessage(err.what(), &err.loc); | 902 | res.error = {err.what(), err.line, err.col}; |
892 | return res; | 903 | return res; |
893 | } catch (const std::logic_error& err) { | 904 | } catch (const std::logic_error& err) { |
894 | res.error = err.what(); | 905 | res.error = {err.what(), 1, 1}; |
895 | return res; | 906 | return res; |
896 | } | 907 | } |
897 | if (!errors.empty()) { | 908 | if (!errors.empty()) { |
898 | std::ostringstream buf; | 909 | const error& err = errors.front(); |
899 | for (error_list::iterator it = errors.begin(); it != errors.end(); ++it) { | 910 | switch (err.m_type) { |
900 | const error& err = *it; | 911 | case ERROR_TYPE::ERROR_SYNTAX_ERROR: |
901 | switch (err.m_type) { | 912 | res.error = {"syntax error"s, err.m_begin.m_line, err.m_begin.m_col}; |
902 | case ERROR_TYPE::ERROR_SYNTAX_ERROR: | 913 | break; |
903 | buf << res.errorMessage("syntax error"sv, &err); | 914 | case ERROR_TYPE::ERROR_INVALID_EOF: |
904 | break; | 915 | res.error = {"invalid EOF"s, err.m_begin.m_line, err.m_begin.m_col}; |
905 | case ERROR_TYPE::ERROR_INVALID_EOF: | 916 | break; |
906 | buf << res.errorMessage("invalid EOF"sv, &err); | ||
907 | break; | ||
908 | } | ||
909 | } | 917 | } |
910 | res.error = buf.str(); | ||
911 | } | 918 | } |
912 | return res; | 919 | return res; |
913 | } | 920 | } |
@@ -944,9 +951,9 @@ void trim(std::string& str) { | |||
944 | } | 951 | } |
945 | } // namespace Utils | 952 | } // namespace Utils |
946 | 953 | ||
947 | std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc) const { | 954 | std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol) const { |
948 | const int ASCII = 255; | 955 | const int ASCII = 255; |
949 | int length = loc->m_begin.m_line; | 956 | int length = errLine; |
950 | auto begin = codes->begin(); | 957 | auto begin = codes->begin(); |
951 | auto end = codes->end(); | 958 | auto end = codes->end(); |
952 | int count = 0; | 959 | int count = 0; |
@@ -961,7 +968,7 @@ std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc | |||
961 | count++; | 968 | count++; |
962 | } | 969 | } |
963 | } | 970 | } |
964 | int oldCol = loc->m_begin.m_col; | 971 | int oldCol = errCol; |
965 | int col = std::max(0, oldCol - 1); | 972 | int col = std::max(0, oldCol - 1); |
966 | auto it = begin; | 973 | auto it = begin; |
967 | for (int i = 0; i < oldCol && it != end; ++i) { | 974 | for (int i = 0; i < oldCol && it != end; ++i) { |
@@ -977,7 +984,7 @@ std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc | |||
977 | } | 984 | } |
978 | Utils::replace(line, "\t"sv, " "sv); | 985 | Utils::replace(line, "\t"sv, " "sv); |
979 | std::ostringstream buf; | 986 | std::ostringstream buf; |
980 | buf << loc->m_begin.m_line << ": "sv << msg << '\n' | 987 | buf << errLine << ": "sv << msg << '\n' |
981 | << line << '\n' | 988 | << line << '\n' |
982 | << std::string(col, ' ') << "^"sv; | 989 | << std::string(col, ' ') << "^"sv; |
983 | return buf.str(); | 990 | return buf.str(); |