Skip to content

Commit

Permalink
supporting enum
Browse files Browse the repository at this point in the history
  • Loading branch information
chloro-pn committed Jun 13, 2024
1 parent 2581b4b commit 3861332
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 4 deletions.
34 changes: 34 additions & 0 deletions include/wamon/enum_def.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#pragma once

#include <algorithm>
#include <string>
#include <vector>

#include "wamon/exception.h"

namespace wamon {

class EnumDef {
public:
EnumDef(const std::string& enum_name) : enum_name_(enum_name) {}

void AddEnumItem(const std::string& enum_id) {
auto it = std::find(enum_items_.begin(), enum_items_.end(), enum_id);
if (it != enum_items_.end()) {
throw WamonException("EnumDef.AddEnumItem error, duplicate enum id {}", enum_id);
}
enum_items_.push_back(enum_id);
}

const std::string& GetEnumName() const { return enum_name_; }

void SetEnumName(const std::string& name) { enum_name_ = name; }

const std::vector<std::string>& GetEnumItems() const { return enum_items_; }

private:
std::string enum_name_;
std::vector<std::string> enum_items_;
};

} // namespace wamon
14 changes: 12 additions & 2 deletions include/wamon/package_unit.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "wamon/ast.h"
#include "wamon/builtin_functions.h"
#include "wamon/enum_def.h"
#include "wamon/exception.h"
#include "wamon/function_def.h"
#include "wamon/method_def.h"
Expand Down Expand Up @@ -56,19 +57,27 @@ class PackageUnit {
void AddFuncDef(std::unique_ptr<FunctionDef>&& func_def) {
auto name = func_def->GetFunctionName();
if (funcs_.find(name) != funcs_.end()) {
throw WamonException("duplicate func {}", func_def->GetFunctionName());
throw WamonException("duplicate func {}", name);
}
funcs_[name] = std::move(func_def);
}

void AddStructDef(std::unique_ptr<StructDef>&& struct_def) {
auto name = struct_def->GetStructName();
if (structs_.find(name) != structs_.end()) {
throw WamonException("duplicate struct {}", struct_def->GetStructName());
throw WamonException("duplicate struct {}", name);
}
structs_[name] = std::move(struct_def);
}

void AddEnumDef(std::unique_ptr<EnumDef>&& enum_def) {
auto name = enum_def->GetEnumName();
if (enums_.find(name) != enums_.end()) {
throw WamonException("duplicate enum {}", name);
}
enums_[name] = std::move(enum_def);
}

void AddMethod(const std::string& type_name, std::unique_ptr<methods_def>&& methods) {
assert(type_name.empty() == false);
if (structs_.find(type_name) == structs_.end()) {
Expand Down Expand Up @@ -171,6 +180,7 @@ class PackageUnit {
std::vector<std::unique_ptr<VariableDefineStmt>> var_define_;
std::unordered_map<std::string, std::unique_ptr<FunctionDef>> funcs_;
std::unordered_map<std::string, std::unique_ptr<StructDef>> structs_;
std::unordered_map<std::string, std::unique_ptr<EnumDef>> enums_;
BuiltinFunctions builtin_functions_;
size_t lambda_count_{0};
// 只有通过Merge生成的PackageUnit才使用这项
Expand Down
4 changes: 4 additions & 0 deletions include/wamon/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <vector>

#include "wamon/ast.h"
#include "wamon/enum_def.h"
#include "wamon/exception.h"
#include "wamon/function_def.h"
#include "wamon/parameter_list_item.h"
Expand Down Expand Up @@ -116,6 +117,9 @@ std::unique_ptr<OperatorDef> TryToParseOperatorOverride(PackageUnit &pu, const s
std::unique_ptr<StructDef> TryToParseStructDeclaration(PackageUnit &pu, const std::vector<WamonToken> &tokens,
size_t &begin);

std::unique_ptr<EnumDef> TryToParseEnumDeclaration(PackageUnit &pu, const std::vector<WamonToken> &tokens,
size_t &begin);

std::unique_ptr<VariableDefineStmt> TryToParseVariableDeclaration(PackageUnit &pu,
const std::vector<WamonToken> &tokens, size_t &begin);

Expand Down
4 changes: 4 additions & 0 deletions include/wamon/token.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ enum class Token {
STRUCT,
TRAIT,
DESTRUCTOR,
// 枚举定义
ENUM,
// 变量定义
LET,
// 变量引用
Expand Down Expand Up @@ -242,6 +244,8 @@ inline const char *GetTokenStr(Token token) {
return "trait";
case Token::DESTRUCTOR:
return "destructor";
case Token::ENUM:
return "enum";
case Token::LET:
return "let";
case Token::REF:
Expand Down
1 change: 1 addition & 0 deletions src/key_words.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ static void register_buildin_keywords(std::unordered_map<std::string, Token> &kw
kws["operator"] = Token::OPERATOR;
kws["struct"] = Token::STRUCT;
kws["destructor"] = Token::DESTRUCTOR;
kws["enum"] = Token::ENUM;
kws["trait"] = Token::TRAIT;
kws["let"] = Token::LET;
kws["ref"] = Token::REF;
Expand Down
6 changes: 6 additions & 0 deletions src/package_unit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ PackageUnit PackageUnit::_MergePackageUnits(std::vector<PackageUnit>&& packages)
result.AddFuncDef(std::move(func_define->second));
}

for (auto enum_define = it->enums_.begin(); enum_define != it->enums_.end(); ++enum_define) {
auto enum_name = enum_define->first;
enum_define->second->SetEnumName(it->GetName() + "$" + enum_name);
result.AddEnumDef(std::move(enum_define->second));
}

for (auto struct_define = it->structs_.begin(); struct_define != it->structs_.end(); ++struct_define) {
auto struct_name = struct_define->first;
struct_define->second->SetStructName(it->GetName() + "$" + struct_name);
Expand Down
31 changes: 29 additions & 2 deletions src/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ void AssertTokenOrThrow(const std::vector<WamonToken> &tokens, size_t &begin, To
}

// package_name, var_name
template <bool without_packagename = false>
std::pair<std::string, std::string> ParseIdentifier(PackageUnit &pu, const std::vector<WamonToken> &tokens,
size_t &begin) {
if (tokens.size() <= begin || tokens[begin].token != Token::ID || tokens[begin].type != WamonToken::ValueType::STR) {
Expand All @@ -48,6 +49,9 @@ std::pair<std::string, std::string> ParseIdentifier(PackageUnit &pu, const std::
if (tokens.size() <= begin || tokens[begin].token != Token::SCOPE) {
return {pu.GetCurrentParsingPackage(), v1};
}
if constexpr (without_packagename) {
throw WamonException("ParseIdentifier error, without_packagename == true but still parse package_name {}", v1);
}
begin += 1;
if (tokens[begin].token != Token::ID || tokens[begin].type != WamonToken::ValueType::STR) {
throw WamonException("parse identifier error : {}", GetTokenStr(tokens[begin].token));
Expand Down Expand Up @@ -938,18 +942,36 @@ std::unique_ptr<StructDef> TryToParseStructDeclaration(PackageUnit &pu, const st
if (AssertToken(tokens, begin, Token::TRAIT)) {
is_trait = true;
}
auto [package_name, struct_name] = ParseIdentifier(pu, tokens, begin);
auto [package_name, struct_name] = ParseIdentifier<true>(pu, tokens, begin);
ret.reset(new StructDef(struct_name, is_trait));
AssertTokenOrThrow(tokens, begin, Token::LEFT_BRACE, __FILE__, __LINE__);
while (AssertToken(tokens, begin, Token::RIGHT_BRACE) == false) {
auto type = ParseType(pu, tokens, begin);
auto [pack_name, field_name] = ParseIdentifier(pu, tokens, begin);
auto [pack_name, field_name] = ParseIdentifier<true>(pu, tokens, begin);
AssertTokenOrThrow(tokens, begin, Token::SEMICOLON, __FILE__, __LINE__);
ret->AddDataMember(field_name, std::move(type));
}
return ret;
}

std::unique_ptr<EnumDef> TryToParseEnumDeclaration(PackageUnit &pu, const std::vector<WamonToken> &tokens,
size_t &begin) {
std::unique_ptr<EnumDef> ret(nullptr);
bool succ = AssertToken(tokens, begin, Token::ENUM);
if (succ == false) {
return ret;
}
auto [package_name, enum_name] = ParseIdentifier<true>(pu, tokens, begin);
ret.reset(new EnumDef(enum_name));
AssertTokenOrThrow(tokens, begin, Token::LEFT_BRACE, __FILE__, __LINE__);
while (AssertToken(tokens, begin, Token::RIGHT_BRACE) == false) {
auto [pn, fn] = ParseIdentifier<true>(pu, tokens, begin);
AssertTokenOrThrow(tokens, begin, Token::SEMICOLON, __FILE__, __LINE__);
ret->AddEnumItem(fn);
}
return ret;
}

// let var_name : type = (expr_list); or
// let var_name : type = expr;
std::unique_ptr<VariableDefineStmt> TryToParseVariableDeclaration(PackageUnit &pu,
Expand Down Expand Up @@ -1047,6 +1069,11 @@ PackageUnit Parse(const std::vector<WamonToken> &tokens) {
package_unit.AddStructDef(std::move(struct_def));
continue;
}
auto enum_def = TryToParseEnumDeclaration(package_unit, tokens, current_index);
if (enum_def != nullptr) {
package_unit.AddEnumDef(std::move(enum_def));
continue;
}
auto var_declaration = TryToParseVariableDeclaration(package_unit, tokens, current_index);
if (var_declaration != nullptr) {
package_unit.AddVarDef(std::move(var_declaration));
Expand Down
21 changes: 21 additions & 0 deletions test/parser_test.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "wamon/parser.h"

#include "gtest/gtest.h"
#include "wamon/enum_def.h"
#include "wamon/exception.h"
#include "wamon/package_unit.h"
#include "wamon/scanner.h"
Expand Down Expand Up @@ -368,3 +369,23 @@ TEST(parse, parse_type) {
EXPECT_EQ(begin, tokens.size() - 1);
EXPECT_EQ(type->IsBasicType(), false);
}

TEST(parse, parse_enum) {
wamon::Scanner scan;
std::string str = R"(
enum Animal {
cat;
dog;
bird;
}
)";
auto tokens = scan.Scan(str);
size_t begin = 0;
wamon::PackageUnit pu;
auto enum_def = wamon::TryToParseEnumDeclaration(pu, tokens, begin);
EXPECT_NE(enum_def, nullptr);
EXPECT_EQ(enum_def->GetEnumName(), "Animal");
EXPECT_EQ(enum_def->GetEnumItems().size(), 3);
EXPECT_EQ(enum_def->GetEnumItems()[0], "cat");
EXPECT_EQ(begin, tokens.size() - 1);
}

0 comments on commit 3861332

Please sign in to comment.