diff --git a/include/element.h b/include/element.h new file mode 100644 index 0000000..ce110f6 --- /dev/null +++ b/include/element.h @@ -0,0 +1,53 @@ +#ifndef ACPA_ELEMENT_H +#define ACPA_ELEMENT_H + +#include +#include +#include +#include + +using std::map; +using std::shared_ptr; +using std::string; +using std::vector; +using std::weak_ptr; + +struct Struct; +struct ValType; +struct TemplateType; +struct StructType; +struct FunctionType; + +struct Struct { + weak_ptr fa; + vector> c1; + vector> c2; + map> vars; + map> structs; +}; + +struct ValType { + virtual int type() const = 0; + virtual ~ValType() = default; +}; + +struct TemplateType : ValType { + int type() const override; +}; + +struct StructType : ValType { + int type() const override; + shared_ptr str; + map, shared_ptr> mp; +}; + +struct FunctionType : ValType { + int type() const override; + vector> c1; + vector> c2; + shared_ptr c3; +}; + +bool sameType(shared_ptr, shared_ptr); + +#endif \ No newline at end of file diff --git a/include/read.h b/include/read.h new file mode 100644 index 0000000..da41de7 --- /dev/null +++ b/include/read.h @@ -0,0 +1,8 @@ +#ifndef ACPA_READ_H +#define ACPA_READ_H + +#include + +std::string read(); + +#endif \ No newline at end of file diff --git a/include/scan.h b/include/scan.h new file mode 100644 index 0000000..bb5d959 --- /dev/null +++ b/include/scan.h @@ -0,0 +1,10 @@ +#ifndef ACPA_SCAN_H +#define ACPA_SCAN_H + +#include "token.h" +#include +#include + +std::vector scan(std::string); + +#endif \ No newline at end of file diff --git a/include/token.h b/include/token.h new file mode 100644 index 0000000..89e489e --- /dev/null +++ b/include/token.h @@ -0,0 +1,38 @@ +#ifndef ACPA_TOKEN_H +#define ACPA_TOKEN_H + +#include +#include + +enum class TokenType { + COMMA, // , + SEMI, // ; + LB, // { + RB, // } + LP, // ( + RP, // ) + LT, // < + RT, // > + ASSIGN, // = + DOT, // . + COLON, // : + SCOPE, // :: + IMPLY, // -> + STRUCT, // struct + FN, // Fn + RETURN, // return + TYPEOF, // typeof + PUBLIC, // public + ID, // identifier + EXCEED +}; + +extern std::string token_mp[]; + +struct Token { + int line; + TokenType type; + std::string s; +}; + +#endif \ No newline at end of file diff --git a/include/work.h b/include/work.h new file mode 100644 index 0000000..eec1a53 --- /dev/null +++ b/include/work.h @@ -0,0 +1,10 @@ +#ifndef ACPA_WORK_H +#define ACPA_WORK_H + +#include "element.h" +#include "token.h" +#include + +void work(std::vector); + +#endif \ No newline at end of file diff --git a/src/element.cpp b/src/element.cpp new file mode 100644 index 0000000..d82b7c1 --- /dev/null +++ b/src/element.cpp @@ -0,0 +1,70 @@ +#include "element.h" +#include +#include + +using namespace std; + +int TemplateType::type() const { + return 0; +} + +int StructType::type() const { + return 1; +} + +int FunctionType::type() const { + return 2; +} + +bool sameType(shared_ptr a, shared_ptr b) { + static set, shared_ptr>> eq; + if (a->type() != b->type()) { + return false; + } + if (a->type() == 0) { + auto aa = static_pointer_cast(a), + bb = static_pointer_cast(b); + return aa == bb || eq.find({aa, bb}) != eq.end(); + } + if (a->type() == 1) { + auto aa = static_pointer_cast(a); + auto bb = static_pointer_cast(b); + if (aa->str != bb->str) { + return false; + } + assert(aa->mp.size() == bb->mp.size()); + for (auto ia = aa->mp.begin(), ib = bb->mp.begin(); ia != aa->mp.end(); + ia++, ib++) { + assert(ia->first == ib->first); + if (!sameType(ia->second, ib->second)) { + return false; + } + } + return true; + } + // if(a->type()==2) + { + auto aa = static_pointer_cast(a); + auto bb = static_pointer_cast(b); + if (aa->c1.size() != bb->c1.size() || aa->c2.size() != bb->c2.size()) { + return false; + } + for (size_t i = 0; i < aa->c1.size(); i++) { + eq.insert({aa->c1[i], bb->c1[i]}); + } + bool flag = 1; + for (size_t i = 0; i < aa->c2.size(); i++) { + if (!sameType(aa->c2[i], bb->c2[i])) { + flag = 0; + break; + } + } + if (!flag && !sameType(aa->c3, bb->c3)) { + flag = 0; + } + for (size_t i = 0; i < aa->c1.size(); i++) { + eq.erase({aa->c1[i], bb->c1[i]}); + } + return flag; + } +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 07615e0..89eaf39 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,832 +1,15 @@ +#include "element.h" +#include "read.h" +#include "scan.h" +#include "token.h" +#include "work.h" #include -#include + using namespace std; -enum class TokenType { - COMMA, // , - SEMI, // ; - LB, // { - RB, // } - LP, // ( - RP, // ) - LT, // < - RT, // > - ASSIGN, // = - DOT, // . - COLON, // : - SCOPE, // :: - IMPLY, // -> - STRUCT, // struct - FN, // Fn - RETURN, // return - TYPEOF, // typeof - PUBLIC, // public - ID, // identifier - EXCEED -}; - -struct Token { - int line; - TokenType type; - wstring s; -}; - -size_t pt; -vector tokens; - -void printTokens() { - wstring_convert> cvt; - string mp[] = {",", - ";", - "{", - "}", - "(", - ")", - "<", - ">", - "=", - ".", - ":", - "::", - "->", - "struct", - "Fn", - "return", - "typeof", - "public", - "ID"}; - for (auto u : tokens) { - cout << mp[static_cast(u.type)] << " " << u.line << " " << cvt.to_bytes(u.s) - << endl; - } - cout << endl; -} - -void read() { - string ss; - for (char ch = getchar(); ch != EOF; ch = getchar()) { - ss += ch; - } - wstring_convert> cvt; - wstring s = cvt.from_bytes(ss); - - size_t pt = 0; - int line = 1; - auto skipSpace = [&]() { - while (pt < s.size() && iswspace(s[pt])) { - if (s[pt] == L'\n') { - line++; - } - pt++; - } - }; - for (skipSpace(); pt < s.size(); skipSpace()) { - TokenType type; - wstring t; - if (s[pt] == L',') { - type = TokenType::COMMA, pt++; - } else if (s[pt] == L';') { - type = TokenType::SEMI, pt++; - } else if (s[pt] == L'{') { - type = TokenType::LB, pt++; - } else if (s[pt] == L'}') { - type = TokenType::RB, pt++; - } else if (s[pt] == L'(') { - type = TokenType::LP, pt++; - } else if (s[pt] == L')') { - type = TokenType::RP, pt++; - } else if (s[pt] == L'<') { - type = TokenType::LT, pt++; - } else if (s[pt] == L'>') { - type = TokenType::RT, pt++; - } else if (s[pt] == L'=') { - type = TokenType::ASSIGN, pt++; - } else if (s[pt] == L'.') { - type = TokenType::DOT, pt++; - } else if (s[pt] == L':') { - if (pt + 1 < s.size() && s[pt + 1] == ':') { - type = TokenType::SCOPE, pt += 2; - } else { - type = TokenType::COLON, pt++; - } - } else if (s[pt] == L'-') { - if (pt + 1 < s.size() && s[pt + 1] == '>') { - type = TokenType::IMPLY, pt += 2; - } else { - printf("error on line %d", line), exit(1); - } - } else if ((s[pt] >= 0 && s[pt] < 128) ? (iswalpha(s[pt]) || s[pt] == L'_') - : iswprint(s[pt])) { - size_t r = pt + 1; - while (r < s.size() - && ((s[r] >= 0 && s[r] < 128) - ? (iswalpha(s[r]) || s[r] == L'_' || iswdigit(s[r])) - : iswprint(s[r]))) { - r++; - } - t = s.substr(pt, r - pt); - if (t == L"struct") { - type = TokenType::STRUCT, t.clear(); - } else if (t == L"Fn") { - type = TokenType::FN, t.clear(); - } else if (t == L"return") { - type = TokenType::RETURN, t.clear(); - } else if (t == L"typeof") { - type = TokenType::TYPEOF, t.clear(); - } else if (t == L"public") { - type = TokenType::PUBLIC, t.clear(); - } else { - type = TokenType::ID; - } - pt = r; - } else { - printf("error on line %d", line), exit(1); - } - tokens.push_back({line, type, t}); - } -} - -struct Struct; -struct ValType; -struct TemplateType; -struct StructType; -struct FunctionType; - -struct Struct { - weak_ptr fa; - vector> c1; - vector> c2; - map> vars; - map> structs; -}; - -struct ValType { - virtual const int type() = 0; -}; - -struct TemplateType : ValType { - const int type() override { - return 0; - } -}; - -struct StructType : ValType { - const int type() override { - return 1; - } - shared_ptr str; - map, shared_ptr> mp; -}; - -struct FunctionType : ValType { - const int type() override { - return 2; - } - vector> c1; - vector> c2; - shared_ptr c3; -}; - -bool sameType(shared_ptr a, shared_ptr b) { - static set, shared_ptr>> eq; - if (a->type() != b->type()) { - return false; - } - if (a->type() == 0) { - auto aa = static_pointer_cast(a), - bb = static_pointer_cast(b); - return aa == bb || eq.find({aa, bb}) != eq.end(); - } - if (a->type() == 1) { - auto aa = static_pointer_cast(a); - auto bb = static_pointer_cast(b); - if (aa->str != bb->str) { - return false; - } - assert(aa->mp.size() == bb->mp.size()); - for (auto ia = aa->mp.begin(), ib = bb->mp.begin(); ia != aa->mp.end(); - ia++, ib++) { - assert(ia->first == ib->first); - if (!sameType(ia->second, ib->second)) { - return false; - } - } - return true; - } - // if(a->type()==2) - { - auto aa = static_pointer_cast(a); - auto bb = static_pointer_cast(b); - if (aa->c1.size() != bb->c1.size() || aa->c2.size() != bb->c2.size()) { - return false; - } - for (size_t i = 0; i < aa->c1.size(); i++) { - eq.insert({aa->c1[i], bb->c1[i]}); - } - bool flag = 1; - for (size_t i = 0; i < aa->c2.size(); i++) { - if (!sameType(aa->c2[i], bb->c2[i])) { - flag = 0; - break; - } - } - if (!flag && !sameType(aa->c3, bb->c3)) { - flag = 0; - } - for (size_t i = 0; i < aa->c1.size(); i++) { - eq.erase({aa->c1[i], bb->c1[i]}); - } - return flag; - } -} - -struct Def { - virtual const int type() = 0; -}; - -struct DefTemplate : Def { - const int type() override { - return 0; - } - shared_ptr def_template; -}; - -struct DefStruct : Def { - const int type() override { - return 1; - } - shared_ptr def_struct; -}; - -struct DefVar : Def { - const int type() override { - return 2; - } - shared_ptr def_var; -}; - -map> ndefs; - -bool preview(vector v) { - if (pt + v.size() > tokens.size()) { - return false; - } - for (size_t i = 0; i < v.size(); i++) { - if (tokens[pt + i].type != v[i]) { - return false; - } - } - return true; -} -bool preview(TokenType t) { - return preview(vector{t}); -} -wstring jump(TokenType t) { - if (preview(t)) { - return tokens[pt++].s; - } - if (pt < tokens.size()) { - printf("error on line %d", tokens[pt].line); - } else { - puts("error on end"); - } - exit(1); -} - -shared_ptr _createVal(shared_ptr t); -shared_ptr createVal(); -vector> createVals(); -shared_ptr _createType(shared_ptr); -shared_ptr createType(); -vector> createTypes(); -vector>> createTems(); -vector>> createPars(); -pair> createStruct(); -pair> createVar(); - -shared_ptr struct_replace(shared_ptr vt, shared_ptr ut) { - static map, shared_ptr> eq; - if (vt->type() == 0) { - auto vtt = static_pointer_cast(vt); - auto it1 = ut->mp.find(vtt); - auto it2 = eq.find(vtt); - assert(it1 == ut->mp.end() || it2 == eq.end()); - if (it1 != ut->mp.end()) { - return it1->second; - } - if (it2 != eq.end()) { - return static_pointer_cast(it2->second); - } - return vt; - } - if (vt->type() == 1) { - auto vtt = static_pointer_cast(vt); - auto tt = make_shared(); - (*tt) = (*ut); - set> vis; - for (auto u = vtt->str; u.get() != nullptr; u = u->fa.lock()) { - vis.insert(u); - } - for (auto u = ut->str; u.get() != nullptr && vis.find(u) == vis.end(); - u = u->fa.lock()) { - for (auto tem : u->c1) { - tt->mp.erase(tem); - } - } - for (auto pr : vtt->mp) { - tt->mp[pr.first] = struct_replace(pr.second, ut); - } - return static_pointer_cast(tt); - } - // if(vt->type()==2) - { - auto vtt = static_pointer_cast(vt); - auto tt = make_shared(); - for (size_t i = 0; i < vtt->c1.size(); i++) { - tt->c1.push_back(eq[vtt->c1[i]] = make_shared()); - } - for (auto cc : vtt->c2) { - tt->c2.push_back(struct_replace(cc, ut)); - } - tt->c3 = struct_replace(vtt->c3, ut); - for (size_t i = 0; i < vtt->c1.size(); i++) { - eq.erase(vtt->c1[i]); - } - return static_pointer_cast(tt); - } -} - -shared_ptr function_replace( - shared_ptr t, - const map, shared_ptr>& mp) { - static map, shared_ptr> eq; - if (t->type() == 0) { - auto tt = static_pointer_cast(t); - auto it1 = mp.find(tt); - auto it2 = eq.find(tt); - assert(it1 == mp.end() || it2 == eq.end()); - if (it1 != mp.end()) { - return it1->second; - } - if (it2 != eq.end()) { - return static_pointer_cast(it2->second); - } - return t; - } - if (t->type() == 1) { - auto tt = make_shared(); - (*tt) = (*static_pointer_cast(t)); - for (auto& pr : static_pointer_cast(tt)->mp) { - pr.second = function_replace(pr.second, mp); - } - return tt; - } - // if(t->type()==2) - { - auto vt = static_pointer_cast(t); - auto tt = make_shared(); - for (size_t i = 0; i < vt->c1.size(); i++) { - tt->c1.push_back(eq[vt->c1[i]] = make_shared()); - } - for (auto cc : vt->c2) { - tt->c2.push_back(function_replace(cc, mp)); - } - tt->c3 = function_replace(vt->c3, mp); - for (size_t i = 0; i < vt->c1.size(); i++) { - eq.erase(vt->c1[i]); - } - return static_pointer_cast(tt); - } -} - -shared_ptr _createVal(shared_ptr ft) { - auto str = ft->str; - auto s = jump(TokenType::ID); - if (str->vars.find(s) == str->vars.end()) { - printf("error on line %d", tokens[pt - 1].line), exit(0); - } - auto t = struct_replace(str->vars[s], ft); - while (t->type() == 2 && (preview(TokenType::LT) || preview(TokenType::LP))) { - auto tt = static_pointer_cast(t); - vector> types; - if (preview(TokenType::LT)) { - types = createTypes(); - } - if (tt->c1.size() != types.size()) { - printf("error on line %d", tokens[pt - 1].line), exit(0); - } - map, shared_ptr> mp; - for (size_t i = 0; i < types.size(); i++) { - mp[tt->c1[i]] = types[i]; - } - auto vals = createVals(); - bool legal = tt->c2.size() == vals.size(); - if (legal) { - for (size_t i = 0; i < vals.size(); i++) { - if (!sameType(vals[i], function_replace(tt->c2[i], mp))) { - legal = 0; - break; - } - } - } - if (!legal) { - printf("error on line %d", tokens[pt - 1].line), exit(0); - } - t = function_replace(tt->c3, mp); - } - if (!preview(TokenType::DOT)) { - return t; - } - if (t->type() != 1) { - printf("error on line %d", tokens[pt].line), exit(0); - } - pt++; - return _createVal(static_pointer_cast(t)); -} - -shared_ptr createVal() { - shared_ptr t; - if (preview(TokenType::FN)) { - pt++; - auto tt = make_shared(); - vector>> tems; - if (preview(TokenType::LT)) { - tems = createTems(); - } - for (const auto& pr : tems) { - tt->c1.push_back(pr.second); - } - auto pars = createPars(); - for (const auto& pr : pars) { - tt->c2.push_back(pr.second); - } - jump(TokenType::IMPLY); - tt->c3 = createType(); - - jump(TokenType::LB); - vector defs; - while (!preview(TokenType::RETURN)) { - if (preview({TokenType::STRUCT, TokenType::ID})) { - defs.push_back(createStruct().first); - jump(TokenType::SEMI); - } else { - defs.push_back(createVar().first); - } - } - pt++; - auto ret = createVal(); - jump(TokenType::SEMI); - if (!sameType(tt->c3, ret)) { - printf("error on line %d", tokens[pt - 1].line), exit(0); - } - for (const auto& pr : tems) { - ndefs.erase(pr.first); - } - for (const auto& pr : pars) { - ndefs.erase(pr.first); - } - for (const auto& s : defs) { - ndefs.erase(s); - } - jump(TokenType::RB); - - t = static_pointer_cast(tt); - } else { - bool flag = 0; // 新实例 - if (preview(TokenType::TYPEOF)) { - flag = 1; - } else if (preview(TokenType::ID)) { - auto s = tokens[pt].s; - if (ndefs.find(s) != ndefs.end() && ndefs[s]->type() == 1) { - flag = 1; - } - } - - if (flag) { - t = createType(); - if (t->type() != 1) { - printf("error on line %d", tokens[pt - 1].line), exit(0); - } - auto tt = static_pointer_cast(t); - auto vals = createVals(); - bool legal = vals.size() == tt->str->c2.size(); - if (legal) { - for (size_t i = 0; i < vals.size(); i++) { - if (!sameType(vals[i], - struct_replace(tt->str->c2[i], tt))) { - legal = 0; - break; - } - } - } - if (!legal) { - printf("error on line %d", tokens[pt - 1].line), exit(0); - } - } else { - auto s = jump(TokenType::ID); - if (ndefs.find(s) == ndefs.end() || ndefs[s]->type() != 2) { - printf("error on line %d", tokens[pt - 1].line), exit(0); - } - t = static_pointer_cast(ndefs[s])->def_var; - } - } - while (t->type() == 2 && (preview(TokenType::LT) || preview(TokenType::LP))) { - auto tt = static_pointer_cast(t); - vector> types; - if (preview(TokenType::LT)) { - types = createTypes(); - } - if (tt->c1.size() != types.size()) { - printf("error on line %d", tokens[pt - 1].line), exit(0); - } - map, shared_ptr> mp; - for (size_t i = 0; i < types.size(); i++) { - mp[tt->c1[i]] = types[i]; - } - auto vals = createVals(); - bool legal = tt->c2.size() == vals.size(); - if (legal) { - for (size_t i = 0; i < vals.size(); i++) { - if (!sameType(vals[i], function_replace(tt->c2[i], mp))) { - legal = 0; - break; - } - } - } - if (!legal) { - printf("error on line %d", tokens[pt - 1].line), exit(0); - } - t = function_replace(tt->c3, mp); - } - if (!preview(TokenType::DOT)) { - return t; - } - if (t->type() != 1) { - printf("error on line %d", tokens[pt].line), exit(0); - } - pt++; - return _createVal(static_pointer_cast(t)); -} - -vector> createVals() { - vector> vals; - jump(TokenType::LP); - if (!preview(TokenType::RP)) { - auto single = [&]() { vals.push_back(createVal()); }; - for (single(); preview(TokenType::COMMA); pt++, single()) { - ; - } - } - jump(TokenType::RP); - return vals; -} - -shared_ptr _createType(shared_ptr t) { - auto str = t->str; - auto s = jump(TokenType::ID); - if (str->structs.find(s) == str->structs.end()) { - printf("error on line %d", tokens[pt - 1].line), exit(0); - } - auto tt = make_shared(); - tt->str = str->structs[s], tt->mp = t->mp; - vector> types; - if (tt->str->c1.size() || preview(TokenType::LT)) { - types = createTypes(); - } - if (tt->str->c1.size() != types.size()) { - printf("error on line %d", tokens[pt - 1].line), exit(0); - } - for (size_t i = 0; i < types.size(); i++) { - tt->mp[tt->str->c1[i]] = types[i]; - } - if (!preview(TokenType::SCOPE)) { - return static_pointer_cast(tt); - } - pt++; - return _createType(tt); -} - -shared_ptr createType() { - if (preview(TokenType::FN)) { - pt++; - auto t = make_shared(); - jump(TokenType::LP); - auto tems = createTems(); - for (const auto& pr : tems) { - t->c1.push_back(pr.second); - } - jump(TokenType::COMMA); - t->c2 = createTypes(); - jump(TokenType::COMMA); - t->c3 = createType(); - jump(TokenType::RP); - for (const auto& pr : tems) { - ndefs.erase(pr.first); - } - return t; - } - shared_ptr t; - if (preview(TokenType::TYPEOF)) { - pt++; - jump(TokenType::LP); - t = createVal(); - jump(TokenType::RP); - } else { - auto s = jump(TokenType::ID); - if (ndefs.find(s) == ndefs.end() || ndefs[s]->type() == 2) { - printf("error on line %d", tokens[pt - 1].line), exit(0); - } - if (ndefs[s]->type() == 1) { - auto tt = make_shared(); - tt->str = static_pointer_cast(ndefs[s])->def_struct; - vector> types; - if (tt->str->c1.size() || preview(TokenType::LT)) { - types = createTypes(); - } - if (tt->str->c1.size() != types.size()) { - printf("error on line %d", tokens[pt - 1].line), exit(0); - } - for (size_t i = 0; i < types.size(); i++) { - tt->mp[tt->str->c1[i]] = types[i]; - } - t = static_pointer_cast(tt); - } else { - t = static_pointer_cast( - static_pointer_cast(ndefs[s])->def_template); - } - } - if (!preview(TokenType::SCOPE)) { - return t; - } - if (t->type() != 1) { - printf("error on line %d", tokens[pt].line), exit(0); - } - pt++; - return _createType(static_pointer_cast(t)); -} - -vector> createTypes() { - vector> types; - jump(TokenType::LT); - if (!preview(TokenType::RT)) { - auto single = [&]() { types.push_back(createType()); }; - for (single(); preview(TokenType::COMMA); pt++, single()) { - ; - } - } - jump(TokenType::RT); - return types; -} - -vector>> createTems() { - vector>> tems; - jump(TokenType::LT); - if (preview(TokenType::ID)) { - auto single = [&]() { - auto s = jump(TokenType::ID); - if (ndefs.find(s) != ndefs.end()) { - printf("error on line %d", tokens[pt - 1].line), exit(0); - } - auto x = make_shared(); - auto d = make_shared(); - d->def_template = x; - ndefs[s] = static_pointer_cast(d); - tems.push_back({s, x}); - }; - for (single(); preview(TokenType::COMMA); pt++, single()) { - ; - } - } - jump(TokenType::RT); - return tems; -} - -vector>> createPars() { - vector>> pars; - jump(TokenType::LP); - if (preview(TokenType::ID)) { - auto single = [&]() { - auto s = jump(TokenType::ID); - if (ndefs.find(s) != ndefs.end()) { - printf("error on line %d", tokens[pt - 1].line), exit(0); - } - jump(TokenType::COLON); - auto t = createType(); - auto d = make_shared(); - d->def_var = t; - ndefs[s] = static_pointer_cast(d); - pars.push_back({s, t}); - }; - for (single(); preview(TokenType::COMMA); pt++, single()) { - ; - } - } - jump(TokenType::RP); - return pars; -} - -pair> createStruct() { - jump(TokenType::STRUCT); - wstring s; - vector>> tems; - vector>> pars; - - if (preview(TokenType::ID)) { - s = tokens[pt++].s; - if (preview(TokenType::LT)) { - tems = createTems(); - } - pars = createPars(); - } - auto t = make_shared(); - for (const auto& pr : tems) { - t->c1.push_back(pr.second); - } - for (const auto& pr : pars) { - t->c2.push_back(pr.second); - t->vars[pr.first] = pr.second; - } - - jump(TokenType::LB); - vector defs; - vector> subs; - while (!preview(TokenType::RB)) { - bool pub = 0; - if (preview(TokenType::PUBLIC)) { - pub = 1, pt++; - } - if (preview({TokenType::STRUCT, TokenType::ID})) { - auto tt = createStruct(); - jump(TokenType::SEMI); - subs.push_back(tt.second); - defs.push_back(tt.first); - if (pub) { - t->structs[tt.first] = tt.second; - } - } else { - auto tt = createVar(); - defs.push_back(tt.first); - if (pub) { - t->vars[tt.first] = tt.second; - } - } - } - jump(TokenType::RB); - - for (auto str : subs) { - str->fa = t; - } - for (const auto& pr : tems) { - ndefs.erase(pr.first); - } - for (const auto& pr : pars) { - ndefs.erase(pr.first); - } - for (const auto& ss : defs) { - ndefs.erase(ss); - } - - if (!s.empty()) { - auto tt = make_shared(); - tt->def_struct = t; - ndefs[s] = static_pointer_cast(tt); - } - return {s, t}; -} - -pair> createVar() { - wstring s; - shared_ptr t; - if (preview(TokenType::STRUCT)) { - auto pr = createStruct(); - s = jump(TokenType::ID); - jump(TokenType::SEMI); - auto tt = make_shared(); - tt->str = pr.second; - t = static_pointer_cast(tt); - } else { - s = jump(TokenType::ID); - jump(TokenType::ASSIGN); - t = createVal(); - jump(TokenType::SEMI); - } - if (ndefs.find(s) != ndefs.end()) { - printf("error on line %d", tokens[pt - 1].line), exit(0); - } - auto d = make_shared(); - d->def_var = t; - ndefs[s] = static_pointer_cast(d); - return {s, t}; -} - -void work() { - createVar(); -} - int main(int argc, char* argv[]) { - #define AS_STR(x) #x argparse::ArgumentParser program("acpa", - AS_STR(APP_VERSION), + "0.1a0", argparse::default_arguments::help, false); @@ -845,9 +28,7 @@ int main(int argc, char* argv[]) { auto input_file = program.get("input_file"); freopen(input_file.c_str(), "r", stdin); - read(); - printTokens(); - work(); + work(scan(read())); + return 0; } - diff --git a/src/read.cpp b/src/read.cpp new file mode 100644 index 0000000..765a502 --- /dev/null +++ b/src/read.cpp @@ -0,0 +1,11 @@ +#include "read.h" + +using namespace std; + +string read() { + string s; + for (char ch = getchar(); ch != EOF; ch = getchar()) { + s += ch; + } + return s; +} \ No newline at end of file diff --git a/src/scan.cpp b/src/scan.cpp new file mode 100644 index 0000000..bd74ca8 --- /dev/null +++ b/src/scan.cpp @@ -0,0 +1,78 @@ +#include "scan.h" + +using namespace std; + +vector scan(string s) { + size_t pt = 0; + int line = 1; + vector tokens; + auto skipSpace = [&]() { + while (pt < s.size() && isspace(s[pt])) { + if (s[pt] == '\n') { + line++; + } + pt++; + } + }; + for (skipSpace(); pt < s.size(); skipSpace()) { + TokenType type; + string t; + if (s[pt] == ',') { + type = TokenType::COMMA, pt++; + } else if (s[pt] == ';') { + type = TokenType::SEMI, pt++; + } else if (s[pt] == '{') { + type = TokenType::LB, pt++; + } else if (s[pt] == '}') { + type = TokenType::RB, pt++; + } else if (s[pt] == '(') { + type = TokenType::LP, pt++; + } else if (s[pt] == ')') { + type = TokenType::RP, pt++; + } else if (s[pt] == '<') { + type = TokenType::LT, pt++; + } else if (s[pt] == '>') { + type = TokenType::RT, pt++; + } else if (s[pt] == '=') { + type = TokenType::ASSIGN, pt++; + } else if (s[pt] == '.') { + type = TokenType::DOT, pt++; + } else if (s[pt] == ':') { + if (pt + 1 < s.size() && s[pt + 1] == ':') { + type = TokenType::SCOPE, pt += 2; + } else { + type = TokenType::COLON, pt++; + } + } else if (s[pt] == '-') { + if (pt + 1 < s.size() && s[pt + 1] == '>') { + type = TokenType::IMPLY, pt += 2; + } else { + printf("error on line %d", line), exit(1); + } + } else if (isalpha(s[pt]) || s[pt] == '_') { + size_t r = pt + 1; + while (r < s.size() && (isalpha(s[r]) || s[r] == '_' || isdigit(s[r]))) { + r++; + } + t = s.substr(pt, r - pt); + if (t == "struct") { + type = TokenType::STRUCT, t.clear(); + } else if (t == "Fn") { + type = TokenType::FN, t.clear(); + } else if (t == "return") { + type = TokenType::RETURN, t.clear(); + } else if (t == "typeof") { + type = TokenType::TYPEOF, t.clear(); + } else if (t == "public") { + type = TokenType::PUBLIC, t.clear(); + } else { + type = TokenType::ID; + } + pt = r; + } else { + printf("error on line %d", line), exit(1); + } + tokens.push_back({line, type, t}); + } + return tokens; +} \ No newline at end of file diff --git a/src/token.cpp b/src/token.cpp new file mode 100644 index 0000000..873a0cd --- /dev/null +++ b/src/token.cpp @@ -0,0 +1,22 @@ + +#include + +std::string token_mp[] = {",", + ";", + "{", + "}", + "(", + ")", + "<", + ">", + "=", + ".", + ":", + "::", + "->", + "struct", + "Fn", + "return", + "typeof", + "public", + "ID"}; diff --git a/src/work.cpp b/src/work.cpp new file mode 100644 index 0000000..56f995e --- /dev/null +++ b/src/work.cpp @@ -0,0 +1,603 @@ +#include "work.h" +#include +#include + +using namespace std; + +size_t pt; +vector tokens; + +// void printTokens() { +// wstring_convert> cvt; +// for (auto u : tokens) { +// cout << token_mp[static_cast(u.type)] << " " << u.line << " " << +// cvt.to_bytes(u.s) +// << endl; +// } +// cout << endl; +// } + +struct Def { + virtual int type() const = 0; + virtual ~Def() = default; +}; + +struct DefTemplate : Def { + int type() const override { + return 0; + } + shared_ptr def_template; +}; + +struct DefStruct : Def { + int type() const override { + return 1; + } + shared_ptr def_struct; +}; + +struct DefVar : Def { + int type() const override { + return 2; + } + shared_ptr def_var; +}; + +map> ndefs; + +bool preview(vector v) { + if (pt + v.size() > tokens.size()) { + return false; + } + for (size_t i = 0; i < v.size(); i++) { + if (tokens[pt + i].type != v[i]) { + return false; + } + } + return true; +} +bool preview(TokenType t) { + return preview(vector{t}); +} +string jump(TokenType t) { + if (preview(t)) { + return tokens[pt++].s; + } + if (pt < tokens.size()) { + printf("error on line %d", tokens[pt].line); + } else { + puts("error on end"); + } + exit(1); +} + +shared_ptr _createVal(shared_ptr t); +shared_ptr createVal(); +vector> createVals(); +shared_ptr _createType(shared_ptr); +shared_ptr createType(); +vector> createTypes(); +vector>> createTems(); +vector>> createPars(); +pair> createStruct(); +pair> createVar(); + +shared_ptr struct_replace(shared_ptr vt, shared_ptr ut) { + static map, shared_ptr> eq; + if (vt->type() == 0) { + auto vtt = static_pointer_cast(vt); + auto it1 = ut->mp.find(vtt); + auto it2 = eq.find(vtt); + assert(it1 == ut->mp.end() || it2 == eq.end()); + if (it1 != ut->mp.end()) { + return it1->second; + } + if (it2 != eq.end()) { + return static_pointer_cast(it2->second); + } + return vt; + } + if (vt->type() == 1) { + auto vtt = static_pointer_cast(vt); + auto tt = make_shared(); + (*tt) = (*ut); + set> vis; + for (auto u = vtt->str; u.get() != nullptr; u = u->fa.lock()) { + vis.insert(u); + } + for (auto u = ut->str; u.get() != nullptr && vis.find(u) == vis.end(); + u = u->fa.lock()) { + for (auto tem : u->c1) { + tt->mp.erase(tem); + } + } + for (auto pr : vtt->mp) { + tt->mp[pr.first] = struct_replace(pr.second, ut); + } + return static_pointer_cast(tt); + } + // if(vt->type()==2) + { + auto vtt = static_pointer_cast(vt); + auto tt = make_shared(); + for (size_t i = 0; i < vtt->c1.size(); i++) { + tt->c1.push_back(eq[vtt->c1[i]] = make_shared()); + } + for (auto cc : vtt->c2) { + tt->c2.push_back(struct_replace(cc, ut)); + } + tt->c3 = struct_replace(vtt->c3, ut); + for (size_t i = 0; i < vtt->c1.size(); i++) { + eq.erase(vtt->c1[i]); + } + return static_pointer_cast(tt); + } +} + +shared_ptr function_replace( + shared_ptr t, + const map, shared_ptr>& mp) { + static map, shared_ptr> eq; + if (t->type() == 0) { + auto tt = static_pointer_cast(t); + auto it1 = mp.find(tt); + auto it2 = eq.find(tt); + assert(it1 == mp.end() || it2 == eq.end()); + if (it1 != mp.end()) { + return it1->second; + } + if (it2 != eq.end()) { + return static_pointer_cast(it2->second); + } + return t; + } + if (t->type() == 1) { + auto tt = make_shared(); + (*tt) = (*static_pointer_cast(t)); + for (auto& pr : static_pointer_cast(tt)->mp) { + pr.second = function_replace(pr.second, mp); + } + return tt; + } + // if(t->type()==2) + { + auto vt = static_pointer_cast(t); + auto tt = make_shared(); + for (size_t i = 0; i < vt->c1.size(); i++) { + tt->c1.push_back(eq[vt->c1[i]] = make_shared()); + } + for (auto cc : vt->c2) { + tt->c2.push_back(function_replace(cc, mp)); + } + tt->c3 = function_replace(vt->c3, mp); + for (size_t i = 0; i < vt->c1.size(); i++) { + eq.erase(vt->c1[i]); + } + return static_pointer_cast(tt); + } +} + +shared_ptr _createVal(shared_ptr ft) { + auto str = ft->str; + auto s = jump(TokenType::ID); + if (str->vars.find(s) == str->vars.end()) { + printf("error on line %d", tokens[pt - 1].line), exit(0); + } + auto t = struct_replace(str->vars[s], ft); + while (t->type() == 2 && (preview(TokenType::LT) || preview(TokenType::LP))) { + auto tt = static_pointer_cast(t); + vector> types; + if (preview(TokenType::LT)) { + types = createTypes(); + } + if (tt->c1.size() != types.size()) { + printf("error on line %d", tokens[pt - 1].line), exit(0); + } + map, shared_ptr> mp; + for (size_t i = 0; i < types.size(); i++) { + mp[tt->c1[i]] = types[i]; + } + auto vals = createVals(); + bool legal = tt->c2.size() == vals.size(); + if (legal) { + for (size_t i = 0; i < vals.size(); i++) { + if (!sameType(vals[i], function_replace(tt->c2[i], mp))) { + legal = 0; + break; + } + } + } + if (!legal) { + printf("error on line %d", tokens[pt - 1].line), exit(0); + } + t = function_replace(tt->c3, mp); + } + if (!preview(TokenType::DOT)) { + return t; + } + if (t->type() != 1) { + printf("error on line %d", tokens[pt].line), exit(0); + } + pt++; + return _createVal(static_pointer_cast(t)); +} + +shared_ptr createVal() { + shared_ptr t; + if (preview(TokenType::FN)) { + pt++; + auto tt = make_shared(); + vector>> tems; + if (preview(TokenType::LT)) { + tems = createTems(); + } + for (const auto& pr : tems) { + tt->c1.push_back(pr.second); + } + auto pars = createPars(); + for (const auto& pr : pars) { + tt->c2.push_back(pr.second); + } + jump(TokenType::IMPLY); + tt->c3 = createType(); + + jump(TokenType::LB); + vector defs; + while (!preview(TokenType::RETURN)) { + if (preview({TokenType::STRUCT, TokenType::ID})) { + defs.push_back(createStruct().first); + jump(TokenType::SEMI); + } else { + defs.push_back(createVar().first); + } + } + pt++; + auto ret = createVal(); + jump(TokenType::SEMI); + if (!sameType(tt->c3, ret)) { + printf("error on line %d", tokens[pt - 1].line), exit(0); + } + for (const auto& pr : tems) { + ndefs.erase(pr.first); + } + for (const auto& pr : pars) { + ndefs.erase(pr.first); + } + for (const auto& s : defs) { + ndefs.erase(s); + } + jump(TokenType::RB); + + t = static_pointer_cast(tt); + } else { + bool flag = 0; // 新实例 + if (preview(TokenType::TYPEOF)) { + flag = 1; + } else if (preview(TokenType::ID)) { + auto s = tokens[pt].s; + if (ndefs.find(s) != ndefs.end() && ndefs[s]->type() == 1) { + flag = 1; + } + } + + if (flag) { + t = createType(); + if (t->type() != 1) { + printf("error on line %d", tokens[pt - 1].line), exit(0); + } + auto tt = static_pointer_cast(t); + auto vals = createVals(); + bool legal = vals.size() == tt->str->c2.size(); + if (legal) { + for (size_t i = 0; i < vals.size(); i++) { + if (!sameType(vals[i], + struct_replace(tt->str->c2[i], tt))) { + legal = 0; + break; + } + } + } + if (!legal) { + printf("error on line %d", tokens[pt - 1].line), exit(0); + } + } else { + auto s = jump(TokenType::ID); + if (ndefs.find(s) == ndefs.end() || ndefs[s]->type() != 2) { + printf("error on line %d", tokens[pt - 1].line), exit(0); + } + t = static_pointer_cast(ndefs[s])->def_var; + } + } + while (t->type() == 2 && (preview(TokenType::LT) || preview(TokenType::LP))) { + auto tt = static_pointer_cast(t); + vector> types; + if (preview(TokenType::LT)) { + types = createTypes(); + } + if (tt->c1.size() != types.size()) { + printf("error on line %d", tokens[pt - 1].line), exit(0); + } + map, shared_ptr> mp; + for (size_t i = 0; i < types.size(); i++) { + mp[tt->c1[i]] = types[i]; + } + auto vals = createVals(); + bool legal = tt->c2.size() == vals.size(); + if (legal) { + for (size_t i = 0; i < vals.size(); i++) { + if (!sameType(vals[i], function_replace(tt->c2[i], mp))) { + legal = 0; + break; + } + } + } + if (!legal) { + printf("error on line %d", tokens[pt - 1].line), exit(0); + } + t = function_replace(tt->c3, mp); + } + if (!preview(TokenType::DOT)) { + return t; + } + if (t->type() != 1) { + printf("error on line %d", tokens[pt].line), exit(0); + } + pt++; + return _createVal(static_pointer_cast(t)); +} + +vector> createVals() { + vector> vals; + jump(TokenType::LP); + if (!preview(TokenType::RP)) { + auto single = [&]() { vals.push_back(createVal()); }; + for (single(); preview(TokenType::COMMA); pt++, single()) { + ; + } + } + jump(TokenType::RP); + return vals; +} + +shared_ptr _createType(shared_ptr t) { + auto str = t->str; + auto s = jump(TokenType::ID); + if (str->structs.find(s) == str->structs.end()) { + printf("error on line %d", tokens[pt - 1].line), exit(0); + } + auto tt = make_shared(); + tt->str = str->structs[s], tt->mp = t->mp; + vector> types; + if (tt->str->c1.size() || preview(TokenType::LT)) { + types = createTypes(); + } + if (tt->str->c1.size() != types.size()) { + printf("error on line %d", tokens[pt - 1].line), exit(0); + } + for (size_t i = 0; i < types.size(); i++) { + tt->mp[tt->str->c1[i]] = types[i]; + } + if (!preview(TokenType::SCOPE)) { + return static_pointer_cast(tt); + } + pt++; + return _createType(tt); +} + +shared_ptr createType() { + if (preview(TokenType::FN)) { + pt++; + auto t = make_shared(); + jump(TokenType::LP); + auto tems = createTems(); + for (const auto& pr : tems) { + t->c1.push_back(pr.second); + } + jump(TokenType::COMMA); + t->c2 = createTypes(); + jump(TokenType::COMMA); + t->c3 = createType(); + jump(TokenType::RP); + for (const auto& pr : tems) { + ndefs.erase(pr.first); + } + return t; + } + shared_ptr t; + if (preview(TokenType::TYPEOF)) { + pt++; + jump(TokenType::LP); + t = createVal(); + jump(TokenType::RP); + } else { + auto s = jump(TokenType::ID); + if (ndefs.find(s) == ndefs.end() || ndefs[s]->type() == 2) { + printf("error on line %d", tokens[pt - 1].line), exit(0); + } + if (ndefs[s]->type() == 1) { + auto tt = make_shared(); + tt->str = static_pointer_cast(ndefs[s])->def_struct; + vector> types; + if (tt->str->c1.size() || preview(TokenType::LT)) { + types = createTypes(); + } + if (tt->str->c1.size() != types.size()) { + printf("error on line %d", tokens[pt - 1].line), exit(0); + } + for (size_t i = 0; i < types.size(); i++) { + tt->mp[tt->str->c1[i]] = types[i]; + } + t = static_pointer_cast(tt); + } else { + t = static_pointer_cast( + static_pointer_cast(ndefs[s])->def_template); + } + } + if (!preview(TokenType::SCOPE)) { + return t; + } + if (t->type() != 1) { + printf("error on line %d", tokens[pt].line), exit(0); + } + pt++; + return _createType(static_pointer_cast(t)); +} + +vector> createTypes() { + vector> types; + jump(TokenType::LT); + if (!preview(TokenType::RT)) { + auto single = [&]() { types.push_back(createType()); }; + for (single(); preview(TokenType::COMMA); pt++, single()) { + ; + } + } + jump(TokenType::RT); + return types; +} + +vector>> createTems() { + vector>> tems; + jump(TokenType::LT); + if (preview(TokenType::ID)) { + auto single = [&]() { + auto s = jump(TokenType::ID); + if (ndefs.find(s) != ndefs.end()) { + printf("error on line %d", tokens[pt - 1].line), exit(0); + } + auto x = make_shared(); + auto d = make_shared(); + d->def_template = x; + ndefs[s] = static_pointer_cast(d); + tems.push_back({s, x}); + }; + for (single(); preview(TokenType::COMMA); pt++, single()) { + ; + } + } + jump(TokenType::RT); + return tems; +} + +vector>> createPars() { + vector>> pars; + jump(TokenType::LP); + if (preview(TokenType::ID)) { + auto single = [&]() { + auto s = jump(TokenType::ID); + if (ndefs.find(s) != ndefs.end()) { + printf("error on line %d", tokens[pt - 1].line), exit(0); + } + jump(TokenType::COLON); + auto t = createType(); + auto d = make_shared(); + d->def_var = t; + ndefs[s] = static_pointer_cast(d); + pars.push_back({s, t}); + }; + for (single(); preview(TokenType::COMMA); pt++, single()) { + ; + } + } + jump(TokenType::RP); + return pars; +} + +pair> createStruct() { + jump(TokenType::STRUCT); + string s; + vector>> tems; + vector>> pars; + + if (preview(TokenType::ID)) { + s = tokens[pt++].s; + if (preview(TokenType::LT)) { + tems = createTems(); + } + pars = createPars(); + } + auto t = make_shared(); + for (const auto& pr : tems) { + t->c1.push_back(pr.second); + } + for (const auto& pr : pars) { + t->c2.push_back(pr.second); + t->vars[pr.first] = pr.second; + } + + jump(TokenType::LB); + vector defs; + vector> subs; + while (!preview(TokenType::RB)) { + bool pub = 0; + if (preview(TokenType::PUBLIC)) { + pub = 1, pt++; + } + if (preview({TokenType::STRUCT, TokenType::ID})) { + auto tt = createStruct(); + jump(TokenType::SEMI); + subs.push_back(tt.second); + defs.push_back(tt.first); + if (pub) { + t->structs[tt.first] = tt.second; + } + } else { + auto tt = createVar(); + defs.push_back(tt.first); + if (pub) { + t->vars[tt.first] = tt.second; + } + } + } + jump(TokenType::RB); + + for (auto str : subs) { + str->fa = t; + } + for (const auto& pr : tems) { + ndefs.erase(pr.first); + } + for (const auto& pr : pars) { + ndefs.erase(pr.first); + } + for (const auto& ss : defs) { + ndefs.erase(ss); + } + + if (!s.empty()) { + auto tt = make_shared(); + tt->def_struct = t; + ndefs[s] = static_pointer_cast(tt); + } + return {s, t}; +} + +pair> createVar() { + string s; + shared_ptr t; + if (preview(TokenType::STRUCT)) { + auto pr = createStruct(); + s = jump(TokenType::ID); + jump(TokenType::SEMI); + auto tt = make_shared(); + tt->str = pr.second; + t = static_pointer_cast(tt); + } else { + s = jump(TokenType::ID); + jump(TokenType::ASSIGN); + t = createVal(); + jump(TokenType::SEMI); + } + if (ndefs.find(s) != ndefs.end()) { + printf("error on line %d", tokens[pt - 1].line), exit(0); + } + auto d = make_shared(); + d->def_var = t; + ndefs[s] = static_pointer_cast(d); + return {s, t}; +} + +void work(vector _tokens) { + tokens = _tokens; + createVar(); +} \ No newline at end of file diff --git a/xmake.lua b/xmake.lua index 3ac57d1..06e25ee 100644 --- a/xmake.lua +++ b/xmake.lua @@ -12,7 +12,7 @@ target("build") set_default(true) set_warnings("allextra") add_files("src/**.cpp") - -- add_includedirs("include/") + add_includedirs("include/") add_includedirs("third-party/") add_defines("APP_VERSION=" .. app_version) if is_mode("release") then