diff --git a/CMakeLists.txt b/CMakeLists.txt index a8cd4e4..1af6ae0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ execute_process(COMMAND configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/version.cc.in" "${CMAKE_CURRENT_BINARY_DIR}/src/version.cc" @ONLY) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20 -O0 -Werror") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20 -Werror") set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR}/.install/) @@ -36,5 +36,11 @@ set(INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include) include_directories(${INCLUDE_DIR}) + +SET(FUNC_IMPL ${CMAKE_SOURCE_DIR}/src/parse_function/function_impl.cc) +SET(FUNC_DEF ${CMAKE_SOURCE_DIR}/include/parse_function/function.h) +SET(FUNC_KIND_DEF ${CMAKE_SOURCE_DIR}/include/parse_function/kinds.def) +SET(FUNC_DIAG_DEF ${CMAKE_SOURCE_DIR}/include/diag/kinds_parse.def) + add_subdirectory(src) add_subdirectory(tests) diff --git a/gram/config.py b/gram/config.py index baedf1c..29cc4e1 100644 --- a/gram/config.py +++ b/gram/config.py @@ -185,6 +185,19 @@ "`false`":"kw_false", "`true`":"kw_true", "`nullptr`":"kw_nullptr", + "`binary-literal`":"binary_literal", + "`floating-point-literal`":"floating_point_literal", + "`character-literal`":"char_literal", + "`string-literal`":"string_literal", + "`integer-literal`":"integer_literal", + "`decimal-literal`":"decimal_literal", + "`octal-literal`":"octal_literal", + "`hexadecimal-literal`":"hexadecimal_literal", + "`raw-string`":"raw_string", + "`user-defined-character-literal`":"user_defined_char_literal", + "`user-defined-string-literal`":"user_defined_string_literal", + "`user-defined-floating-point-literal`":"user_defined_floating_point_literal", + "`user-defined-integer-literal`":"user_defined_integer_literal", } gram_tree = {} @@ -654,7 +667,7 @@ gram_tree["static_assert-declaration"] = [ ["`static_assert`", "`(`", "constant-expression", "`)`", "`;`"], - ["`static_assert`", "`(`", "constant-expression", "`,`", "string-literal", "`)`", "`;`"] + ["`static_assert`", "`(`", "constant-expression", "`,`", "`string-literal`", "`)`", "`;`"] ] gram_tree["empty-declaration"] = [ @@ -1056,16 +1069,16 @@ ] gram_tree["asm-declaration"] = [ - "attribute-specifier-seq[opt]", "`asm`", "`(`", "string-literal", "`)`", "`;`", + "attribute-specifier-seq[opt]", "`asm`", "`(`", "`string-literal`", "`)`", "`;`", ] gram_tree["linkage-specification"] = [ - ["`extern`", "string-literal", "`{`", "declaration-seq[opt]", "`}`"], - ["`extern`", "string-literal", "declaration"], + ["`extern`", "`string-literal`", "`{`", "declaration-seq[opt]", "`}`"], + ["`extern`", "`string-literal`", "declaration"], ] gram_tree["attribute-specifier-seq"] = [ - "attribute-specifier", "attribute-specifier-seq[opt]", + "attribute-specifier", "attribute-specifier-seq[opt]", ] gram_tree["attribute-specifier"] = [ @@ -1310,8 +1323,8 @@ ] gram_tree["literal-operator-id"] = [ - ["`operator`", "string-literal", "`identifier`"], - ["`operator`", "user-defined-string-literal"], + ["`operator`", "`string-literal`", "`identifier`"], + ["`operator`", "`user-defined-string-literal`"], ] gram_tree["template-declaration"] = [ @@ -1562,7 +1575,7 @@ ] gram_tree["header-name-tokens"] = [ - ["string-literal"], + ["`string-literal`"], ["`<`", "h-pp-tokens", "`>`"], ] @@ -1605,10 +1618,10 @@ ["`export`"], ["`identifier`"], ["pp-number"], - ["character-literal"], - ["user-defined-character-literal"], - ["string-literal"], - ["user-defined-string-literal"], + ["`character-literal`"], + ["`user-defined-character-literal`"], + ["`string-literal`"], + ["`user-defined-string-literal`"], ["preprocessing-op-or-punc"], # each non-whitespace character that cannot be one of the above ] @@ -1698,43 +1711,19 @@ ] gram_tree["literal"] = [ - ["integer-literal"], - ["character-literal"], - ["floating-point-literal"], - ["string-literal"], + ["`integer-literal`"], + ["`binary-literal`"], + ["`octal-literal`"], + ["`decimal-literal`"], + ["`hexadecimal-literal`"], + ["`character-literal`"], + ["`floating-point-literal`"], + ["`string-literal`"], ["boolean-literal"], ["pointer-literal"], ["user-defined-literal"], ] -gram_tree["integer-literal"] = [ - ["binary-literal", "integer-suffix[opt]"], - ["octal-literal", "integer-suffix[opt]"], - ["decimal-literal", "integer-suffix[opt]"], - ["hexadecimal-literal", "integer-suffix[opt]"], -] - -gram_tree["binary-literal"] = [ - ["`0b`", "binary-digit"], - ["`0B`", "`binary-digit`"], - ["binary-literal", "`'`"], - ["binary-literal", "`'`[opt]", "binary-digit"], -] - -gram_tree["octal-literal"] = [ - ["`0`"], - ["octal-literal", "`'`[opt]", "octal-digit"], -] - -gram_tree["decimal-literal"] = [ - ["nonzero-digit"], - ["decimal-literal", "`'`[opt]", "digit"], -] - -gram_tree["hexadecimal-literal"] = [ - "hexadecimal-prefix", "hexadecimal-digit-sequence", -] - gram_tree["binary-digit"] = [ ["`0`"], ["`1`"], @@ -1810,10 +1799,6 @@ ["`ll`"], ["`LL`"], ] -gram_tree["character-literal"] = [ - "encoding-prefix[opt]", "`'`","c-char-sequence", "`'`", -] - gram_tree["encoding-prefix"] = [ ["`u8`"],["`u`"], ["`U`"], ["`L`"], ] @@ -1851,11 +1836,6 @@ ["hexadecimal-escape-sequence", "hexadecimal-digit"], ] -gram_tree["floating-point-literal"] = [ - ["decimal-floating-point-literal"], - ["hexadecimal-floating-point-literal"], -] - gram_tree["decimal-floating-point-literal"] = [ ["fractional-constant", "exponent-part[opt]", "floating-point-suffix[opt]"], ["digit-sequence", "exponent-part[opt]", "floating-point-suffix[opt]"], @@ -1899,11 +1879,6 @@ ["`f`"], ["`l`"], ["`F`"], ["`L`"], ] -gram_tree["string-literal"] = [ - ["encoding-prefix[opt]", '`"`', "s-char-sequence[opt]", '`"`'], - ["encoding-prefix[opt]", '`R`', "raw-string"], -] - gram_tree["s-char-sequence"] = [ ["s-char"], ["s-char-sequence", "s-char"], @@ -1915,9 +1890,6 @@ ["universal-character-name"], ] -gram_tree["raw-string"] = [ - '`"`', "d-char-sequence[opt]", "`(`", "r-char-sequence[opt]" ,"`)`", "d-char-sequence[opt]", '`"`', -] gram_tree["r-char-sequence"] = [ ["r-char"], @@ -1950,33 +1922,12 @@ ] gram_tree["user-defined-literal"] = [ - ["user-defined-integer-literal"], - ["user-defined-floating-point-literal"], - ["user-defined-string-literal"], - ["user-defined-character-literal"], -] - -gram_tree["user-defined-integer-literal"] = [ - ["decimal-literal", "ud-suffix"], - ["octal-literal", "ud-suffix"], - ["hexadecimal-literal", "ud-suffix"], - ["binary-literal", "ud-suffix"], -] - -gram_tree["user-defined-floating-point-literal"] = [ - ["fractional-constant", "exponent-part[opt]", "ud-suffix"], - ["digit-sequence", "exponent-part", "ud-suffix"], - ["hexadecimal-prefix", "hexadecimal-fractional-constant", "binary-exponent-part", "ud-suffix"], - ["hexadecimal-prefix", "hexadecimal-digit-sequence", "binary-exponent-part", "ud-suffix"], + ["`user-defined-integer-literal`"], + ["`user-defined-floating-point-literal`"], + ["`user-defined-string-literal`"], + ["`user-defined-character-literal`"], ] -gram_tree["user-defined-string-literal"] = [ - "string-literal", "ud-suffix", -] - -gram_tree["user-defined-character-literal"] = [ - "character-literal", "ud-suffix", -] gram_tree["ud-suffix"] = [ "`identifier`", diff --git a/gram/create_parse_functions.py b/gram/create_parse_functions.py index d3d670f..9753c39 100644 --- a/gram/create_parse_functions.py +++ b/gram/create_parse_functions.py @@ -42,8 +42,8 @@ def create_serial_parse_function(serial_idx, key, v, tag_name="TagName"): tag_name = f""" {name}::kTag """ content_init = "" - content_type = f"using parse_func_type = SerialParseFunctions<" - content_func_def = f"""SerialParseFunctions serial_funcs( + content_type = f"using parse_func_type = SerialParseFunctions;"} {content_func_def}); static_assert(base::kNumberOfElements == 1); serial_funcs.executed_mask( decltype(serial_funcs)::base::bitset_type(this->executed_mask_.value() ) ); output = serial_funcs(); - this->executed_mask(base::bitset_type(serial_funcs.executed_mask().value())); + this->executed_mask_.set(serial_funcs.executed_mask().value()); return output; """ if not flg: @@ -97,12 +98,12 @@ def create_serial_parse_function(serial_idx, key, v, tag_name="TagName"): return content_op, content_init, content_type + ">;", "", comments -def create_serial_in_parallel_function(s_v, k, flg, tidx): +def create_serial_in_parallel_function(s_v, k, flg, idx_str, tidx): name = camel_case(k) tag_name = f""" {name}::kTag """ assert isinstance(s_v, list) - contents_type = f"SerialParseFunctions<" - contents = f"""SerialParseFunctions(ParseFunctionInputs( + contents_type = f"SerialParseFunctions" + contents contents_type += ">," contents += ")," return contents, contents_type, flg -def create_parallel_function_normal(v, k, idx, offset, out_name="output"): +def create_parallel_function_normal(v, k, idx, offset, out_name="output", type_recursive=False): name = camel_case(k) tag_name = f""" {name}::kTag """ - contents_type = f"""ParallelParseFunctions<{len(v)}, """ + contents_type = f"""ParallelParseFunctions " + content_op = f""" static_assert(base::kNumberOfElements >= {len(v)}); using parallel_funcs_bitset_map = decltype(parallel_funcs_{idx})::base::bitset_type; - parallel_funcs_{idx}.executed_mask( parallel_funcs_bitset_map(base::bitset_type::range<{offset}, {offset + len(v)}>(this->executed_mask_.value({offset})) )); + parallel_funcs_{idx}.executed_mask( parallel_funcs_bitset_map(this->executed_mask_.value({offset})) ); {out_name} = parallel_funcs_{idx}(); - this->executed_mask(base::bitset_type(parallel_funcs_{idx}.executed_mask().value() ,{offset})); + this->executed_mask_.set(parallel_funcs_{idx}.executed_mask().value() ,{offset}); """ + if type_recursive: + content_op = f"""{out_name} = recursive_funcs_{idx}();""" content_init = "" return content_op, content_init, contents_type, content_func_def, flg @@ -182,7 +195,8 @@ def create_parallel_function(serial_idx, key, v): if not flg_has_recursive: non_recursive_eles.append(s_v) else: - recursive_eles.append(s_v) + assert (len(s_v) > 1) + recursive_eles.append(s_v[1:]) assert (len(non_recursive_eles) > 0) @@ -205,7 +219,7 @@ def create_parallel_function(serial_idx, key, v): content_non_op = f"unreachable({tag_name});return output;" return content_non_op, "", "", "", flg content_r_op, content_r_init, content_r_type, content_r_func_def, flg = create_parallel_function_normal( - recursive_eles, k, 1, len(non_recursive_eles)) + recursive_eles, k, 1, len(non_recursive_eles), "output", True) if not flg: content_r_op = f"unreachable({tag_name});return output;" return content_r_op, "", "", "", flg @@ -222,10 +236,25 @@ def create_parallel_function(serial_idx, key, v): """ + "\n}\n" + f""" diag::infos() << basic::str::from({tag_name}, "into recursive. \\n"); {content_r_type} {content_r_func_def} - {content_r_op}""" + """ - if(!output.work_){ + {content_r_op}""" + f""" + if(!output.work_){{ return non_recursive_output; - } + }} +const auto* p_start = &context_->token_lists().at(start_token); + const auto* p_end = &context_->token_lists().at(output.cur_token_); + Line line{{ + p_start, + p_end, + this->kind(), + token::details::TokenKind::unknown, + token::TokenLists::len(p_start, p_end), + this->calling_depth(), + Line::segments_type() + }}; + line.segments_.append(non_recursive_output.line_); + line.segments_.append(output.line_); + output.line_ = context_->paint(line); + return output; """ @@ -284,8 +313,34 @@ def write_to_file(src_file_name, the_contents, title, end="}"): all_content_out_path = args[0] all_header_content_out_path = args[1] all_header_kind_content_out_path = args[2] - if len(args) > 3: - all_single_src_out_path = args[3] + all_header_diag_def_out_path = args[3] + if len(args) > 4: + all_single_src_out_path = args[4] + + diag_def_title = """/* +* MIT License +* Copyright (c) 2023 mxlol233 (mxlol233@outlook.com) + +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: + +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. + +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +*LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +*/ + +""" kind_def_title = """/* * MIT License @@ -353,15 +408,18 @@ class NAME : public ParseFunction { \\ public: \\ constexpr static basic::mem::TraceTag::tag_type kTag = #NAME; \\ using base = ParseFunction< N>; \\ - constexpr static ParseFunctionKind kind = ParseFunctionKind::TYPE; \\ + ParseFunctionKind kind() override{\\ + constexpr static ParseFunctionKind kKind = ParseFunctionKind::TYPE; \\ + return kKind;\\ + }\\ ~NAME() = default; \\ template \\ - explicit NAME(bool opt, Params... params) : base(opt, params...) {} \\ + explicit NAME(Context* context, bool opt, Params... params) : base(context, #NAME,opt, params...) {} \\ template \\ - explicit NAME(Params... params) : base(params...) {} \\ - explicit NAME(const ParseFunctionInputs& param) \\ - : base(param) {} \\ - ParseFunctionOutputs operator()() override; \\ + explicit NAME(Context* context,Params... params) : base(context,#NAME,params...) {} \\ + explicit NAME(Context* context,const ParseFunctionInputs& param) \\ + : base(context,#NAME,param) {} \\ + ParseFunctionOutputs operator()() ; \\ }; ___CONTENT_DEF___ @@ -397,6 +455,7 @@ class NAME : public ParseFunction { \\ #include "diag.h" #include "parse_function/function.h" #include "parse_function/parallel_function_impl.h" +#include "parse_function/recursive_function_impl.h" #include "parse_function/serial_function_impl.h" #include "token.h" @@ -410,12 +469,13 @@ class NAME : public ParseFunction { \\ define_tmplate = """ ___CONTENT_COM___ - inline ParseFunctionOutputs ___NAME___::operator()() + ParseFunctionOutputs ___NAME___::operator()() { auto output = base::operator()(); if (!this->valid()) { return output; } + auto start_token = output.cur_token_; ___CONTENT_OP___ } """ @@ -477,7 +537,7 @@ class NAME : public ParseFunction { \\ header_content_defs += f"""ParseFunctionDef({camel_case(k)},k{camel_case(k)}, {num_ele});""" header_content_types += f""" PARSE_FUNC(k{camel_case(k)}) """ - if len(args) > 3: + if len(args) > 4: src_file_name = f"""{all_single_src_out_path}/{k.replace("-","_")}.cc""" write_to_file(src_file_name, the_contents, title) header_contents = header_contents_template.replace( @@ -485,12 +545,16 @@ class NAME : public ParseFunction { \\ write_to_file(f"{all_content_out_path}", all_contents, title) write_to_file(f"{all_header_content_out_path}", header_contents, header_title) + + diag_def_contents = "" + for k, v in diag_kinds.items(): + z = f"""DIAG({k}, "expected {v[0]} in {v[1]}.", "", + Level::kError) + """ + diag_def_contents += z + + write_to_file(f"{all_header_diag_def_out_path}", "\n" + + diag_def_contents, diag_def_title, "\n") + write_to_file(f"{all_header_kind_content_out_path}", "\n" + header_content_types, kind_def_title, "\n#undef PARSE_FUNC") - -# with open(f"{os.path.dirname(__file__)}/../.build/t.def", "w") as f: -# for k, v in diag_kinds.items(): -# z = f"""DIAG({k}, "expected {v[0]} in {v[1]}.", "", -# Level::kError) -# """ -# f.write(z) diff --git a/include/ast.h b/include/ast.h index 53cc541..3cb1ae1 100644 --- a/include/ast.h +++ b/include/ast.h @@ -22,4 +22,97 @@ */ #pragma once -namespace lsp::ast {} +#include +#include "basic/map.h" +#include "basic/vec.h" +#include "token.h" + +namespace lps::parser::details { + +enum class ParseFunctionKind : uint16_t { + kUnknown = 0, + kExpectedToken = 1, +#define PARSE_FUNC(FUNC) FUNC, +#include "parse_function/kinds.def" + kNum, +}; + +namespace kind { + +static constexpr std::array, + static_cast(ParseFunctionKind::kNum)> + kLists = {{ +#define PARSE_FUNC(X) {ParseFunctionKind::X, #X}, +#include "parse_function/kinds.def" + }}; + +static constexpr lps::basic::map::Map( + ParseFunctionKind::kNum)> + kMap{kLists}; + +} // namespace kind + +inline std::ostream& operator<<(std::ostream& s, ParseFunctionKind kind) { + s << kind::kMap.at(kind); + return s; +} + +struct Line { + using segments_type = basic::Vector<2, const Line*>; + Line() = default; + Line(const token::Token* start, const token::Token* end, + ParseFunctionKind kind, token::details::TokenKind token_kind, size_t len, + size_t calling_depth, segments_type&& segments) + : start_(start), + end_(end), + kind_(kind), + token_kind_(token_kind), + len_(len), + calling_depth_(calling_depth), + segments_(std::move(segments)) {} + const token::Token* start_{nullptr}; + const token::Token* end_{nullptr}; + ParseFunctionKind kind_{ParseFunctionKind::kUnknown}; + token::details::TokenKind token_kind_{token::details::TokenKind::unknown}; + size_t len_{0}; + size_t calling_depth_{0}; + segments_type segments_; +}; + +inline bool operator==(const Line& a, const Line& b) { + return a.start_ == b.start_ && a.end_ == b.end_ && a.kind_ == b.kind_ && + a.token_kind_ == b.token_kind_ && a.len_ == b.len_ && + a.calling_depth_ == b.calling_depth_ && a.segments_ == b.segments_; +} + +class Tree { + public: + struct Node { + using sub_nodes_type = std::vector; + sub_nodes_type children_; + const token::Token* start_{nullptr}; + const token::Token* end_{nullptr}; + ParseFunctionKind kind_{ParseFunctionKind::kUnknown}; + token::details::TokenKind token_kind_{token::details::TokenKind::unknown}; + size_t len_{0}; + explicit Node() = default; + Node(const Line* line) + : start_(line->start_), + end_(line->end_), + kind_(line->kind_), + token_kind_(line->token_kind_), + len_(line->len_) { + for (const auto* p : line->segments_) { + children_.push_back(Node(p)); + } + } + }; + explicit Tree(const Line* line) : root_(Node(line)) {} + const Node& root() { return root_; } + + private: + Node root_; +}; + +} // namespace lps::parser::details diff --git a/include/basic/bitset.h b/include/basic/bitset.h index d84df15..96169bb 100644 --- a/include/basic/bitset.h +++ b/include/basic/bitset.h @@ -23,62 +23,77 @@ #pragma once -#include #include -#include #include "basic/exception.h" #include "basic/mem.h" -#include "basic/vec.h" namespace lps::basic { -template +template class Bitset { public: + using ele_type = bool; + using bitset = std::array; constexpr static mem::TraceTag::tag_type kTag = "Bitset"; template - static std::bitset range(std::bitset b) { + static std::array range(const bitset& b) { static_assert(R <= L && L <= N, "Not valid."); - b >>= R; - b <<= (N - L + R); - b >>= (N - L); - return b; + std::array new_b; + size_t idx = 0; + for (int i = R; i < L; i++) { + new_b[idx++] = b[i]; + } + return new_b; } - static std::bitset range(std::bitset b, std::size_t R, std::size_t L) { + static bitset range(const bitset& b, std::size_t R, std::size_t L) { lps_assert(kTag, R <= L && L <= N); - b >>= R; - b <<= (N - L + R); - b >>= (N - L); - return b; + bitset new_b; + size_t idx = 0; + for (int i = R; i < L; i++) { + new_b[idx++] = b[i]; + } + return new_b; } static constexpr size_t kN = N; - Bitset() : len_(N) { value_.reset(); } + + explicit Bitset() { reset(); } + template - explicit Bitset(const std::array& other, size_t start_idx = 0) + explicit Bitset(const std::array& other, size_t start_idx = 0) : start_idx_(start_idx) { - size_t m = std::min(N, N1); - for (size_t i = start_idx; i < m; i++) { - value_[i] = other[i]; - } - len_ = m; + set(other, start_idx); } template - explicit Bitset(const std::bitset& other, size_t start_idx = 0) - : start_idx_(start_idx) { + void set(const std::array& other, size_t start_idx = 0) { + start_idx_ = start_idx; size_t m = std::min(N, N1); if (start_idx > 0) { lps_assert(kTag, N1 < N); - value_ = value_.to_ullong() || (other.to_ullong() << start_idx); + for (int i = 0; i < N1; i++) { + value_[start_idx + i] = other[i]; + } } else { - value_ = other.to_ullong(); + + for (int i = 0; i < m; i++) { + value_[i] = other[i]; + } } len_ = m; + lps_assert(kTag, len_ + start_idx_ <= N); } - void reset() { value_ = value(start_idx_).reset().to_ullong(); } - void set() { value_ = value(start_idx_).set().to_ullong(); } + void reset() { + for (int i = start_idx_; i < start_idx_ + len_; i++) { + value_[i] = false; + } + } + void set() { + for (int i = start_idx_; i < start_idx_ + len_; i++) { + value_[i] = true; + } + } void set(size_t pos) { lps_assert(kTag, (pos + start_idx_) < len_); value_[pos + start_idx_] = true; @@ -87,73 +102,29 @@ class Bitset { lps_assert(kTag, (pos + start_idx_) < len_); return value_[pos + start_idx_]; } - std::bitset value(size_t start_idx = 0) { - return std::bitset( - range(value_, start_idx, start_idx + len_).to_ullong()); - } - - template - std::bitset value(size_t start_idx = 0) { - return std::bitset( - range(value_, start_idx, start_idx + len_).to_ullong()); + bitset value(size_t start_idx = 0) { + if (start_idx == 0) { + return range(value_, 0, len_); + } + auto a = range(value_, start_idx, len_); + return a; } - bool all() { - return range(value_, start_idx_, start_idx_ + len_).count() == len_; + [[nodiscard]] bool all() const { + size_t cnt = 0; + for (int i = start_idx_; i < start_idx_ + len_; i++) { + if (value_[i]) { + cnt++; + } + } + return cnt == len_; } [[nodiscard]] size_t start_idx() const { return start_idx_; } private: - std::bitset value_; - size_t len_{0}; + bitset value_; + size_t len_{N}; size_t start_idx_{0}; }; -template -class Bitset (8 * sizeof(unsigned long long))), - bool>::type> { - public: - constexpr static mem::TraceTag::tag_type kTag = "Bitset"; - static constexpr size_t kN = N; - Bitset() : len_(N) { LPS_ERROR(kTag, "Unsupport yet."); } - template - explicit Bitset(const std::array& other, size_t start_idx = 0) { - constexpr size_t kM = std::min(N, N1); - for (size_t i = start_idx; i < kM; i++) { - value_[i] = other[i]; - } - len_ = kM; - } - template - explicit Bitset(const std::bitset& other, size_t start_idx = 0) { - static_assert(N1 < N, "not valid size"); - for (size_t i = start_idx; i < N1; i++) { - value_[i] = other[i]; - } - len_ = N1; - } - void reset() { value_.fill(false); } - void set() { value_.fill(true); } - void set(size_t pos) { - lps_assert(kTag, pos < len_); - value_[pos] = true; - } - bool at(size_t pos) { - lps_assert(kTag, pos < len_); - return value_[pos]; - } - std::array value(size_t start_idx = 0) { - lps_assert(kTag, start_idx == 0); - return value_; - } - bool all() { - lps_assert(kTag, len_ <= N); - return std::ranges::all_of(value_.begin(), value_.begin() + len_, - [](bool a) { return a; }); - } - - private: - basic::Vector value_; - size_t len_{0}; -}; } // namespace lps::basic diff --git a/include/basic/vec.h b/include/basic/vec.h index 2da4f9f..e2069f8 100644 --- a/include/basic/vec.h +++ b/include/basic/vec.h @@ -32,8 +32,7 @@ #include "basic/mem.h" template -using SizeType = - std::conditional_t= 8, uint64_t, uint32_t>; +using SizeType = std::conditional_t= 8, uint64_t, uint32_t>; namespace lps::basic::vec::details { @@ -270,6 +269,12 @@ class Vector : public vec::details::Impl { SET(); } + Vector(size_t N_hat, const ele_type& val) : base_type("Vector") { + for (size_t i = 0; i < N_hat; i++) { + this->append(val); + } + } + explicit Vector(const Vector& v) : base_type(v.tag_) { for (const T& a : v) { this->append(a); @@ -290,6 +295,30 @@ class Vector : public vec::details::Impl { return *this; } + bool operator==(const Vector& v) const { + if (this->size() != v.size()) { + return false; + } + for (size_t i = 0; i < this->size_; ++i) { + if (this->first_[i] != v.first_[i]) { + return false; + } + } + return true; + } + + bool operator!=(const Vector& v) const { + if (this->size() != v.size()) { + return true; + } + for (size_t i = 0; i < this->size_; ++i) { + if (this->first_[i] != v.first_[i]) { + return true; + } + } + return false; + } + #undef SET explicit Vector(const T (&d)[N]) : base_type(d) {} Vector& operator=(const T (&d)[N]) { diff --git a/include/diag/.gitignore b/include/diag/.gitignore new file mode 100644 index 0000000..0326cbc --- /dev/null +++ b/include/diag/.gitignore @@ -0,0 +1 @@ +kinds_parse.def diff --git a/include/diag/kinds_lex.def b/include/diag/kinds_lex.def index 7e8da73..49fa78e 100644 --- a/include/diag/kinds_lex.def +++ b/include/diag/kinds_lex.def @@ -71,3 +71,9 @@ DIAG(expected_r_paren_in_the_define_with_parameters, "expected `)`.", "", Level::kError) DIAG(expected_vertws_after_slash_in_preprocessing, "expected `\\n` after `\\`.", "", Level::kError) +DIAG(expected_directive_command_after_hash, + "expected directive command after `#`.", "", Level::kError) +DIAG(expected_constant_expression_after_if_directive, + "expected `constant-expression` after `#if`.", "", Level::kError) +DIAG(expected_new_line_after_if_constant_expression_directive, + "expected `\\n` after `#if constant-expression`.", "", Level::kError) diff --git a/include/diag/kinds_parse.def b/include/diag/kinds_parse.def deleted file mode 100644 index 04b2206..0000000 --- a/include/diag/kinds_parse.def +++ /dev/null @@ -1,1089 +0,0 @@ -/* -* MIT License -* Copyright (c) 2023 mxlol233 (mxlol233@outlook.com) - -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: - -* The above copyright notice and this permission notice shall be included in all -* copies or substantial portions of the Software. - -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -*LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -*/ - -DIAG(primary_expression_expect_kw_this, - "expected `this` in primary_expression.", "", Level::kError) -DIAG(primary_expression_expect_l_paren, "expected `(` in primary_expression.", - "", Level::kError) -DIAG(primary_expression_expect_r_paren, "expected `)` in primary_expression.", - "", Level::kError) -DIAG(unqualified_id_expect_identifier, - "expected `identifier` in unqualified_id.", "", Level::kError) -DIAG(unqualified_id_expect_tilde, "expected `~` in unqualified_id.", "", - Level::kError) -DIAG(qualified_id_expect_kw_template, "expected `template` in qualified_id.", - "", Level::kError) -DIAG(nested_name_specifier_expect_coloncolon, - "expected `::` in nested_name_specifier.", "", Level::kError) -DIAG(nested_name_specifier_expect_identifier, - "expected `identifier` in nested_name_specifier.", "", Level::kError) -DIAG(nested_name_specifier_expect_kw_template, - "expected `template` in nested_name_specifier.", "", Level::kError) -DIAG(lambda_expression_expect_less, "expected `<` in lambda_expression.", "", - Level::kError) -DIAG(lambda_expression_expect_greater, "expected `>` in lambda_expression.", "", - Level::kError) -DIAG(lambda_introducer_expect_l_square, "expected `[` in lambda_introducer.", - "", Level::kError) -DIAG(lambda_introducer_expect_r_square, "expected `]` in lambda_introducer.", - "", Level::kError) -DIAG(lambda_declarator_expect_l_paren, "expected `(` in lambda_declarator.", "", - Level::kError) -DIAG(lambda_declarator_expect_r_paren, "expected `)` in lambda_declarator.", "", - Level::kError) -DIAG(lambda_capture_expect_comma, "expected `,` in lambda_capture.", "", - Level::kError) -DIAG(capture_default_expect_amp, "expected `&` in capture_default.", "", - Level::kError) -DIAG(capture_default_expect_equal, "expected `=` in capture_default.", "", - Level::kError) -DIAG(capture_list_expect_comma, "expected `,` in capture_list.", "", - Level::kError) -DIAG(simple_capture_expect_identifier, - "expected `identifier` in simple_capture.", "", Level::kError) -DIAG(simple_capture_expect_ellipsis, "expected `...` in simple_capture.", "", - Level::kError) -DIAG(simple_capture_expect_amp, "expected `&` in simple_capture.", "", - Level::kError) -DIAG(simple_capture_expect_kw_this, "expected `this` in simple_capture.", "", - Level::kError) -DIAG(simple_capture_expect_star, "expected `*` in simple_capture.", "", - Level::kError) -DIAG(init_capture_expect_ellipsis, "expected `...` in init_capture.", "", - Level::kError) -DIAG(init_capture_expect_identifier, "expected `identifier` in init_capture.", - "", Level::kError) -DIAG(init_capture_expect_amp, "expected `&` in init_capture.", "", - Level::kError) -DIAG(fold_expression_expect_l_paren, "expected `(` in fold_expression.", "", - Level::kError) -DIAG(fold_expression_expect_ellipsis, "expected `...` in fold_expression.", "", - Level::kError) -DIAG(fold_expression_expect_r_paren, "expected `)` in fold_expression.", "", - Level::kError) -DIAG(fold_operator_expect_plus, "expected `+` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_minus, "expected `-` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_star, "expected `*` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_slash, "expected `/` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_percent, "expected `%` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_caret, "expected `^` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_amp, "expected `&` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_pipe, "expected `|` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_lessless, "expected `<<` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_greatergreater, "expected `>>` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_plusequal, "expected `+=` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_minusequal, "expected `-=` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_starequal, "expected `*=` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_slashequal, "expected `/=` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_percentequal, "expected `%=` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_caretequal, "expected `^=` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_ampequal, "expected `&=` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_pipeequal, "expected `|=` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_lesslessequal, "expected `<<=` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_greatergreaterequal, - "expected `>>=` in fold_operator.", "", Level::kError) -DIAG(fold_operator_expect_equal, "expected `=` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_equalequal, "expected `==` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_exclaimequal, "expected `!=` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_less, "expected `<` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_greater, "expected `>` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_lessequal, "expected `<=` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_greaterequal, "expected `>=` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_ampamp, "expected `&&` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_pipepipe, "expected `||` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_comma, "expected `,` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_periodstar, "expected `.*` in fold_operator.", "", - Level::kError) -DIAG(fold_operator_expect_arrowstar, "expected `->*` in fold_operator.", "", - Level::kError) -DIAG(requires_expression_expect_kw_requires, - "expected `requires` in requires_expression.", "", Level::kError) -DIAG(requirement_parameter_list_expect_l_paren, - "expected `(` in requirement_parameter_list.", "", Level::kError) -DIAG(requirement_parameter_list_expect_r_paren, - "expected `)` in requirement_parameter_list.", "", Level::kError) -DIAG(requirement_body_expect_l_brace, "expected `{` in requirement_body.", "", - Level::kError) -DIAG(requirement_body_expect_r_brace, "expected `}` in requirement_body.", "", - Level::kError) -DIAG(simple_requirement_expect_semi, "expected `;` in simple_requirement.", "", - Level::kError) -DIAG(type_requirement_expect_kw_typename, - "expected `typename` in type_requirement.", "", Level::kError) -DIAG(type_requirement_expect_semi, "expected `;` in type_requirement.", "", - Level::kError) -DIAG(compound_requirement_expect_l_brace, - "expected `{` in compound_requirement.", "", Level::kError) -DIAG(compound_requirement_expect_r_brace, - "expected `}` in compound_requirement.", "", Level::kError) -DIAG(compound_requirement_expect_kw_noexcept, - "expected `noexcept` in compound_requirement.", "", Level::kError) -DIAG(compound_requirement_expect_semi, "expected `;` in compound_requirement.", - "", Level::kError) -DIAG(return_type_requirement_expect_arrow, - "expected `->` in return_type_requirement.", "", Level::kError) -DIAG(nested_requirement_expect_kw_requires, - "expected `requires` in nested_requirement.", "", Level::kError) -DIAG(nested_requirement_expect_semi, "expected `;` in nested_requirement.", "", - Level::kError) -DIAG(postfix_expression_expect_l_square, "expected `[` in postfix_expression.", - "", Level::kError) -DIAG(postfix_expression_expect_r_square, "expected `]` in postfix_expression.", - "", Level::kError) -DIAG(postfix_expression_expect_l_paren, "expected `(` in postfix_expression.", - "", Level::kError) -DIAG(postfix_expression_expect_r_paren, "expected `)` in postfix_expression.", - "", Level::kError) -DIAG(postfix_expression_expect_period, "expected `.` in postfix_expression.", - "", Level::kError) -DIAG(postfix_expression_expect_kw_template, - "expected `template` in postfix_expression.", "", Level::kError) -DIAG(postfix_expression_expect_arrow, "expected `->` in postfix_expression.", - "", Level::kError) -DIAG(postfix_expression_expect_plusplus, "expected `++` in postfix_expression.", - "", Level::kError) -DIAG(postfix_expression_expect_minusminus, - "expected `--` in postfix_expression.", "", Level::kError) -DIAG(postfix_expression_expect_kw_dynamic_cast, - "expected `dynamic_cast` in postfix_expression.", "", Level::kError) -DIAG(postfix_expression_expect_less, "expected `<` in postfix_expression.", "", - Level::kError) -DIAG(postfix_expression_expect_greater, "expected `>` in postfix_expression.", - "", Level::kError) -DIAG(postfix_expression_expect_kw_static_cast, - "expected `static_cast` in postfix_expression.", "", Level::kError) -DIAG(postfix_expression_expect_kw_reinterpret_cast, - "expected `reinterpret_cast` in postfix_expression.", "", Level::kError) -DIAG(postfix_expression_expect_kw_const_cast, - "expected `const_cast` in postfix_expression.", "", Level::kError) -DIAG(postfix_expression_expect_kw_typeid, - "expected `typeid` in postfix_expression.", "", Level::kError) -DIAG(unary_expression_expect_plusplus, "expected `++` in unary_expression.", "", - Level::kError) -DIAG(unary_expression_expect_minusminus, "expected `--` in unary_expression.", - "", Level::kError) -DIAG(unary_expression_expect_kw_sizeof, - "expected `sizeof` in unary_expression.", "", Level::kError) -DIAG(unary_expression_expect_l_paren, "expected `(` in unary_expression.", "", - Level::kError) -DIAG(unary_expression_expect_r_paren, "expected `)` in unary_expression.", "", - Level::kError) -DIAG(unary_expression_expect_ellipsis, "expected `...` in unary_expression.", - "", Level::kError) -DIAG(unary_expression_expect_identifier, - "expected `identifier` in unary_expression.", "", Level::kError) -DIAG(unary_expression_expect_kw_alignof, - "expected `alignof` in unary_expression.", "", Level::kError) -DIAG(unary_operator_expect_star, "expected `*` in unary_operator.", "", - Level::kError) -DIAG(unary_operator_expect_amp, "expected `&` in unary_operator.", "", - Level::kError) -DIAG(unary_operator_expect_plus, "expected `+` in unary_operator.", "", - Level::kError) -DIAG(unary_operator_expect_minus, "expected `-` in unary_operator.", "", - Level::kError) -DIAG(unary_operator_expect_exclaim, "expected `!` in unary_operator.", "", - Level::kError) -DIAG(unary_operator_expect_tilde, "expected `~` in unary_operator.", "", - Level::kError) -DIAG(await_expression_expect_kw_co_await, - "expected `co_await` in await_expression.", "", Level::kError) -DIAG(noexcept_expression_expect_kw_noexcept, - "expected `noexcept` in noexcept_expression.", "", Level::kError) -DIAG(noexcept_expression_expect_l_paren, "expected `(` in noexcept_expression.", - "", Level::kError) -DIAG(noexcept_expression_expect_r_paren, "expected `)` in noexcept_expression.", - "", Level::kError) -DIAG(new_expression_expect_coloncolon, "expected `::` in new_expression.", "", - Level::kError) -DIAG(new_expression_expect_kw_new, "expected `new` in new_expression.", "", - Level::kError) -DIAG(new_expression_expect_l_paren, "expected `(` in new_expression.", "", - Level::kError) -DIAG(new_expression_expect_r_paren, "expected `)` in new_expression.", "", - Level::kError) -DIAG(new_placement_expect_l_paren, "expected `(` in new_placement.", "", - Level::kError) -DIAG(new_placement_expect_r_paren, "expected `)` in new_placement.", "", - Level::kError) -DIAG(noptr_new_declarator_expect_l_square, - "expected `[` in noptr_new_declarator.", "", Level::kError) -DIAG(noptr_new_declarator_expect_r_square, - "expected `]` in noptr_new_declarator.", "", Level::kError) -DIAG(new_initializer_expect_l_paren, "expected `(` in new_initializer.", "", - Level::kError) -DIAG(new_initializer_expect_r_paren, "expected `)` in new_initializer.", "", - Level::kError) -DIAG(delete_expression_expect_coloncolon, "expected `::` in delete_expression.", - "", Level::kError) -DIAG(delete_expression_expect_kw_delete, - "expected `delete` in delete_expression.", "", Level::kError) -DIAG(delete_expression_expect_l_square, "expected `[` in delete_expression.", - "", Level::kError) -DIAG(delete_expression_expect_r_square, "expected `]` in delete_expression.", - "", Level::kError) -DIAG(cast_expression_expect_l_paren, "expected `(` in cast_expression.", "", - Level::kError) -DIAG(cast_expression_expect_r_paren, "expected `)` in cast_expression.", "", - Level::kError) -DIAG(pm_expression_expect_periodstar, "expected `.*` in pm_expression.", "", - Level::kError) -DIAG(pm_expression_expect_arrowstar, "expected `->*` in pm_expression.", "", - Level::kError) -DIAG(multiplicative_expression_expect_star, - "expected `*` in multiplicative_expression.", "", Level::kError) -DIAG(multiplicative_expression_expect_slash, - "expected `/` in multiplicative_expression.", "", Level::kError) -DIAG(multiplicative_expression_expect_percent, - "expected `%` in multiplicative_expression.", "", Level::kError) -DIAG(additive_expression_expect_plus, "expected `+` in additive_expression.", - "", Level::kError) -DIAG(additive_expression_expect_minus, "expected `-` in additive_expression.", - "", Level::kError) -DIAG(shift_expression_expect_lessless, "expected `<<` in shift_expression.", "", - Level::kError) -DIAG(shift_expression_expect_greatergreater, - "expected `>>` in shift_expression.", "", Level::kError) -DIAG(compare_expression_expect_spaceship, - "expected `<=>` in compare_expression.", "", Level::kError) -DIAG(relational_expression_expect_less, - "expected `<` in relational_expression.", "", Level::kError) -DIAG(relational_expression_expect_greater, - "expected `>` in relational_expression.", "", Level::kError) -DIAG(relational_expression_expect_lessequal, - "expected `<=` in relational_expression.", "", Level::kError) -DIAG(relational_expression_expect_greaterequal, - "expected `>=` in relational_expression.", "", Level::kError) -DIAG(equality_expression_expect_equalequal, - "expected `==` in equality_expression.", "", Level::kError) -DIAG(equality_expression_expect_exclaimequal, - "expected `!=` in equality_expression.", "", Level::kError) -DIAG(and_expression_expect_amp, "expected `&` in and_expression.", "", - Level::kError) -DIAG(exclusive_or_expression_expect_caret, - "expected `^` in exclusive_or_expression.", "", Level::kError) -DIAG(inclusive_or_expression_expect_pipe, - "expected `|` in inclusive_or_expression.", "", Level::kError) -DIAG(logical_and_expression_expect_ampamp, - "expected `&&` in logical_and_expression.", "", Level::kError) -DIAG(logical_or_expression_expect_pipepipe, - "expected `||` in logical_or_expression.", "", Level::kError) -DIAG(conditional_expression_expect_question, - "expected `?` in conditional_expression.", "", Level::kError) -DIAG(conditional_expression_expect_colon, - "expected `:` in conditional_expression.", "", Level::kError) -DIAG(yield_expression_expect_kw_co_yield, - "expected `co_yield` in yield_expression.", "", Level::kError) -DIAG(throw_expression_expect_kw_throw, "expected `throw` in throw_expression.", - "", Level::kError) -DIAG(assignment_operator_expect_equal, "expected `=` in assignment_operator.", - "", Level::kError) -DIAG(assignment_operator_expect_starequal, - "expected `*=` in assignment_operator.", "", Level::kError) -DIAG(assignment_operator_expect_slashequal, - "expected `/=` in assignment_operator.", "", Level::kError) -DIAG(assignment_operator_expect_percentequal, - "expected `%=` in assignment_operator.", "", Level::kError) -DIAG(assignment_operator_expect_plusequal, - "expected `+=` in assignment_operator.", "", Level::kError) -DIAG(assignment_operator_expect_minusequal, - "expected `-=` in assignment_operator.", "", Level::kError) -DIAG(assignment_operator_expect_greatergreaterequal, - "expected `>>=` in assignment_operator.", "", Level::kError) -DIAG(assignment_operator_expect_lesslessequal, - "expected `<<=` in assignment_operator.", "", Level::kError) -DIAG(assignment_operator_expect_ampequal, - "expected `&=` in assignment_operator.", "", Level::kError) -DIAG(assignment_operator_expect_caretequal, - "expected `^=` in assignment_operator.", "", Level::kError) -DIAG(assignment_operator_expect_pipeequal, - "expected `|=` in assignment_operator.", "", Level::kError) -DIAG(expression_expect_comma, "expected `,` in expression.", "", Level::kError) -DIAG(labeled_statement_expect_identifier, - "expected `identifier` in labeled_statement.", "", Level::kError) -DIAG(labeled_statement_expect_colon, "expected `:` in labeled_statement.", "", - Level::kError) -DIAG(labeled_statement_expect_kw_case, "expected `case` in labeled_statement.", - "", Level::kError) -DIAG(labeled_statement_expect_kw_default, - "expected `default` in labeled_statement.", "", Level::kError) -DIAG(expression_statement_expect_semi, "expected `;` in expression_statement.", - "", Level::kError) -DIAG(compound_statement_expect_l_brace, "expected `{` in compound_statement.", - "", Level::kError) -DIAG(compound_statement_expect_r_brace, "expected `}` in compound_statement.", - "", Level::kError) -DIAG(selection_statement_expect_kw_if, "expected `if` in selection_statement.", - "", Level::kError) -DIAG(selection_statement_expect_kw_constexpr, - "expected `constexpr` in selection_statement.", "", Level::kError) -DIAG(selection_statement_expect_l_paren, "expected `(` in selection_statement.", - "", Level::kError) -DIAG(selection_statement_expect_r_paren, "expected `)` in selection_statement.", - "", Level::kError) -DIAG(selection_statement_expect_kw_else, - "expected `else` in selection_statement.", "", Level::kError) -DIAG(selection_statement_expect_kw_switch, - "expected `switch` in selection_statement.", "", Level::kError) -DIAG(iteration_statement_expect_kw_while, - "expected `while` in iteration_statement.", "", Level::kError) -DIAG(iteration_statement_expect_l_paren, "expected `(` in iteration_statement.", - "", Level::kError) -DIAG(iteration_statement_expect_r_paren, "expected `)` in iteration_statement.", - "", Level::kError) -DIAG(iteration_statement_expect_kw_do, "expected `do` in iteration_statement.", - "", Level::kError) -DIAG(iteration_statement_expect_semi, "expected `;` in iteration_statement.", - "", Level::kError) -DIAG(iteration_statement_expect_kw_for, - "expected `for` in iteration_statement.", "", Level::kError) -DIAG(iteration_statement_expect_colon, "expected `:` in iteration_statement.", - "", Level::kError) -DIAG(for_range_declaration_expect_l_square, - "expected `[` in for_range_declaration.", "", Level::kError) -DIAG(for_range_declaration_expect_r_square, - "expected `]` in for_range_declaration.", "", Level::kError) -DIAG(jump_statement_expect_kw_break, "expected `break` in jump_statement.", "", - Level::kError) -DIAG(jump_statement_expect_semi, "expected `;` in jump_statement.", "", - Level::kError) -DIAG(jump_statement_expect_kw_continue, - "expected `continue` in jump_statement.", "", Level::kError) -DIAG(jump_statement_expect_kw_return, "expected `return` in jump_statement.", - "", Level::kError) -DIAG(jump_statement_expect_kw_goto, "expected `goto` in jump_statement.", "", - Level::kError) -DIAG(jump_statement_expect_identifier, - "expected `identifier` in jump_statement.", "", Level::kError) -DIAG(coroutine_return_statement_expect_kw_co_return, - "expected `co_return` in coroutine_return_statement.", "", Level::kError) -DIAG(coroutine_return_statement_expect_semi, - "expected `;` in coroutine_return_statement.", "", Level::kError) -DIAG(nodeclspec_function_declaration_expect_semi, - "expected `;` in nodeclspec_function_declaration.", "", Level::kError) -DIAG(alias_declaration_expect_kw_using, - "expected `using` in alias_declaration.", "", Level::kError) -DIAG(alias_declaration_expect_identifier, - "expected `identifier` in alias_declaration.", "", Level::kError) -DIAG(alias_declaration_expect_equal, "expected `=` in alias_declaration.", "", - Level::kError) -DIAG(alias_declaration_expect_semi, "expected `;` in alias_declaration.", "", - Level::kError) -DIAG(simple_declaration_expect_semi, "expected `;` in simple_declaration.", "", - Level::kError) -DIAG(simple_declaration_expect_l_square, "expected `[` in simple_declaration.", - "", Level::kError) -DIAG(simple_declaration_expect_r_square, "expected `]` in simple_declaration.", - "", Level::kError) -DIAG(static_assert_declaration_expect_kw_static_assert, - "expected `static_assert` in static_assert_declaration.", "", - Level::kError) -DIAG(static_assert_declaration_expect_l_paren, - "expected `(` in static_assert_declaration.", "", Level::kError) -DIAG(static_assert_declaration_expect_r_paren, - "expected `)` in static_assert_declaration.", "", Level::kError) -DIAG(static_assert_declaration_expect_semi, - "expected `;` in static_assert_declaration.", "", Level::kError) -DIAG(static_assert_declaration_expect_comma, - "expected `,` in static_assert_declaration.", "", Level::kError) -DIAG(empty_declaration_expect_semi, "expected `;` in empty_declaration.", "", - Level::kError) -DIAG(attribute_declaration_expect_semi, - "expected `;` in attribute_declaration.", "", Level::kError) -DIAG(decl_specifier_expect_kw_friend, "expected `friend` in decl_specifier.", - "", Level::kError) -DIAG(decl_specifier_expect_kw_typedef, "expected `typedef` in decl_specifier.", - "", Level::kError) -DIAG(decl_specifier_expect_kw_constexpr, - "expected `constexpr` in decl_specifier.", "", Level::kError) -DIAG(decl_specifier_expect_kw_consteval, - "expected `consteval` in decl_specifier.", "", Level::kError) -DIAG(decl_specifier_expect_kw_constinit, - "expected `constinit` in decl_specifier.", "", Level::kError) -DIAG(decl_specifier_expect_kw_inline, "expected `inline` in decl_specifier.", - "", Level::kError) -DIAG(storage_class_specifier_expect_kw_static, - "expected `static` in storage_class_specifier.", "", Level::kError) -DIAG(storage_class_specifier_expect_kw_thread_local, - "expected `thread_local` in storage_class_specifier.", "", Level::kError) -DIAG(storage_class_specifier_expect_kw_extern, - "expected `extern` in storage_class_specifier.", "", Level::kError) -DIAG(storage_class_specifier_expect_kw_mutable, - "expected `mutable` in storage_class_specifier.", "", Level::kError) -DIAG(function_specifier_expect_kw_virtual, - "expected `virtual` in function_specifier.", "", Level::kError) -DIAG(explicit_specifier_expect_kw_explicit, - "expected `explicit` in explicit_specifier.", "", Level::kError) -DIAG(explicit_specifier_expect_l_paren, "expected `(` in explicit_specifier.", - "", Level::kError) -DIAG(explicit_specifier_expect_r_paren, "expected `)` in explicit_specifier.", - "", Level::kError) -DIAG(typedef_name_expect_identifier, "expected `identifier` in typedef_name.", - "", Level::kError) -DIAG(simple_type_specifier_expect_kw_template, - "expected `template` in simple_type_specifier.", "", Level::kError) -DIAG(simple_type_specifier_expect_kw_char, - "expected `char` in simple_type_specifier.", "", Level::kError) -DIAG(simple_type_specifier_expect_kw_char8_t, - "expected `char8_t` in simple_type_specifier.", "", Level::kError) -DIAG(simple_type_specifier_expect_kw_char16_t, - "expected `char16_t` in simple_type_specifier.", "", Level::kError) -DIAG(simple_type_specifier_expect_kw_char32_t, - "expected `char32_t` in simple_type_specifier.", "", Level::kError) -DIAG(simple_type_specifier_expect_kw_wchar_t, - "expected `wchar_t` in simple_type_specifier.", "", Level::kError) -DIAG(simple_type_specifier_expect_kw_bool, - "expected `bool` in simple_type_specifier.", "", Level::kError) -DIAG(simple_type_specifier_expect_kw_short, - "expected `short` in simple_type_specifier.", "", Level::kError) -DIAG(simple_type_specifier_expect_kw_int, - "expected `int` in simple_type_specifier.", "", Level::kError) -DIAG(simple_type_specifier_expect_kw_long, - "expected `long` in simple_type_specifier.", "", Level::kError) -DIAG(simple_type_specifier_expect_kw_signed, - "expected `signed` in simple_type_specifier.", "", Level::kError) -DIAG(simple_type_specifier_expect_kw_unsigned, - "expected `unsigned` in simple_type_specifier.", "", Level::kError) -DIAG(simple_type_specifier_expect_kw_float, - "expected `float` in simple_type_specifier.", "", Level::kError) -DIAG(simple_type_specifier_expect_kw_double, - "expected `double` in simple_type_specifier.", "", Level::kError) -DIAG(simple_type_specifier_expect_kw_void, - "expected `void` in simple_type_specifier.", "", Level::kError) -DIAG(elaborated_type_specifier_expect_identifier, - "expected `identifier` in elaborated_type_specifier.", "", Level::kError) -DIAG(elaborated_type_specifier_expect_kw_template, - "expected `template` in elaborated_type_specifier.", "", Level::kError) -DIAG(elaborated_enum_specifier_expect_kw_enum, - "expected `enum` in elaborated_enum_specifier.", "", Level::kError) -DIAG(elaborated_enum_specifier_expect_identifier, - "expected `identifier` in elaborated_enum_specifier.", "", Level::kError) -DIAG(decltype_specifier_expect_kw_decltype, - "expected `decltype` in decltype_specifier.", "", Level::kError) -DIAG(decltype_specifier_expect_l_paren, "expected `(` in decltype_specifier.", - "", Level::kError) -DIAG(decltype_specifier_expect_r_paren, "expected `)` in decltype_specifier.", - "", Level::kError) -DIAG(placeholder_type_specifier_expect_kw_auto, - "expected `auto` in placeholder_type_specifier.", "", Level::kError) -DIAG(placeholder_type_specifier_expect_kw_decltype, - "expected `decltype` in placeholder_type_specifier.", "", Level::kError) -DIAG(placeholder_type_specifier_expect_l_paren, - "expected `(` in placeholder_type_specifier.", "", Level::kError) -DIAG(placeholder_type_specifier_expect_r_paren, - "expected `)` in placeholder_type_specifier.", "", Level::kError) -DIAG(init_declarator_list_expect_comma, "expected `,` in init_declarator_list.", - "", Level::kError) -DIAG(noptr_declarator_expect_l_square, "expected `[` in noptr_declarator.", "", - Level::kError) -DIAG(noptr_declarator_expect_r_square, "expected `]` in noptr_declarator.", "", - Level::kError) -DIAG(noptr_declarator_expect_l_paren, "expected `(` in noptr_declarator.", "", - Level::kError) -DIAG(noptr_declarator_expect_r_paren, "expected `)` in noptr_declarator.", "", - Level::kError) -DIAG(parameters_and_qualifiers_expect_l_paren, - "expected `(` in parameters_and_qualifiers.", "", Level::kError) -DIAG(parameters_and_qualifiers_expect_r_paren, - "expected `)` in parameters_and_qualifiers.", "", Level::kError) -DIAG(trailing_return_type_expect_arrow, - "expected `->` in trailing_return_type.", "", Level::kError) -DIAG(ptr_operator_expect_star, "expected `*` in ptr_operator.", "", - Level::kError) -DIAG(ptr_operator_expect_amp, "expected `&` in ptr_operator.", "", - Level::kError) -DIAG(ptr_operator_expect_ampamp, "expected `&&` in ptr_operator.", "", - Level::kError) -DIAG(cv_qualifier_expect_kw_const, "expected `const` in cv_qualifier.", "", - Level::kError) -DIAG(cv_qualifier_expect_kw_volatile, "expected `volatile` in cv_qualifier.", - "", Level::kError) -DIAG(ref_qualifier_expect_amp, "expected `&` in ref_qualifier.", "", - Level::kError) -DIAG(ref_qualifier_expect_ampamp, "expected `&&` in ref_qualifier.", "", - Level::kError) -DIAG(declarator_id_expect_ellipsis, "expected `...` in declarator_id.", "", - Level::kError) -DIAG(noptr_abstract_declarator_expect_l_square, - "expected `[` in noptr_abstract_declarator.", "", Level::kError) -DIAG(noptr_abstract_declarator_expect_r_square, - "expected `]` in noptr_abstract_declarator.", "", Level::kError) -DIAG(noptr_abstract_declarator_expect_l_paren, - "expected `(` in noptr_abstract_declarator.", "", Level::kError) -DIAG(noptr_abstract_declarator_expect_r_paren, - "expected `)` in noptr_abstract_declarator.", "", Level::kError) -DIAG(noptr_abstract_pack_declarator_expect_l_square, - "expected `[` in noptr_abstract_pack_declarator.", "", Level::kError) -DIAG(noptr_abstract_pack_declarator_expect_r_square, - "expected `]` in noptr_abstract_pack_declarator.", "", Level::kError) -DIAG(noptr_abstract_pack_declarator_expect_ellipsis, - "expected `...` in noptr_abstract_pack_declarator.", "", Level::kError) -DIAG(parameter_declaration_clause_expect_ellipsis, - "expected `...` in parameter_declaration_clause.", "", Level::kError) -DIAG(parameter_declaration_clause_expect_comma, - "expected `,` in parameter_declaration_clause.", "", Level::kError) -DIAG(parameter_declaration_list_expect_comma, - "expected `,` in parameter_declaration_list.", "", Level::kError) -DIAG(parameter_declaration_expect_equal, - "expected `=` in parameter_declaration.", "", Level::kError) -DIAG(initializer_expect_l_paren, "expected `(` in initializer.", "", - Level::kError) -DIAG(initializer_expect_r_paren, "expected `)` in initializer.", "", - Level::kError) -DIAG(brace_or_equal_initializer_expect_equal, - "expected `=` in brace_or_equal_initializer.", "", Level::kError) -DIAG(braced_init_list_expect_l_brace, "expected `{` in braced_init_list.", "", - Level::kError) -DIAG(braced_init_list_expect_comma, "expected `,` in braced_init_list.", "", - Level::kError) -DIAG(braced_init_list_expect_r_brace, "expected `}` in braced_init_list.", "", - Level::kError) -DIAG(initializer_list_expect_ellipsis, "expected `...` in initializer_list.", - "", Level::kError) -DIAG(initializer_list_expect_comma, "expected `,` in initializer_list.", "", - Level::kError) -DIAG(designated_initializer_list_expect_comma, - "expected `,` in designated_initializer_list.", "", Level::kError) -DIAG(designator_expect_period, "expected `.` in designator.", "", Level::kError) -DIAG(designator_expect_identifier, "expected `identifier` in designator.", "", - Level::kError) -DIAG(function_body_expect_equal, "expected `=` in function_body.", "", - Level::kError) -DIAG(function_body_expect_kw_default, "expected `default` in function_body.", - "", Level::kError) -DIAG(function_body_expect_semi, "expected `;` in function_body.", "", - Level::kError) -DIAG(function_body_expect_kw_delete, "expected `delete` in function_body.", "", - Level::kError) -DIAG(enum_name_expect_identifier, "expected `identifier` in enum_name.", "", - Level::kError) -DIAG(enum_specifier_expect_l_brace, "expected `{` in enum_specifier.", "", - Level::kError) -DIAG(enum_specifier_expect_r_brace, "expected `}` in enum_specifier.", "", - Level::kError) -DIAG(enum_specifier_expect_comma, "expected `,` in enum_specifier.", "", - Level::kError) -DIAG(enum_head_name_expect_identifier, - "expected `identifier` in enum_head_name.", "", Level::kError) -DIAG(opaque_enum_declaration_expect_semi, - "expected `;` in opaque_enum_declaration.", "", Level::kError) -DIAG(enum_key_expect_kw_enum, "expected `enum` in enum_key.", "", Level::kError) -DIAG(enum_key_expect_kw_class, "expected `class` in enum_key.", "", - Level::kError) -DIAG(enum_key_expect_kw_struct, "expected `struct` in enum_key.", "", - Level::kError) -DIAG(enum_base_expect_colon, "expected `:` in enum_base.", "", Level::kError) -DIAG(enumerator_list_expect_comma, "expected `,` in enumerator_list.", "", - Level::kError) -DIAG(enumerator_definition_expect_equal, - "expected `=` in enumerator_definition.", "", Level::kError) -DIAG(enumerator_expect_identifier, "expected `identifier` in enumerator.", "", - Level::kError) -DIAG(using_enum_declaration_expect_kw_using, - "expected `using` in using_enum_declaration.", "", Level::kError) -DIAG(using_enum_declaration_expect_semi, - "expected `;` in using_enum_declaration.", "", Level::kError) -DIAG(namespace_name_expect_identifier, - "expected `identifier` in namespace_name.", "", Level::kError) -DIAG(named_namespace_definition_expect_kw_inline, - "expected `inline` in named_namespace_definition.", "", Level::kError) -DIAG(named_namespace_definition_expect_kw_namespace, - "expected `namespace` in named_namespace_definition.", "", Level::kError) -DIAG(named_namespace_definition_expect_identifier, - "expected `identifier` in named_namespace_definition.", "", Level::kError) -DIAG(named_namespace_definition_expect_l_brace, - "expected `{` in named_namespace_definition.", "", Level::kError) -DIAG(named_namespace_definition_expect_r_brace, - "expected `}` in named_namespace_definition.", "", Level::kError) -DIAG(unnamed_namespace_definition_expect_kw_inline, - "expected `inline` in unnamed_namespace_definition.", "", Level::kError) -DIAG(unnamed_namespace_definition_expect_kw_namespace, - "expected `namespace` in unnamed_namespace_definition.", "", Level::kError) -DIAG(unnamed_namespace_definition_expect_l_brace, - "expected `{` in unnamed_namespace_definition.", "", Level::kError) -DIAG(unnamed_namespace_definition_expect_r_brace, - "expected `}` in unnamed_namespace_definition.", "", Level::kError) -DIAG(nested_namespace_definition_expect_kw_namespace, - "expected `namespace` in nested_namespace_definition.", "", Level::kError) -DIAG(nested_namespace_definition_expect_coloncolon, - "expected `::` in nested_namespace_definition.", "", Level::kError) -DIAG(nested_namespace_definition_expect_kw_inline, - "expected `inline` in nested_namespace_definition.", "", Level::kError) -DIAG(nested_namespace_definition_expect_identifier, - "expected `identifier` in nested_namespace_definition.", "", Level::kError) -DIAG(nested_namespace_definition_expect_l_brace, - "expected `{` in nested_namespace_definition.", "", Level::kError) -DIAG(nested_namespace_definition_expect_r_brace, - "expected `}` in nested_namespace_definition.", "", Level::kError) -DIAG(enclosing_namespace_specifier_expect_identifier, - "expected `identifier` in enclosing_namespace_specifier.", "", - Level::kError) -DIAG(enclosing_namespace_specifier_expect_coloncolon, - "expected `::` in enclosing_namespace_specifier.", "", Level::kError) -DIAG(enclosing_namespace_specifier_expect_kw_inline, - "expected `inline` in enclosing_namespace_specifier.", "", Level::kError) -DIAG(namespace_alias_expect_identifier, - "expected `identifier` in namespace_alias.", "", Level::kError) -DIAG(namespace_alias_definition_expect_kw_namespace, - "expected `namespace` in namespace_alias_definition.", "", Level::kError) -DIAG(namespace_alias_definition_expect_identifier, - "expected `identifier` in namespace_alias_definition.", "", Level::kError) -DIAG(namespace_alias_definition_expect_equal, - "expected `=` in namespace_alias_definition.", "", Level::kError) -DIAG(namespace_alias_definition_expect_semi, - "expected `;` in namespace_alias_definition.", "", Level::kError) -DIAG(using_directive_expect_kw_using, "expected `using` in using_directive.", - "", Level::kError) -DIAG(using_directive_expect_kw_namespace, - "expected `namespace` in using_directive.", "", Level::kError) -DIAG(using_directive_expect_semi, "expected `;` in using_directive.", "", - Level::kError) -DIAG(using_declaration_expect_kw_using, - "expected `using` in using_declaration.", "", Level::kError) -DIAG(using_declaration_expect_semi, "expected `;` in using_declaration.", "", - Level::kError) -DIAG(using_declarator_list_expect_ellipsis, - "expected `...` in using_declarator_list.", "", Level::kError) -DIAG(using_declarator_list_expect_comma, - "expected `,` in using_declarator_list.", "", Level::kError) -DIAG(using_declarator_expect_kw_typename, - "expected `typename` in using_declarator.", "", Level::kError) -DIAG(asm_declaration_expect_kw_asm, "expected `asm` in asm_declaration.", "", - Level::kError) -DIAG(asm_declaration_expect_l_paren, "expected `(` in asm_declaration.", "", - Level::kError) -DIAG(asm_declaration_expect_r_paren, "expected `)` in asm_declaration.", "", - Level::kError) -DIAG(asm_declaration_expect_semi, "expected `;` in asm_declaration.", "", - Level::kError) -DIAG(linkage_specification_expect_kw_extern, - "expected `extern` in linkage_specification.", "", Level::kError) -DIAG(linkage_specification_expect_l_brace, - "expected `{` in linkage_specification.", "", Level::kError) -DIAG(linkage_specification_expect_r_brace, - "expected `}` in linkage_specification.", "", Level::kError) -DIAG(attribute_specifier_expect_l_square, - "expected `[` in attribute_specifier.", "", Level::kError) -DIAG(attribute_specifier_expect_r_square, - "expected `]` in attribute_specifier.", "", Level::kError) -DIAG(alignment_specifier_expect_kw_alignas, - "expected `alignas` in alignment_specifier.", "", Level::kError) -DIAG(alignment_specifier_expect_l_paren, "expected `(` in alignment_specifier.", - "", Level::kError) -DIAG(alignment_specifier_expect_ellipsis, - "expected `...` in alignment_specifier.", "", Level::kError) -DIAG(alignment_specifier_expect_r_paren, "expected `)` in alignment_specifier.", - "", Level::kError) -DIAG(attribute_using_prefix_expect_kw_using, - "expected `using` in attribute_using_prefix.", "", Level::kError) -DIAG(attribute_using_prefix_expect_colon, - "expected `:` in attribute_using_prefix.", "", Level::kError) -DIAG(attribute_list_expect_comma, "expected `,` in attribute_list.", "", - Level::kError) -DIAG(attribute_list_expect_ellipsis, "expected `...` in attribute_list.", "", - Level::kError) -DIAG(attribute_token_expect_identifier, - "expected `identifier` in attribute_token.", "", Level::kError) -DIAG(attribute_scoped_token_expect_coloncolon, - "expected `::` in attribute_scoped_token.", "", Level::kError) -DIAG(attribute_scoped_token_expect_identifier, - "expected `identifier` in attribute_scoped_token.", "", Level::kError) -DIAG(attribute_namespace_expect_identifier, - "expected `identifier` in attribute_namespace.", "", Level::kError) -DIAG(attribute_argument_clause_expect_l_paren, - "expected `(` in attribute_argument_clause.", "", Level::kError) -DIAG(attribute_argument_clause_expect_r_paren, - "expected `)` in attribute_argument_clause.", "", Level::kError) -DIAG(balanced_token_expect_l_paren, "expected `(` in balanced_token.", "", - Level::kError) -DIAG(balanced_token_expect_r_paren, "expected `)` in balanced_token.", "", - Level::kError) -DIAG(balanced_token_expect_l_square, "expected `[` in balanced_token.", "", - Level::kError) -DIAG(balanced_token_expect_r_square, "expected `]` in balanced_token.", "", - Level::kError) -DIAG(balanced_token_expect_l_brace, "expected `{` in balanced_token.", "", - Level::kError) -DIAG(balanced_token_expect_r_brace, "expected `}` in balanced_token.", "", - Level::kError) -DIAG(balanced_token_expect_identifier, - "expected `identifier` in balanced_token.", "", Level::kError) -DIAG(module_declaration_expect_kw_export, - "expected `export` in module_declaration.", "", Level::kError) -DIAG(module_declaration_expect_kw_module, - "expected `module` in module_declaration.", "", Level::kError) -DIAG(module_declaration_expect_semi, "expected `;` in module_declaration.", "", - Level::kError) -DIAG(module_name_expect_identifier, "expected `identifier` in module_name.", "", - Level::kError) -DIAG(module_partition_expect_colon, "expected `:` in module_partition.", "", - Level::kError) -DIAG(module_partition_expect_identifier, - "expected `identifier` in module_partition.", "", Level::kError) -DIAG(module_name_qualifier_expect_identifier, - "expected `identifier` in module_name_qualifier.", "", Level::kError) -DIAG(module_name_qualifier_expect_period, - "expected `.` in module_name_qualifier.", "", Level::kError) -DIAG(export_declaration_expect_kw_export, - "expected `export` in export_declaration.", "", Level::kError) -DIAG(export_declaration_expect_l_brace, "expected `{` in export_declaration.", - "", Level::kError) -DIAG(export_declaration_expect_r_brace, "expected `}` in export_declaration.", - "", Level::kError) -DIAG(module_import_declaration_expect_kw_import, - "expected `import` in module_import_declaration.", "", Level::kError) -DIAG(global_module_fragment_expect_kw_module, - "expected `module` in global_module_fragment.", "", Level::kError) -DIAG(global_module_fragment_expect_semi, - "expected `;` in global_module_fragment.", "", Level::kError) -DIAG(private_module_fragment_expect_kw_module, - "expected `module` in private_module_fragment.", "", Level::kError) -DIAG(private_module_fragment_expect_colon, - "expected `:` in private_module_fragment.", "", Level::kError) -DIAG(private_module_fragment_expect_kw_private, - "expected `private` in private_module_fragment.", "", Level::kError) -DIAG(private_module_fragment_expect_semi, - "expected `;` in private_module_fragment.", "", Level::kError) -DIAG(class_name_expect_identifier, "expected `identifier` in class_name.", "", - Level::kError) -DIAG(class_specifier_expect_l_brace, "expected `{` in class_specifier.", "", - Level::kError) -DIAG(class_specifier_expect_r_brace, "expected `}` in class_specifier.", "", - Level::kError) -DIAG(class_virt_specifier_expect_kw_final, - "expected `final` in class_virt_specifier.", "", Level::kError) -DIAG(class_key_expect_kw_class, "expected `class` in class_key.", "", - Level::kError) -DIAG(class_key_expect_kw_struct, "expected `struct` in class_key.", "", - Level::kError) -DIAG(class_key_expect_kw_union, "expected `union` in class_key.", "", - Level::kError) -DIAG(member_specification_expect_colon, "expected `:` in member_specification.", - "", Level::kError) -DIAG(member_declaration_expect_semi, "expected `;` in member_declaration.", "", - Level::kError) -DIAG(member_declarator_list_expect_comma, - "expected `,` in member_declarator_list.", "", Level::kError) -DIAG(member_declarator_expect_identifier, - "expected `identifier` in member_declarator.", "", Level::kError) -DIAG(member_declarator_expect_colon, "expected `:` in member_declarator.", "", - Level::kError) -DIAG(virt_specifier_expect_kw_override, - "expected `override` in virt_specifier.", "", Level::kError) -DIAG(virt_specifier_expect_kw_final, "expected `final` in virt_specifier.", "", - Level::kError) -DIAG(pure_specifier_expect_equal, "expected `=` in pure_specifier.", "", - Level::kError) -DIAG(conversion_function_id_expect_kw_operator, - "expected `operator` in conversion_function_id.", "", Level::kError) -DIAG(base_clause_expect_colon, "expected `:` in base_clause.", "", - Level::kError) -DIAG(base_specifier_list_expect_ellipsis, - "expected `...` in base_specifier_list.", "", Level::kError) -DIAG(base_specifier_list_expect_comma, "expected `,` in base_specifier_list.", - "", Level::kError) -DIAG(base_specifier_expect_kw_virtual, "expected `virtual` in base_specifier.", - "", Level::kError) -DIAG(class_or_decltype_expect_kw_template, - "expected `template` in class_or_decltype.", "", Level::kError) -DIAG(access_specifier_expect_kw_private, - "expected `private` in access_specifier.", "", Level::kError) -DIAG(access_specifier_expect_kw_protected, - "expected `protected` in access_specifier.", "", Level::kError) -DIAG(access_specifier_expect_kw_public, - "expected `public` in access_specifier.", "", Level::kError) -DIAG(ctor_initializer_expect_colon, "expected `:` in ctor_initializer.", "", - Level::kError) -DIAG(mem_initializer_list_expect_ellipsis, - "expected `...` in mem_initializer_list.", "", Level::kError) -DIAG(mem_initializer_expect_l_paren, "expected `(` in mem_initializer.", "", - Level::kError) -DIAG(mem_initializer_expect_r_paren, "expected `)` in mem_initializer.", "", - Level::kError) -DIAG(mem_initializer_id_expect_identifier, - "expected `identifier` in mem_initializer_id.", "", Level::kError) -DIAG(operator_function_id_expect_kw_operator, - "expected `operator` in operator_function_id.", "", Level::kError) -DIAG(the_operator_expect_kw_new, "expected `new` in the_operator.", "", - Level::kError) -DIAG(the_operator_expect_kw_delete, "expected `delete` in the_operator.", "", - Level::kError) -DIAG(literal_operator_id_expect_kw_operator, - "expected `operator` in literal_operator_id.", "", Level::kError) -DIAG(literal_operator_id_expect_identifier, - "expected `identifier` in literal_operator_id.", "", Level::kError) -DIAG(template_head_expect_kw_template, "expected `template` in template_head.", - "", Level::kError) -DIAG(template_head_expect_less, "expected `<` in template_head.", "", - Level::kError) -DIAG(template_head_expect_greater, "expected `>` in template_head.", "", - Level::kError) -DIAG(template_parameter_list_expect_comma, - "expected `,` in template_parameter_list.", "", Level::kError) -DIAG(requires_clause_expect_kw_requires, - "expected `requires` in requires_clause.", "", Level::kError) -DIAG(constraint_logical_or_expression_expect_pipepipe, - "expected `||` in constraint_logical_or_expression.", "", Level::kError) -DIAG(constraint_logical_and_expression_expect_ampamp, - "expected `&&` in constraint_logical_and_expression.", "", Level::kError) -DIAG(type_parameter_expect_ellipsis, "expected `...` in type_parameter.", "", - Level::kError) -DIAG(type_parameter_expect_identifier, - "expected `identifier` in type_parameter.", "", Level::kError) -DIAG(type_parameter_expect_equal, "expected `=` in type_parameter.", "", - Level::kError) -DIAG(type_parameter_key_expect_kw_class, - "expected `class` in type_parameter_key.", "", Level::kError) -DIAG(type_parameter_key_expect_kw_typename, - "expected `typename` in type_parameter_key.", "", Level::kError) -DIAG(type_constraint_expect_less, "expected `<` in type_constraint.", "", - Level::kError) -DIAG(type_constraint_expect_greater, "expected `>` in type_constraint.", "", - Level::kError) -DIAG(simple_template_id_expect_less, "expected `<` in simple_template_id.", "", - Level::kError) -DIAG(simple_template_id_expect_greater, "expected `>` in simple_template_id.", - "", Level::kError) -DIAG(template_id_expect_less, "expected `<` in template_id.", "", Level::kError) -DIAG(template_id_expect_greater, "expected `>` in template_id.", "", - Level::kError) -DIAG(template_name_expect_identifier, "expected `identifier` in template_name.", - "", Level::kError) -DIAG(template_argument_list_expect_ellipsis, - "expected `...` in template_argument_list.", "", Level::kError) -DIAG(template_argument_list_expect_comma, - "expected `,` in template_argument_list.", "", Level::kError) -DIAG(deduction_guide_expect_l_paren, "expected `(` in deduction_guide.", "", - Level::kError) -DIAG(deduction_guide_expect_r_paren, "expected `)` in deduction_guide.", "", - Level::kError) -DIAG(deduction_guide_expect_arrow, "expected `->` in deduction_guide.", "", - Level::kError) -DIAG(deduction_guide_expect_semi, "expected `;` in deduction_guide.", "", - Level::kError) -DIAG(concept_definition_expect_kw_concept, - "expected `concept` in concept_definition.", "", Level::kError) -DIAG(concept_definition_expect_equal, "expected `=` in concept_definition.", "", - Level::kError) -DIAG(concept_definition_expect_semi, "expected `;` in concept_definition.", "", - Level::kError) -DIAG(concept_name_expect_identifier, "expected `identifier` in concept_name.", - "", Level::kError) -DIAG(typename_specifier_expect_kw_typename, - "expected `typename` in typename_specifier.", "", Level::kError) -DIAG(typename_specifier_expect_identifier, - "expected `identifier` in typename_specifier.", "", Level::kError) -DIAG(typename_specifier_expect_kw_template, - "expected `template` in typename_specifier.", "", Level::kError) -DIAG(explicit_instantiation_expect_kw_extern, - "expected `extern` in explicit_instantiation.", "", Level::kError) -DIAG(explicit_instantiation_expect_kw_template, - "expected `template` in explicit_instantiation.", "", Level::kError) -DIAG(explicit_specialization_expect_kw_template, - "expected `template` in explicit_specialization.", "", Level::kError) -DIAG(explicit_specialization_expect_less, - "expected `<` in explicit_specialization.", "", Level::kError) -DIAG(explicit_specialization_expect_greater, - "expected `>` in explicit_specialization.", "", Level::kError) -DIAG(try_block_expect_kw_try, "expected `try` in try_block.", "", Level::kError) -DIAG(function_try_block_expect_kw_try, "expected `try` in function_try_block.", - "", Level::kError) -DIAG(handler_expect_kw_catch, "expected `catch` in handler.", "", Level::kError) -DIAG(handler_expect_l_paren, "expected `(` in handler.", "", Level::kError) -DIAG(handler_expect_r_paren, "expected `)` in handler.", "", Level::kError) -DIAG(exception_declaration_expect_ellipsis, - "expected `...` in exception_declaration.", "", Level::kError) -DIAG(noexcept_specifier_expect_kw_noexcept, - "expected `noexcept` in noexcept_specifier.", "", Level::kError) -DIAG(noexcept_specifier_expect_l_paren, "expected `(` in noexcept_specifier.", - "", Level::kError) -DIAG(noexcept_specifier_expect_r_paren, "expected `)` in noexcept_specifier.", - "", Level::kError) -DIAG(pp_global_module_fragment_expect_kw_module, - "expected `module` in pp_global_module_fragment.", "", Level::kError) -DIAG(pp_global_module_fragment_expect_semi, - "expected `;` in pp_global_module_fragment.", "", Level::kError) -DIAG(pp_private_module_fragment_expect_kw_module, - "expected `module` in pp_private_module_fragment.", "", Level::kError) -DIAG(pp_private_module_fragment_expect_colon, - "expected `:` in pp_private_module_fragment.", "", Level::kError) -DIAG(pp_private_module_fragment_expect_kw_private, - "expected `private` in pp_private_module_fragment.", "", Level::kError) -DIAG(pp_private_module_fragment_expect_semi, - "expected `;` in pp_private_module_fragment.", "", Level::kError) -DIAG(group_part_expect_hash, "expected `#` in group_part.", "", Level::kError) -DIAG(control_line_expect_hash, "expected `#` in control_line.", "", - Level::kError) -DIAG(control_line_expect_kw_include, "expected `include` in control_line.", "", - Level::kError) -DIAG(control_line_expect_kw_define, "expected `define` in control_line.", "", - Level::kError) -DIAG(control_line_expect_identifier, "expected `identifier` in control_line.", - "", Level::kError) -DIAG(control_line_expect_r_paren, "expected `)` in control_line.", "", - Level::kError) -DIAG(control_line_expect_ellipsis, "expected `...` in control_line.", "", - Level::kError) -DIAG(control_line_expect_kw_undef, "expected `undef` in control_line.", "", - Level::kError) -DIAG(control_line_expect_kw_line, "expected `line` in control_line.", "", - Level::kError) -DIAG(control_line_expect_kw_error, "expected `error` in control_line.", "", - Level::kError) -DIAG(control_line_expect_kw_pragma, "expected `pragma` in control_line.", "", - Level::kError) -DIAG(if_group_expect_hash, "expected `#` in if_group.", "", Level::kError) -DIAG(if_group_expect_kw_if, "expected `if` in if_group.", "", Level::kError) -DIAG(if_group_expect_kw_ifdef, "expected `ifdef` in if_group.", "", - Level::kError) -DIAG(if_group_expect_identifier, "expected `identifier` in if_group.", "", - Level::kError) -DIAG(if_group_expect_kw_ifndef, "expected `ifndef` in if_group.", "", - Level::kError) -DIAG(elif_group_expect_hash, "expected `#` in elif_group.", "", Level::kError) -DIAG(elif_group_expect_kw_elif, "expected `elif` in elif_group.", "", - Level::kError) -DIAG(else_group_expect_hash, "expected `#` in else_group.", "", Level::kError) -DIAG(else_group_expect_kw_else, "expected `else` in else_group.", "", - Level::kError) -DIAG(endif_line_expect_hash, "expected `#` in endif_line.", "", Level::kError) -DIAG(endif_line_expect_kw_endif, "expected `endif` in endif_line.", "", - Level::kError) -DIAG(identifier_list_expect_identifier, - "expected `identifier` in identifier_list.", "", Level::kError) -DIAG(identifier_list_expect_comma, "expected `,` in identifier_list.", "", - Level::kError) -DIAG(defined_macro_expression_expect_kw_defined, - "expected `defined` in defined_macro_expression.", "", Level::kError) -DIAG(defined_macro_expression_expect_identifier, - "expected `identifier` in defined_macro_expression.", "", Level::kError) -DIAG(defined_macro_expression_expect_l_paren, - "expected `(` in defined_macro_expression.", "", Level::kError) -DIAG(defined_macro_expression_expect_r_paren, - "expected `)` in defined_macro_expression.", "", Level::kError) -DIAG(header_name_tokens_expect_less, "expected `<` in header_name_tokens.", "", - Level::kError) -DIAG(header_name_tokens_expect_greater, "expected `>` in header_name_tokens.", - "", Level::kError) -DIAG(has_include_expression_expect_kw___has_include, - "expected `__has_include` in has_include_expression.", "", Level::kError) -DIAG(has_include_expression_expect_l_paren, - "expected `(` in has_include_expression.", "", Level::kError) -DIAG(has_include_expression_expect_r_paren, - "expected `)` in has_include_expression.", "", Level::kError) -DIAG(has_attribute_expression_expect_kw___has_cpp_attribute, - "expected `__has_cpp_attribute` in has_attribute_expression.", "", - Level::kError) -DIAG(has_attribute_expression_expect_l_paren, - "expected `(` in has_attribute_expression.", "", Level::kError) -DIAG(has_attribute_expression_expect_r_paren, - "expected `)` in has_attribute_expression.", "", Level::kError) -DIAG(pp_module_expect_kw_export, "expected `export` in pp_module.", "", - Level::kError) -DIAG(pp_module_expect_kw_module, "expected `module` in pp_module.", "", - Level::kError) -DIAG(pp_module_expect_semi, "expected `;` in pp_module.", "", Level::kError) -DIAG(pp_import_expect_kw_export, "expected `export` in pp_import.", "", - Level::kError) -DIAG(pp_import_expect_kw_import, "expected `import` in pp_import.", "", - Level::kError) -DIAG(pp_import_expect_semi, "expected `;` in pp_import.", "", Level::kError) -DIAG(va_opt_replacement_expect_kw___va_opt__, - "expected `__va_opt__` in va_opt_replacement.", "", Level::kError) -DIAG(va_opt_replacement_expect_l_paren, "expected `(` in va_opt_replacement.", - "", Level::kError) -DIAG(va_opt_replacement_expect_r_paren, "expected `)` in va_opt_replacement.", - "", Level::kError) -DIAG(preprocessing_token_expect_kw_import, - "expected `import` in preprocessing_token.", "", Level::kError) -DIAG(preprocessing_token_expect_kw_module, - "expected `module` in preprocessing_token.", "", Level::kError) -DIAG(preprocessing_token_expect_kw_export, - "expected `export` in preprocessing_token.", "", Level::kError) -DIAG(preprocessing_token_expect_identifier, - "expected `identifier` in preprocessing_token.", "", Level::kError) -DIAG(token_expect_identifier, "expected `identifier` in token.", "", - Level::kError) -DIAG(header_name_expect_less, "expected `<` in header_name.", "", Level::kError) -DIAG(header_name_expect_greater, "expected `>` in header_name.", "", - Level::kError) -DIAG(pp_number_expect_period, "expected `.` in pp_number.", "", Level::kError) -DIAG(preprocessing_operator_expect_hash, - "expected `#` in preprocessing_operator.", "", Level::kError) -DIAG(preprocessing_operator_expect_hashhash, - "expected `##` in preprocessing_operator.", "", Level::kError) -DIAG(operator_or_punctuator_expect_l_brace, - "expected `{` in operator_or_punctuator.", "", Level::kError) -DIAG(operator_or_punctuator_expect_r_brace, - "expected `}` in operator_or_punctuator.", "", Level::kError) -DIAG(operator_or_punctuator_expect_l_square, - "expected `[` in operator_or_punctuator.", "", Level::kError) -DIAG(operator_or_punctuator_expect_r_square, - "expected `]` in operator_or_punctuator.", "", Level::kError) -DIAG(operator_or_punctuator_expect_l_paren, - "expected `(` in operator_or_punctuator.", "", Level::kError) -DIAG(operator_or_punctuator_expect_r_paren, - "expected `)` in operator_or_punctuator.", "", Level::kError) -DIAG(fractional_constant_expect_period, "expected `.` in fractional_constant.", - "", Level::kError) -DIAG(hexadecimal_fractional_constant_expect_period, - "expected `.` in hexadecimal_fractional_constant.", "", Level::kError) -DIAG(sign_expect_plus, "expected `+` in sign.", "", Level::kError) -DIAG(sign_expect_minus, "expected `-` in sign.", "", Level::kError) -DIAG(boolean_literal_expect_kw_false, "expected `false` in boolean_literal.", - "", Level::kError) -DIAG(boolean_literal_expect_kw_true, "expected `true` in boolean_literal.", "", - Level::kError) -DIAG(pointer_literal_expect_kw_nullptr, - "expected `nullptr` in pointer_literal.", "", Level::kError) -DIAG(ud_suffix_expect_identifier, "expected `identifier` in ud_suffix.", "", - Level::kError) diff --git a/include/lex/base.h b/include/lex/base.h index a6874b8..fe0fe3d 100644 --- a/include/lex/base.h +++ b/include/lex/base.h @@ -151,10 +151,22 @@ class Base { return {c, sz}; } - static inline void horzws_skipping(ptr_type& ptr) { + static inline bool horzws_skipping(ptr_type& ptr) { if (basic::str::ascii::is::HorzWs(*ptr)) { ptr.horzws_skipping(); } + if (*ptr == '\\') { + if (!basic::str::ascii::is::VertWs(*(ptr + 1))) { + diag(ptr, ptr + 1, + diag::DiagKind::expected_vertws_after_slash_in_preprocessing); + throw basic::vfile::Eof(); + return false; + } + ++ptr; + ++ptr; + horzws_skipping(ptr); + } + return true; } static inline CharSize advance(ptr_type& ptr) { uint32_t sz = 0; diff --git a/include/lex/pp.h b/include/lex/pp.h index 5341558..8bb78e3 100644 --- a/include/lex/pp.h +++ b/include/lex/pp.h @@ -48,7 +48,6 @@ class Preprocessing : public Base { if (basic::str::ascii::is::Ws(*ptr)) { do { - this->inc(1); ++ptr; } while (basic::str::ascii::is::Ws(*ptr)); } @@ -56,14 +55,30 @@ class Preprocessing : public Base { auto first_ptr = ptr; if (*ptr == '#') { // control-line ++ptr; - auto tmp_ptr = ptr; - auto tmp_tok = tok; - if (lex_control_line(first_ptr, tmp_ptr, tmp_tok)) { - ptr = tmp_ptr; - tok = tmp_tok; - return; + { + auto tmp_ptr = ptr; + auto tmp_tok = tok; + if (lex_control_line(first_ptr, tmp_ptr, tmp_tok)) { + ptr = tmp_ptr; + tok = tmp_tok; + return; + } + } + { + auto tmp_ptr = ptr; + auto tmp_tok = tok; + if (lex_if_section(first_ptr, tmp_ptr, tmp_tok)) { + ptr = tmp_ptr; + tok = tmp_tok; + return; + } } - } else { + diag(first_ptr, ptr, + diag::DiagKind::expected_directive_command_after_hash); + tok.kind(token::details::TokenKind::eof); + return; + } + { if (basic::str::ascii::is::NonDigit(*first_ptr)) { auto tmp_ptr = ptr; auto tmp_tok = tok; @@ -418,20 +433,9 @@ class Preprocessing : public Base { } horzws_skipping(tmp_ptr2); - advance(tmp_ptr2); + ++tmp_ptr2; horzws_skipping(tmp_ptr2); - if (*tmp_ptr2 == '\\') { - if (!basic::str::ascii::is::VertWs(*(tmp_ptr2 + 1))) { - diag(tmp_ptr2, tmp_ptr2 + 1, - diag::DiagKind:: - expected_vertws_after_slash_in_preprocessing); - tok.kind(token::details::TokenKind::eof); - return true; - } - ++tmp_ptr2; - ++tmp_ptr2; - horzws_skipping(tmp_ptr2); - } + tmp_first_ptr = tmp_ptr2; ++tmp_ptr2; replacement_tokens = @@ -486,7 +490,7 @@ class Preprocessing : public Base { case token::details::TokenKind::kw_pragma: default: - unreachable(kTag); + return false; } ptr = tmp_ptr; } @@ -496,7 +500,91 @@ class Preprocessing : public Base { } return false; } - void command() {} + + // conditional-expression: + // logical_or_expression + // logical_or_expression, `?`, expression, `:`, assignment_expression + bool lex_conditional_expression(const typename base::ptr_type& first_ptr, + typename base::ptr_type& ptr, + token::Token& tok); + // constant-expression: + // conditional-expression + bool lex_constant_expression(const typename base::ptr_type& first_ptr, + typename base::ptr_type& ptr, + token::Token& tok) { + return lex_conditional_expression(first_ptr, ptr, tok); + } + + // if-group: + // # if constant-expression new-line group[opt] + // # ifdef identifier new-line group[opt] + // # ifndef identifier new-line group[opt] + bool lex_if_group(const typename base::ptr_type& first_ptr, + typename base::ptr_type& ptr, token::Token& tok) { + auto tmp_first_ptr = first_ptr; + auto tmp_ptr = ptr; + if (*tmp_first_ptr != '#') { + return false; + } + ++tmp_first_ptr; + ++tmp_ptr; + token::Token kw_token; + if (this->lex_identifier(tmp_first_ptr, tmp_ptr, kw_token)) { + switch (kw_token.kind()) { + + case token::details::TokenKind::kw_if: { + horzws_skipping(tmp_ptr); + tmp_first_ptr = tmp_ptr; + ++tmp_ptr; + token::Token constant_expr; + if (!lex_constant_expression(tmp_first_ptr, tmp_ptr, constant_expr)) { + diag(tmp_first_ptr, tmp_ptr, + diag::DiagKind:: + expected_constant_expression_after_if_directive); + throw basic::vfile::Eof(); + return false; + } + horzws_skipping(tmp_ptr); + if (*tmp_ptr != '\n') { + diag(tmp_first_ptr, tmp_ptr, + diag::DiagKind:: + expected_new_line_after_if_constant_expression_directive); + throw basic::vfile::Eof(); + return false; + } + ++tmp_ptr; + horzws_skipping(tmp_ptr); + + unreachable(kTag); + + break; + } + case token::details::TokenKind::kw_ifdef: { + break; + } + case token::details::TokenKind::kw_ifndef: { + break; + } + default: { + return false; + } + } + } + + return false; + } + + // if-section: + // if_group, elif_groups[opt], else_group[opt], endif_line + bool lex_if_section(const typename base::ptr_type& first_ptr, + typename base::ptr_type& ptr, token::Token& tok) { + + if (!lex_if_group(first_ptr, ptr, tok)) { + return false; + } + + return false; + } }; // namespace lps::lexer::details } // namespace lps::lexer::details::pp diff --git a/include/parse_function/.gitignore b/include/parse_function/.gitignore index 85d0fae..e50480f 100644 --- a/include/parse_function/.gitignore +++ b/include/parse_function/.gitignore @@ -1,3 +1,2 @@ -function_impl.h function.h kinds.def diff --git a/include/parse_function/parallel_function_impl.h b/include/parse_function/parallel_function_impl.h index 5190cc7..70c7c5a 100644 --- a/include/parse_function/parallel_function_impl.h +++ b/include/parse_function/parallel_function_impl.h @@ -24,14 +24,14 @@ #include "basic/tui.h" #include "diag.h" -#include "parse_function/parallel_serial_function.h" +#include "parse_function/parallel_serial_recursive_function.h" #include "token.h" namespace lps::parser::details { -template +template ParseFunctionOutputs -ParallelParseFunctions::operator()() { +ParallelParseFunctions::operator()() { lps_assert("ParallelParseFunctions", this->ok_to_try()); auto output = base::operator()(); if (!this->valid()) { @@ -59,7 +59,7 @@ ParallelParseFunctions::operator()() { auto local_output = func(); } if (local_output.work_) { // only allow one of them work - if (local_output.len() > max_len_match_output.len()) { + if (local_output.len_ > max_len_match_output.len_) { max_len_match_output = std::move(local_output); max_len_match_idx = running_sub_func_idx; if (!this->valid( @@ -80,16 +80,15 @@ ParallelParseFunctions::operator()() { parse_functions_); if (max_len_match_output.work_) { this->executed_mask_.set(max_len_match_idx); - output.node_ = std::move(max_len_match_output.node_); diag::infos() << basic::str::from( - std::string(this->calling_depth(), '>'), " ", "ParallelFunc ", + std::string(this->calling_depth(), '>'), " ", this->kName_, basic::tui::color::Shell::colorize( basic::str::from(" ok, matched idx = ", max_len_match_idx, ".\n"), basic::tui::color::Shell::fgreen())); } else { this->executed_mask_.set(); diag::infos() << basic::str::from( - std::string(this->calling_depth(), '>'), " ", "ParallelFunc ", + std::string(this->calling_depth(), '>'), " ", this->kName_, basic::tui::color::Shell::colorize(basic::str::from(" failed\n"), basic::tui::color::Shell::fred())); } @@ -97,4 +96,18 @@ ParallelParseFunctions::operator()() { return output; } +template +void ParallelParseFunctions::reset() { + base::reset(); + std::apply( + [](ParseFuncs&... funcs) { + ( + [](auto& func) { + func.reset(); + }(funcs), + ...); + }, + parse_functions_); +} + } // namespace lps::parser::details diff --git a/include/parse_function/parallel_serial_function.h b/include/parse_function/parallel_serial_function.h deleted file mode 100644 index 8cdd274..0000000 --- a/include/parse_function/parallel_serial_function.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -* MIT License -* Copyright (c) 2023 mxlol233 (mxlol233@outlook.com) - -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: - -* The above copyright notice and this permission notice shall be included in all -* copies or substantial portions of the Software. - -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -*LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -*/ - -#pragma once - -#include -#include -#include "basic/exception.h" -#include "parser.h" - -namespace lps::parser::details { - -template -class ParallelParseFunctions : public ParseFunction { - - public: - using base = ParseFunction; - ParallelParseFunctions(const ParallelParseFunctions& other) = default; - explicit ParallelParseFunctions(const ParseFunctionInputs& param, - ParseFuncs&&... funcs) - : base(param), parse_functions_(funcs...) {} - ParseFunctionOutputs operator()() override; - - protected: - std::tuple parse_functions_; -}; - -template -class SerialParseFunctions : public ParseFunction<1> { - - public: - using base = ParseFunction<1>; - SerialParseFunctions(const SerialParseFunctions& other) = default; - explicit SerialParseFunctions(const ParseFunctionInputs& param, - ParseFuncs&&... funcs) - : base(param), parse_functions_(funcs...) {} - ParseFunctionOutputs operator()() override; - - protected: - std::tuple parse_functions_; -}; -} // namespace lps::parser::details diff --git a/include/parse_function/parallel_serial_recursive_function.h b/include/parse_function/parallel_serial_recursive_function.h new file mode 100644 index 0000000..d3eae91 --- /dev/null +++ b/include/parse_function/parallel_serial_recursive_function.h @@ -0,0 +1,93 @@ +/* +* MIT License +* Copyright (c) 2023 mxlol233 (mxlol233@outlook.com) + +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: + +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. + +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +*LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +*/ + +#pragma once + +#include +#include +#include "basic/exception.h" +#include "parser.h" + +namespace lps::parser::details { + +template +class ParallelParseFunctions : public ParseFunction { + + public: + using base = ParseFunction; + explicit ParallelParseFunctions(Context* context, const char* kName, + const ParseFunctionInputs& param, + ParseFuncs&&... funcs) + : base(context, kName, param), parse_functions_(funcs...) {} + virtual ~ParallelParseFunctions() = default; + ParseFunctionOutputs operator()(); + void reset() override; + ParseFunctionKind kind() override { return Kind; } + + protected: + std::tuple parse_functions_; +}; + +template +class SerialParseFunctions : public ParseFunction<1> { + + public: + using base = ParseFunction<1>; + explicit SerialParseFunctions(Context* context, const char* kName, + const ParseFunctionInputs& param, + ParseFuncs&&... funcs) + : base(context, kName, param), parse_functions_(funcs...) {} + virtual ~SerialParseFunctions() = default; + ParseFunctionOutputs operator()(); + void reset() override; + ParseFunctionKind kind() override { return Kind; } + + protected: + std::tuple parse_functions_; +}; + +template +class RecursiveParseFunctions : public ParseFunction<1> { + + public: + static constexpr int kNFuncs = sizeof...(ParseFuncs); + using working_list_type = basic::Bitset; + using working_list_stack_type = std::stack; + using base = ParseFunction<1>; + explicit RecursiveParseFunctions(Context* context, const char* kName, + const ParseFunctionInputs& param, + ParseFuncs&&... funcs) + : base(context, kName, param), parse_functions_(funcs...) {} + virtual ~RecursiveParseFunctions() = default; + ParseFunctionOutputs operator()(); + ParseFunctionKind kind() override { return Kind; } + + protected: + void execute(ParseFunctionOutputs&, working_list_type& executed_mask); + bool regret(const working_list_type& executed_mask); + void reset() override; + + std::tuple parse_functions_; + working_list_stack_type working_list_stack_; +}; +} // namespace lps::parser::details diff --git a/include/parse_function/recursive_function_impl.h b/include/parse_function/recursive_function_impl.h new file mode 100644 index 0000000..d131ea4 --- /dev/null +++ b/include/parse_function/recursive_function_impl.h @@ -0,0 +1,165 @@ +/* +* MIT License +* Copyright (c) 2023 mxlol233 (mxlol233@outlook.com) + +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: + +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. + +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +*LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +*/ +#pragma once + +#include +#include "diag.h" +#include "parse_function/parallel_serial_recursive_function.h" +#include "parser.h" +#include "token.h" + +namespace lps::parser::details { + +template +ParseFunctionOutputs +RecursiveParseFunctions::operator()() { + lps_assert("RecursiveParseFunctions", this->ok_to_try()); + auto output = base::operator()(); + this->executed_mask_.set(); + if (!this->valid()) { + return output; + } + uint32_t recursive_depth = 0; + working_list_type executed_mask; + auto tmp_output = output; + + Line::segments_type saved_lines; + + do { + + execute(tmp_output, executed_mask); + + if (!tmp_output.work_) { + if (recursive_depth > 0) { + lps_assert("RecursiveParseFunctions", !working_list_stack_.empty()); + executed_mask = working_list_stack_.top(); + if (!regret(executed_mask)) { + break; + } + working_list_stack_.pop(); + --recursive_depth; + continue; + } + break; + } + working_list_stack_.push(executed_mask); + executed_mask.reset(); + ++recursive_depth; + output = tmp_output; + saved_lines.append(tmp_output.line_); + } while (true); + + if (output.work_) { + const auto* p_start = &context_->token_lists().at(this->cur_token()); + const auto* p_end = &context_->token_lists().at(output.cur_token_); + Line line{ + p_start, + p_end, + this->kind(), + token::details::TokenKind::unknown, + token::TokenLists::len(p_start, p_end), + this->calling_depth(), + std::move(saved_lines), + }; + output.line_ = context_->paint(line); + } + return output; +} +template +bool RecursiveParseFunctions::regret( + const working_list_type& executed_mask) { + return !executed_mask.all(); +} + +template +void RecursiveParseFunctions::reset() { + std::apply( + [](ParseFuncs&... funcs) { + ( + [](auto& func) { + func.reset(); + }(funcs), + ...); + }, + parse_functions_); +} + +template +void RecursiveParseFunctions::execute( + ParseFunctionOutputs& output, working_list_type& executed_mask) { + bool flg_continue = true; + uint32_t running_sub_func_idx = 0; + ParseFunctionOutputs max_len_match_output; + max_len_match_output.last_token_ = this->last_token(); + max_len_match_output.cur_token_ = this->cur_token(); + uint32_t max_len_match_idx = -1; + + reset(); + + std::apply( + [this, &flg_continue, &output, &max_len_match_output, + &running_sub_func_idx, &max_len_match_idx, + &executed_mask](ParseFuncs&... funcs) { + ( + [this, &flg_continue, &output, &max_len_match_output, + &running_sub_func_idx, &max_len_match_idx, + &executed_mask](auto& func) { + if (!executed_mask.at(running_sub_func_idx)) { + func.last_token(output.last_token_); + func.cur_token(output.cur_token_); + auto local_output = func(); + while (!local_output.work_ && func.ok_to_try()) { + auto local_output = func(); + } + if (local_output.work_) { // only allow one of them work + if (local_output.len_ > max_len_match_output.len_) { + max_len_match_output = std::move(local_output); + max_len_match_idx = running_sub_func_idx; + if (!this->valid( + local_output.cur_token_)) { // no more chance + executed_mask.set(); + return; + } + } + } else { + output.concat(std::move(local_output), false); + executed_mask.set(running_sub_func_idx); + } + running_sub_func_idx++; + } + }(funcs), + ...); + }, + parse_functions_); + if (max_len_match_output.work_) { + diag::infos() << basic::str::from( + std::string(this->calling_depth(), '>'), " ", this->kName_, + basic::tui::color::Shell::colorize( + basic::str::from(" ok, matched idx = ", max_len_match_idx, ".\n"), + basic::tui::color::Shell::fgreen())); + } else { + } + output.concat(std::move(max_len_match_output), false); +} + +} // namespace lps::parser::details diff --git a/include/parse_function/serial_function_impl.h b/include/parse_function/serial_function_impl.h index 1c4a756..5d281b5 100644 --- a/include/parse_function/serial_function_impl.h +++ b/include/parse_function/serial_function_impl.h @@ -24,14 +24,14 @@ #include #include "diag.h" -#include "parse_function/parallel_serial_function.h" +#include "parse_function/parallel_serial_recursive_function.h" #include "parser.h" #include "token.h" namespace lps::parser::details { -template -ParseFunctionOutputs SerialParseFunctions::operator()() { +template +ParseFunctionOutputs SerialParseFunctions::operator()() { lps_assert("SerialParseFunctions", this->ok_to_try()); this->executed_mask_.set(); auto output = base::operator()(); @@ -53,76 +53,67 @@ ParseFunctionOutputs SerialParseFunctions::operator()() { }, parse_functions_); + Line::segments_type saved_lines(running_sub_func_size, nullptr); + std::stack path_stack; path_stack.push(output); - Tree::Node node; + while (flg_continue) { std::apply( - [this, &running_sub_func_size, &node, &path_stack, &flg_continue, - &running_sub_func_stack_top_idx](ParseFuncs&... funcs) { + [this, &running_sub_func_size, &path_stack, &flg_continue, + &running_sub_func_stack_top_idx, &saved_lines](ParseFuncs&... funcs) { bool flg_not_continue = false; uint32_t running_sub_func_idx = 0; ( - [this, &running_sub_func_size, &node, &path_stack, - &flg_not_continue, &flg_continue, &running_sub_func_idx, - &running_sub_func_stack_top_idx](auto& func) { + [this, &running_sub_func_size, &path_stack, &flg_not_continue, + &flg_continue, &running_sub_func_idx, + &running_sub_func_stack_top_idx, &saved_lines](auto& func) { if (flg_not_continue || !flg_continue) { return; } if (running_sub_func_idx++ < running_sub_func_stack_top_idx) { return; } - auto make_try_again = - [&](basic::Vector<4, diag::DiagInputs>&& diag_inputs) { - if ((running_sub_func_idx - 1) == 0) { - flg_continue = false; - return; - } - flg_not_continue = true; - running_sub_func_stack_top_idx = - (running_sub_func_idx - 1) - 1; - func.reset(); - auto tmp_output(path_stack.top()); - tmp_output.work_ = false; - lps_assert("make_try_again", path_stack.size() > 0); - - path_stack.pop(); - - path_stack.top().concat(std::move(tmp_output), false); - - if (!diag_inputs.empty()) { - decltype(tmp_output) tmp_output0; - tmp_output0.diag_inputs_ = std::move(diag_inputs); - path_stack.top().concat(std::move(tmp_output0), false); - } - return; - }; + auto make_try_again = [&]() { + if ((running_sub_func_idx - 1) == 0) { + flg_continue = false; + return; + } + flg_not_continue = true; + running_sub_func_stack_top_idx = + (running_sub_func_idx - 1) - 1; + func.reset(); + auto tmp_output(path_stack.top()); + tmp_output.work_ = false; + lps_assert("make_try_again", path_stack.size() > 0); + + path_stack.pop(); + + path_stack.top().concat(std::move(tmp_output), false); + return; + }; if (flg_continue) { func.last_token(path_stack.top().last_token_); func.cur_token(path_stack.top().cur_token_); if (!func.ok_to_try() || (!func.valid() && !func.opt())) { - make_try_again(basic::Vector<4, diag::DiagInputs>()); + make_try_again(); return; } auto local_output = func(); if (!local_output.work_ && !func.opt()) { - make_try_again(std::move(local_output.diag_inputs_)); + make_try_again(); return; } + if (local_output.work_) { + lps_assert(this->kName_, local_output.line_ != nullptr); + saved_lines[running_sub_func_idx - 1] = local_output.line_; + } auto output(path_stack.top()); - auto* node_ptr = Tree::instance().append(local_output.node_); - node_ptr->kind_ = func.kKind; - if (func.kKind == ParseFunctionKind::kExpectedToken) { - node_ptr->expected_token_kind_ = func.expected_token_kind(); - } output.concat(std::move(local_output), func.opt()); path_stack.push(output); - if (output.work_) { - node.sub_nodes_.append(node_ptr); - } if ((running_sub_func_idx == running_sub_func_size && output.work_) || !func.valid()) { @@ -135,20 +126,47 @@ ParseFunctionOutputs SerialParseFunctions::operator()() { }, parse_functions_); } - lps_assert("serial_function_impl", path_stack.size() > 0); + lps_assert(this->kName_, path_stack.size() > 0); if (path_stack.top().work_) { - path_stack.top().node_ = std::move(node); + const auto* p_start = &context_->token_lists().at(this->cur_token()); + const auto* p_end = + &context_->token_lists().at(path_stack.top().cur_token_); + Line line{ + p_start, + p_end, + this->kind(), + token::details::TokenKind::unknown, + token::TokenLists::len(p_start, p_end), + this->calling_depth(), + std::move(saved_lines), + }; + path_stack.top().line_ = context_->paint(line); + diag::infos() << basic::str::from( - std::string(this->calling_depth(), '>'), " ", "_SerialFunc ", + std::string(this->calling_depth(), '>'), " ", this->kName_, basic::tui::color::Shell::colorize(basic::str::from(" ok.\n"), basic::tui::color::Shell::fgreen())); } else { diag::infos() << basic::str::from( - std::string(this->calling_depth(), '>'), " ", "_SerialFunc ", + std::string(this->calling_depth(), '>'), " ", this->kName_, basic::tui::color::Shell::colorize(basic::str::from(" failed\n"), basic::tui::color::Shell::fred())); } return path_stack.top(); } +template +void SerialParseFunctions::reset() { + base::reset(); + std::apply( + [](ParseFuncs&... funcs) { + ( + [](auto& func) { + func.reset(); + }(funcs), + ...); + }, + parse_functions_); +} + } // namespace lps::parser::details diff --git a/include/parser.h b/include/parser.h index b01b7c9..695e295 100644 --- a/include/parser.h +++ b/include/parser.h @@ -25,7 +25,10 @@ #include #include +#include +#include #include +#include "ast.h" #include "basic/bitset.h" #include "basic/exception.h" #include "basic/mem.h" @@ -37,84 +40,110 @@ namespace lps::parser { namespace details { +class Context { + public: + friend class ContextTrait; + static constexpr basic::mem::TraceTag::tag_type kTag = "Context"; + using executed_func_type = std::function; + void with(const executed_func_type& func) { func(this); } + token::TokenLists& token_lists() { return token_lists_; } + const token::Token& start_token() const { return start_token_; } + void start_token(const token::Token& token) { start_token_ = token; } + size_t len_from_start(const token::Token& cur_token) { + return token_lists_.len(start_token_, cur_token); + } + const Line* paint(const Line& the_line) { + if (path_.contains(the_line.start_)) { + for (auto& line : path_[the_line.start_]) { + if (line == the_line) { + return &line; + } + } + } + path_[the_line.start_].push_back(the_line); + lps_assert(kTag, path_[the_line.start_].back().len_ > 0); + return &path_[the_line.start_].back(); + } -enum class ParseFunctionKind : uint16_t { - kUnknown = 0, - kExpectedToken = 1, -#define PARSE_FUNC(FUNC) FUNC, -#include "parse_function/kinds.def" - kNum, -}; - -namespace kind { + Line longest_line(const auto& start) { + size_t max_l = 0; + const auto* p_start = &token_lists_.at(start); + auto cmp = [](const Line& l, size_t b) { + return l.len_ > b; + }; + return find_line(p_start, max_l); + } -static constexpr std::array, - static_cast(ParseFunctionKind::kNum)> - kLists = {{ -#define PARSE_FUNC(X) {ParseFunctionKind::X, #X}, -#include "parse_function/kinds.def" - }}; + Line longest_line_with_kind(const auto& start, ParseFunctionKind kind) { + size_t max_l = 0; + const auto* p_start = &token_lists_.at(start); + auto cmp = [](const Line& l, size_t b, ParseFunctionKind kind) { + return l.len_ > b && l.kind_ == kind; + }; + return find_line(p_start, max_l, kind); + } -static constexpr lps::basic::map::Map( - ParseFunctionKind::kNum)> - kMap{kLists}; + Line shortest_line(const token::Token& start) { + size_t min_l = std::numeric_limits::max(); + const auto* p_start = &token_lists_.at(start); + auto cmp = [](const Line& l, size_t b) { + return l.len_ < b; + }; + return find_line(p_start, min_l); + } -} // namespace kind + Tree l2t(const Line& root_line); -inline std::ostream& operator<<(std::ostream& s, ParseFunctionKind kind) { - s << kind::kMap.at(kind); - return s; -} + private: + Line shortest_line(const token::Token* p_start, size_t min_l) { + return find_line<[](const Line& l, size_t b) { + return l.len_ < b; + }>(p_start, min_l); + } -class Tree { - public: - static Tree& instance() { - static Tree tree; - return tree; + template + Line find_line(const token::archived_type* p_start, size_t the_l, + Args... args) { + Line the_line; + lps_assert(kTag, path_.contains(p_start)); + for (const auto& line : path_[p_start]) { + if (F(line, the_l, args...)) { + the_line = line; + } + } + return the_line; } - struct Node { - using sub_nodes_type = basic::Vector<4, Node*>; - using token_pts_type = basic::Vector<8, token::archived_type*>; - ParseFunctionKind kind_{ParseFunctionKind::kUnknown}; - sub_nodes_type sub_nodes_; - token_pts_type token_pts_; - token::details::TokenKind expected_token_kind_{ - token::details::TokenKind::unknown}; - }; + token::TokenLists token_lists_; + token::Token start_token_; + std::unordered_map> path_; +}; - Node* append(const Node& node) { - nodes_.append(node); - return &nodes_.back(); - } - [[nodiscard]] size_t size() const { return nodes_.size(); } +class ContextTrait { + public: + explicit ContextTrait(Context* context) : context_(context) {} + Context* context() { return context_; } - private: - basic::Vector<4, Node> nodes_; + protected: + Context* context_; }; struct ParseFunctionOutputs { - using diag_input_type = basic::Vector<4, diag::DiagInputs>; - using token_list_infos_type = - basic::Vector<16, const token::TokenLists::ele_type*>; explicit ParseFunctionOutputs() = default; -#define SET_MOVE(A, B) \ - (A)->work_ = (B).work_; \ - (A)->last_token_ = (B).last_token_; \ - (A)->cur_token_ = (B).cur_token_; \ - (A)->diag_inputs_ = std::move((B).diag_inputs_); \ - (A)->node_ = std::move((B).node_); \ - (A)->token_list_infos_ = std::move((B).token_list_infos_); - -#define SET(A, B) \ - (A)->work_ = (B).work_; \ - (A)->last_token_ = (B).last_token_; \ - (A)->cur_token_ = (B).cur_token_; \ - (A)->diag_inputs_ = (B).diag_inputs_; \ - (A)->node_ = (B).node_; \ - (A)->token_list_infos_ = (B).token_list_infos_; +#define SET_MOVE(A, B) \ + (A)->work_ = (B).work_; \ + (A)->last_token_ = (B).last_token_; \ + (A)->cur_token_ = (B).cur_token_; \ + (A)->line_ = (B).line_; \ + (A)->len_ = (B).len_; + +#define SET(A, B) \ + (A)->work_ = (B).work_; \ + (A)->last_token_ = (B).last_token_; \ + (A)->cur_token_ = (B).cur_token_; \ + (A)->line_ = (B).line_; \ + (A)->len_ = (B).len_; ParseFunctionOutputs(const ParseFunctionOutputs& other) { SET(this, other); @@ -137,38 +166,24 @@ struct ParseFunctionOutputs { #undef SET_MOVE #undef SET - [[nodiscard]] size_t len() const { - return token_list_infos_.size(); - } - - void diag_record(diag::DiagInputs&& a) { - diag_inputs_.append(std::move(a)); - } - void concat(ParseFunctionOutputs&& other, bool opt = true) { if (!opt) { - for (auto& a : other.diag_inputs_) { - typename decltype(diag_inputs_)::ele_type b(std::move(a)); - this->diag_inputs_.append(std::move(b)); - } this->work_ = other.work_; } if (other.work_) { this->last_token_ = other.last_token_; this->cur_token_ = other.cur_token_; this->work_ = other.work_; - for (auto& a : other.token_list_infos_) { - this->token_list_infos_.append(a); - } + len_ += other.len_; + this->line_ = other.line_; } } bool work_{false}; token::Token last_token_; token::Token cur_token_; - diag_input_type diag_inputs_; - token_list_infos_type token_list_infos_; - Tree::Node node_; + const Line* line_{nullptr}; + size_t len_{0}; }; struct ParseFunctionInputs { @@ -218,35 +233,51 @@ struct ParseFunctionInputs { }; template -class ParseFunction { +class ParseFunction : public ContextTrait { public: using type = ParseFunction; + using context_trait_type = ContextTrait; using output_type = ParseFunctionOutputs; using custom_func_type = std::function; using bitset_type = basic::Bitset; static constexpr size_t kNumberOfElements = NumElements; - const ParseFunctionKind kKind = ParseFunctionKind::kExpectedToken; + virtual ParseFunctionKind kind() { + static constexpr ParseFunctionKind kKind = + ParseFunctionKind::kExpectedToken; + return kKind; + } + virtual ~ParseFunction() = default; template - explicit ParseFunction(Params... params) : params_(params...) {} + explicit ParseFunction(Context* context, const char* kName, Params... params) + : context_trait_type(context), kName_(kName), params_(params...) {} template - explicit ParseFunction(custom_func_type func, + explicit ParseFunction(Context* context, const char* kName, + custom_func_type func, token::details::TokenKind expected_token_kind, Params... params) - : custom_func_(func), + : context_trait_type(context), + kName_(kName), + custom_func_(func), params_(params...), expected_token_kind_(expected_token_kind) {} - explicit ParseFunction(ParseFunctionInputs param, + explicit ParseFunction(Context* context, const char* kName, + ParseFunctionInputs param, token::details::TokenKind expected_token_kind, custom_func_type func) - : params_(std::move(param)), + : context_trait_type(context), + kName_(kName), + params_(std::move(param)), custom_func_(func), expected_token_kind_(expected_token_kind) {} - explicit ParseFunction(const ParseFunctionInputs& param) : params_(param) {} - explicit ParseFunction(ParseFunctionInputs&& param) - : params_(std::move(param)) {} - - virtual output_type operator()() { + explicit ParseFunction(Context* context, const char* kName, + const ParseFunctionInputs& param) + : context_trait_type(context), kName_(kName), params_(param) {} + explicit ParseFunction(Context* context, const char* kName, + ParseFunctionInputs&& param) + : context_trait_type(context), kName_(kName), params_(std::move(param)) {} + + output_type operator()() { if (custom_func_) { return custom_func_(this); } @@ -262,20 +293,10 @@ class ParseFunction { [[nodiscard]] token::Token last_token() const { return params_.last_token_; } [[nodiscard]] token::Token cur_token() const { return params_.cur_token_; } - [[nodiscard]] inline size_t len() const { - return src::Manager::instance().size(params_.cur_token_.file_id()); - } - - [[nodiscard]] inline const char* eof() const { - auto content = - src::Manager::instance().ref_of_char_file(params_.cur_token_.file_id()); - return content.data() + len(); - } [[nodiscard]] inline bool valid() const { return valid(params_.cur_token_); } [[nodiscard]] inline bool valid(const token::Token& tok) const { - return token::TokenLists::instance().next(tok).kind() != - token::details::TokenKind::eof; + return tok.kind() != token::details::TokenKind::eof; } void opt(bool opt) { params_.opt_ = opt; } @@ -287,10 +308,14 @@ class ParseFunction { void calling_depth(size_t depth) { params_.calling_depth_ = depth; } [[nodiscard]] bitset_type executed_mask() const { return executed_mask_; } void executed_mask(const bitset_type& mask) { executed_mask_ = mask; } - void reset() { executed_mask_.reset(); } - bool ok_to_try() { return !executed_mask_.all(); } + virtual void reset() { executed_mask_.reset(); } + bool ok_to_try() { + auto status = executed_mask_.all(); + return !status; + } - static type create_single_token_check(bool opt, size_t calling_depth, + static type create_single_token_check(Context* context, bool opt, + size_t calling_depth, token::details::TokenKind token_kind, diag::DiagKind diag_kind) { typename type::custom_func_type z([token_kind, diag_kind](type* func) { @@ -303,9 +328,9 @@ class ParseFunction { } token::Token next_tok; bool flg_use_lexer = true; - if (token::TokenLists::instance().has(output.cur_token_)) { + if (func->context()->token_lists().has(output.cur_token_)) { const auto* tok_ptr = - token::TokenLists::instance().at(output.cur_token_).next(); + func->context()->token_lists().at(output.cur_token_).next(); if (tok_ptr) { flg_use_lexer = false; next_tok = *tok_ptr; @@ -315,11 +340,14 @@ class ParseFunction { lexer::Lexer lexer(output.cur_token_.next_visitor().second, output.cur_token_.next_visitor().first); lexer.lex(next_tok); + if (next_tok.kind() == token::details::TokenKind::eof) { + next_tok.file_id(output.cur_token_.file_id()); + } lps_assert("create_single_token_check", next_tok.kind() != token::details::TokenKind::unknown); - token::TokenLists::instance().append( + func->context()->token_lists().append( next_tok, token::TokenLists::Info::create(output.cur_token_)); } @@ -328,8 +356,7 @@ class ParseFunction { if (output.cur_token_.kind() != token_kind) { if (!func->opt()) { - output.diag_record( - diag::record(output.cur_token_, diag_kind, {output.last_token_})); + //todo(@mxlol233): add diag. } output.work_ = false; return output; @@ -339,21 +366,33 @@ class ParseFunction { output.last_token_ = output.cur_token_; output.work_ = true; output.cur_token_ = next_tok; - if (next_tok.kind() != token::details::TokenKind::unknown) { - output.token_list_infos_.append( - &(token::TokenLists::instance().at(next_tok))); + ++output.len_; + { + const auto* p_start = + &func->context()->token_lists().at(output.last_token_); + const auto* p_end = &func->context()->token_lists().at(next_tok); + Line line{p_start, + p_end, + ParseFunctionKind::kExpectedToken, + token_kind, + token::TokenLists::len(p_start, p_end), + func->calling_depth(), + Line::segments_type()}; + output.line_ = func->context()->paint(line); } } return output; }); - return type(z, token_kind, opt, calling_depth); + return type(context, token::details::kMap.at(token_kind), z, token_kind, + opt, calling_depth); } protected: ParseFunctionInputs params_; custom_func_type custom_func_{nullptr}; bitset_type executed_mask_; + const char* kName_; private: token::details::TokenKind expected_token_kind_{ diff --git a/include/src.h b/include/src.h index d87062f..4d8e03c 100644 --- a/include/src.h +++ b/include/src.h @@ -26,6 +26,7 @@ #include #include #include +#include "ast.h" #include "basic/exception.h" #include "basic/file.h" #include "basic/mem.h" @@ -197,10 +198,12 @@ class TokenLists { }; using ele_type = token::archived_type; - static TokenLists& instance() { - static TokenLists lists; - return lists; - } + + struct SavedStructure { + ele_type token_; + basic::Vector<8, lps::parser::details::ParseFunctionKind> colors_; + }; + bool has(uint32_t file_id, uint64_t offset) const { if (lists_.contains(file_id)) { return lists_.at(file_id).contains(offset); @@ -228,11 +231,15 @@ class TokenLists { auto info = Info::create(tok); return lists_.at(info.file_id_).at(info.offset_); } + const ele_type& at(const Token& tok) const { + lps_assert(kTag, has(tok)); + auto info = Info::create(tok); + return lists_.at(info.file_id_).at(info.offset_); + } const ele_type& last(const Token& tok) const { lps_assert(kTag, has(tok)); - auto info = Info::create(tok); - const auto* ptr = token::TokenLists::instance().at(tok).last(); + const auto* ptr = at(tok).last(); if (!ptr) { static const ele_type kEmptyTok; return kEmptyTok; @@ -242,8 +249,7 @@ class TokenLists { const ele_type& next(const Token& tok) const { lps_assert(kTag, has(tok)); - auto info = Info::create(tok); - const auto* ptr = token::TokenLists::instance().at(tok).next(); + const auto* ptr = at(tok).next(); if (!ptr) { static const ele_type kEmptyTok; return kEmptyTok; @@ -256,6 +262,31 @@ class TokenLists { return has(info); } + size_t len(const Token& start, const Token& end) const { + lps_assert(kTag, has(start) && has(end)); + const Token* t = &start; + int l = 0; + + while (t != nullptr && *t != end) { + auto info = Info::create(*t); + t = at(info).next(); + ++l; + } + lps_assert(kTag, t != nullptr); + return l; + } + + static size_t len(const Token* p_start, const Token* p_end) { + const Token* p = p_start; + size_t l = 0; + while (p != nullptr && p != p_end) { + p = p->next(); + ++l; + } + lps_assert(kTag, p != nullptr); + return l; + } + void append(const Token& tok, Info last_tok_info = {0, 0}) { auto info = Info::create(tok); if (lists_.contains(tok.file_id())) { diff --git a/include/token.h b/include/token.h index 0012eba..840b244 100644 --- a/include/token.h +++ b/include/token.h @@ -241,6 +241,15 @@ struct Token { } next_visitor_{0, 0}; }; +inline bool operator==(const Token& a, const Token& b) { + return (a.file_id() == b.file_id()) && (a.offset() == b.offset()) && + (a.kind() == b.kind()); +} + +inline bool operator!=(const Token& a, const Token& b) { + return !(a == b); +} + inline std::ostream& operator<<(std::ostream& s, const Token& tok) { s << "kind:" << tok.kind(); diff --git a/include/token/kinds.def b/include/token/kinds.def index c1f9992..da86f09 100644 --- a/include/token/kinds.def +++ b/include/token/kinds.def @@ -198,6 +198,8 @@ TOK(fractional_constant) // 123.4 TOK(decimal_floating_point_literal) // 123.4e-13 TOK(hexadecimal_floating_point_literal) // 12EF.EEP-1234 TOK(floating_point_literal) // hexadecimal_floating_point_literal or decimal_floating_point_literal +TOK(user_defined_floating_point_literal) +TOK(user_defined_integer_literal) TOK(raw_string) // R"ss(xxx)ss" TOK(pp_number) TOK(pp_token) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4ec20d8..6b2fa8c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,22 +2,20 @@ file(GLOB SRC "./*.cc") list(REMOVE_ITEM SRC "./main.cc") -SET(FUNC_IMPL ${CMAKE_SOURCE_DIR}/include/parse_function/function_impl.h) -SET(FUNC_DEF ${CMAKE_SOURCE_DIR}/include/parse_function/function.h) -SET(FUNC_KIND_DEF ${CMAKE_SOURCE_DIR}/include/parse_function/kinds.def) - add_custom_command( - OUTPUT ${FUNC_IMPL} ${FUNC_DEF} ${FUNC_KIND_DEF} + OUTPUT ${FUNC_IMPL} ${FUNC_DEF} ${FUNC_KIND_DEF} ${FUNC_DIAG_DEF} COMMAND python3 ${CMAKE_SOURCE_DIR}/gram/create_parse_functions.py ${FUNC_IMPL} ${FUNC_DEF} ${FUNC_KIND_DEF} + ${FUNC_DIAG_DEF} DEPENDS ${CMAKE_SOURCE_DIR}/gram/create_parse_functions.py + ${CMAKE_SOURCE_DIR}/gram/config.py VERBATIM) list(APPEND SRC "${CMAKE_CURRENT_BINARY_DIR}/version.cc") -add_library(lps_ STATIC ${SRC} ${FUNC_DEF} ${FUNC_IMPL} ${FUNC_KIND_DEF}) +add_library(lps_ STATIC ${SRC} ${FUNC_DEF} ${FUNC_IMPL} ${FUNC_DIAG_DEF} ${FUNC_KIND_DEF}) install(TARGETS lps_ DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/) diff --git a/src/constant_expression.cc b/src/constant_expression.cc new file mode 100644 index 0000000..bbce3b4 --- /dev/null +++ b/src/constant_expression.cc @@ -0,0 +1,67 @@ +/* +* MIT License +* Copyright (c) 2023 mxlol233 (mxlol233@outlook.com) + +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: + +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. + +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +*LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +*/ + +#include "ast.h" +#include "lex/pp.h" +#include "parse_function/function.h" + +namespace lps::lexer::details::pp { + +bool Preprocessing::lex_conditional_expression( + const typename base::ptr_type& first_ptr, typename base::ptr_type& ptr, + token::Token& tok) { + + { + token::Token next_tok; + lexer::Lexer lexer(first_ptr.file_id(), first_ptr.pos()); + lexer.lex(next_tok); + + parser::details::Context context; + context.with([first_ptr, &next_tok](parser::details::Context* context) { + parser::details::ParseFunctionInputs params; + params.opt_ = false; + if (next_tok.kind() != token::details::TokenKind::unknown) { + context->token_lists().append(next_tok); + context->start_token(next_tok); + params.cur_token_ = next_tok; + params.calling_depth_ = 1; + parser::details::ConditionalExpression func(context, params); + auto output = func(); + int dummy = -1; + } + }); + auto line = context.longest_line_with_kind( + next_tok, parser::details::ParseFunctionKind::kConditionalExpression); + if (line.kind_ != + parser::details::ParseFunctionKind::kConditionalExpression || + line.calling_depth_ != 2) { + return false; + } + auto tree = context.l2t(line); + int dummy = -1; + } + + return false; +} + +} // namespace lps::lexer::details::pp diff --git a/src/parse_function/.gitignore b/src/parse_function/.gitignore new file mode 100644 index 0000000..d796321 --- /dev/null +++ b/src/parse_function/.gitignore @@ -0,0 +1 @@ +function_impl.cc diff --git a/src/parser.cc b/src/parser.cc index f111910..60ee62a 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -25,36 +25,37 @@ #include "basic/exception.h" #include "diag.h" #include "lexer.h" -#include "parse_function/function_impl.h" +#include "parse_function/function.h" #include "token.h" namespace lps::parser { +namespace details { +Tree Context::l2t(const Line& root_line) { + Tree tree(&root_line); + return tree; +} +} // namespace details // cpp grammar: https://timsong-cpp.github.io/cppwp/n4868/gram void Parser::parse(uint32_t file_id) { auto content = src::Manager::instance().ref_of_char_file(file_id); if (!content.empty()) { - details::ParseFunctionInputs params; - params.opt_ = false; - token::Token next_tok; - lexer::Lexer lexer(file_id, 0); - lexer.lex(next_tok); - params.cur_token_ = next_tok; - if (next_tok.kind() != token::details::TokenKind::unknown) { - token::TokenLists::instance().append(next_tok); - } - details::TranslationUnit func(params); - auto output = func(); - for (const auto& a : output.diag_inputs_) { - diag::doing(a.main_token_, a.kind_, a.context_tokens_); - } - if (output.work_) { - for (const auto& node : output.node_.sub_nodes_) { - if (node->kind_ != details::ParseFunctionKind::kUnknown) { - // todo(@mxlol233): handle the recursive tree nodes... - } + details::Context context; + context.with([file_id](details::Context* context) { + details::ParseFunctionInputs params; + params.opt_ = false; + token::Token next_tok; + lexer::Lexer lexer(file_id, 0); + lexer.lex(next_tok); + params.cur_token_ = next_tok; + if (next_tok.kind() != token::details::TokenKind::unknown) { + context->token_lists().append(next_tok); + context->start_token(next_tok); + details::TranslationUnit func(context, params); + auto output = func(); + if (output.work_) {} } - } + }); } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 11e77c6..eef24d7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,18 +1,12 @@ add_subdirectory(basic) -add_executable(test_lexer test_lexer.cc - ${CMAKE_SOURCE_DIR}/src/diag.cc - ${CMAKE_SOURCE_DIR}/src/tu.cc - ${CMAKE_SOURCE_DIR}/src/basic.cc - ${CMAKE_SOURCE_DIR}/src/lexer.cc - ) +add_executable(test_lexer test_lexer.cc) +target_link_libraries(test_lexer lps_) add_executable(test_parser test_parser.cc) target_link_libraries(test_parser lps_) -add_executable(test_parse_function_output test_parse_function_output.cc) -target_link_libraries(test_parse_function_output lps_) enable_testing() diff --git a/tests/basic/CMakeLists.txt b/tests/basic/CMakeLists.txt index 91ed298..0d5035d 100644 --- a/tests/basic/CMakeLists.txt +++ b/tests/basic/CMakeLists.txt @@ -1,10 +1,11 @@ add_executable(test_vec test_vec.cc) -target_link_libraries(test_vec) add_executable(test_str test_str.cc) -target_link_libraries(test_str) + +add_executable(test_bitset test_bitset.cc) enable_testing() add_test(NAME test_vec COMMAND test_vec) add_test(NAME test_str COMMAND test_str) +add_test(NAME test_bitset COMMAND test_bitset) diff --git a/tests/basic/test_bitset.cc b/tests/basic/test_bitset.cc new file mode 100644 index 0000000..2c1b604 --- /dev/null +++ b/tests/basic/test_bitset.cc @@ -0,0 +1,32 @@ +/* +* MIT License +* Copyright (c) 2023 mxlol233 (mxlol233@outlook.com) + +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: + +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. + +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +*LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +*/ + +#include "basic/bitset.h" + +int main(int argc, char** argv) { + lps::basic::Bitset<2> a; + a.set(); + + lps::basic::Bitset<1> b(a.value(1)); + return 0; +} diff --git a/tests/samples/lexer/macro_if.cc b/tests/samples/lexer/macro_if.cc new file mode 100644 index 0000000..a592ec1 --- /dev/null +++ b/tests/samples/lexer/macro_if.cc @@ -0,0 +1,5 @@ +#if 1 + (1 * 12) + 13 && (223 - 24 - 22) - 111 * 134 + +int main() { + int ccc; +} diff --git a/tests/test_parse_function_output.cc b/tests/test_parse_function_output.cc deleted file mode 100644 index 39d3889..0000000 --- a/tests/test_parse_function_output.cc +++ /dev/null @@ -1,93 +0,0 @@ -/* -* MIT License -* Copyright (c) 2023 mxlol233 (mxlol233@outlook.com) - -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: - -* The above copyright notice and this permission notice shall be included in all -* copies or substantial portions of the Software. - -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -*LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -*/ - -#include -#include "basic/exception.h" -#include "parser.h" -#include "src.h" -int main(int argc, char** argv) { - - lps::parser::details::ParseFunctionOutputs o1; - { - - lps::parser::details::ParseFunctionOutputs o0; - decltype(o0.diag_inputs_)::ele_type a; - decltype(a.context_tokens_)::ele_type token; - a.context_tokens_.append(token); - a.context_tokens_.append(token); - a.context_tokens_.append(token); - a.context_tokens_.append(token); - a.context_tokens_.append(token); - a.context_tokens_.append(token); - - { - decltype(o0.diag_inputs_)::ele_type b; - b.context_tokens_.append(token); - b.context_tokens_.append(token); - b.context_tokens_.append(token); - b.context_tokens_.append(token); - b.context_tokens_.append(token); - b.context_tokens_.append(token); - o0.diag_inputs_.append(std::move(b)); - } - - { - decltype(o0.diag_inputs_)::ele_type b; - b.context_tokens_.append(token); - b.context_tokens_.append(token); - b.context_tokens_.append(token); - b.context_tokens_.append(token); - b.context_tokens_.append(token); - b.context_tokens_.append(token); - o0.diag_inputs_.append(std::move(b)); - } - - { - decltype(o0.diag_inputs_)::ele_type b; - b.context_tokens_.append(token); - b.context_tokens_.append(token); - b.context_tokens_.append(token); - b.context_tokens_.append(token); - b.context_tokens_.append(token); - b.context_tokens_.append(token); - o0.diag_inputs_.append(std::move(b)); - } - { - decltype(o0.diag_inputs_)::ele_type b; - b.context_tokens_.append(token); - b.context_tokens_.append(token); - b.context_tokens_.append(token); - b.context_tokens_.append(token); - b.context_tokens_.append(token); - b.context_tokens_.append(token); - o0.diag_inputs_.append(std::move(b)); - } - - o0.diag_inputs_.append(std::move(a)); - - o1.concat(std::move(o0), false); - } - - std::cout << o1.diag_inputs_.size() << "\n"; - return 0; -}