510 lines
12 KiB
C++
510 lines
12 KiB
C++
#include "work.h"
|
|
#include <assert.h>
|
|
|
|
using namespace std;
|
|
|
|
size_t pt;
|
|
vector<Token> tokens;
|
|
|
|
// void printTokens() {
|
|
// wstring_convert<codecvt_utf8<wchar_t>> cvt;
|
|
// for (auto u : tokens) {
|
|
// cout << token_mp[static_cast<int>(u.type)] << " " << u.line << " " <<
|
|
// cvt.to_bytes(u.s)
|
|
// << endl;
|
|
// }
|
|
// cout << endl;
|
|
// }
|
|
|
|
struct Def {
|
|
enum Type {
|
|
TEMPLATE,
|
|
STRUCT,
|
|
VAR
|
|
};
|
|
virtual Def::Type type() const = 0;
|
|
virtual ~Def() = default;
|
|
};
|
|
|
|
struct DefTemplate : Def {
|
|
Def::Type type() const override {
|
|
return Def::TEMPLATE;
|
|
}
|
|
shared_ptr<TemplateType> def_template;
|
|
};
|
|
|
|
struct DefStruct : Def {
|
|
Def::Type type() const override {
|
|
return Def::STRUCT;
|
|
}
|
|
shared_ptr<Struct> def_struct;
|
|
};
|
|
|
|
struct DefVar : Def {
|
|
Def::Type type() const override {
|
|
return Def::VAR;
|
|
}
|
|
shared_ptr<ValType> def_var;
|
|
};
|
|
|
|
map<string, shared_ptr<Def>> ndefs;
|
|
|
|
bool preview(vector<TokenType> 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<TokenType>{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<ValType> _createVal(shared_ptr<StructType> t);
|
|
shared_ptr<ValType> createVal();
|
|
vector<shared_ptr<ValType>> createVals();
|
|
shared_ptr<ValType> _createType(shared_ptr<Struct>);
|
|
shared_ptr<ValType> createType();
|
|
vector<shared_ptr<ValType>> createTypes();
|
|
vector<pair<string, shared_ptr<TemplateType>>> createTems();
|
|
vector<pair<string, shared_ptr<ValType>>> createPars(map<string, shared_ptr<ValType>>* = nullptr);
|
|
pair<string, shared_ptr<Struct>> createStruct();
|
|
pair<string, shared_ptr<ValType>> createVar();
|
|
|
|
shared_ptr<ValType> _createVal(shared_ptr<StructType> 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() == ValType::FUNCTION
|
|
&& (preview(TokenType::LT) || preview(TokenType::LP))) {
|
|
auto tt = static_pointer_cast<FunctionType>(t);
|
|
vector<shared_ptr<ValType>> 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<TemplateType>, shared_ptr<ValType>> 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() != ValType::STRUCT) {
|
|
printf("error on line %d", tokens[pt].line), exit(0);
|
|
}
|
|
pt++;
|
|
return _createVal(static_pointer_cast<StructType>(t));
|
|
}
|
|
|
|
shared_ptr<ValType> createVal() {
|
|
shared_ptr<ValType> t;
|
|
if (preview(TokenType::FN)) {
|
|
pt++;
|
|
auto tt = make_shared<FunctionType>();
|
|
vector<pair<string, shared_ptr<TemplateType>>> 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<string> 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<ValType>(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() == Def::STRUCT) {
|
|
flag = 1;
|
|
}
|
|
}
|
|
|
|
if (flag) {
|
|
t = createType();
|
|
if (t->type() != ValType::STRUCT) {
|
|
printf("error on line %d", tokens[pt - 1].line), exit(0);
|
|
}
|
|
auto tt = static_pointer_cast<StructType>(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() != Def::VAR) {
|
|
printf("error on line %d", tokens[pt - 1].line), exit(0);
|
|
}
|
|
t = static_pointer_cast<DefVar>(ndefs[s])->def_var;
|
|
}
|
|
}
|
|
while (t->type() == ValType::FUNCTION
|
|
&& (preview(TokenType::LT) || preview(TokenType::LP))) {
|
|
auto tt = static_pointer_cast<FunctionType>(t);
|
|
vector<shared_ptr<ValType>> 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<TemplateType>, shared_ptr<ValType>> 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() != ValType::STRUCT) {
|
|
printf("error on line %d", tokens[pt].line), exit(0);
|
|
}
|
|
pt++;
|
|
return _createVal(static_pointer_cast<StructType>(t));
|
|
}
|
|
|
|
vector<shared_ptr<ValType>> createVals() {
|
|
vector<shared_ptr<ValType>> 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<ValType> _createType(shared_ptr<StructType> 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<StructType>();
|
|
tt->str = str->structs[s], tt->mp = t->mp;
|
|
vector<shared_ptr<ValType>> 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<ValType>(tt);
|
|
}
|
|
pt++;
|
|
return _createType(tt);
|
|
}
|
|
|
|
shared_ptr<ValType> createType() {
|
|
if (preview(TokenType::FN)) {
|
|
pt++;
|
|
auto t = make_shared<FunctionType>();
|
|
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<ValType> 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() == Def::VAR) {
|
|
printf("error on line %d", tokens[pt - 1].line), exit(0);
|
|
}
|
|
if (ndefs[s]->type() == Def::STRUCT) {
|
|
auto tt = make_shared<StructType>();
|
|
tt->str = static_pointer_cast<DefStruct>(ndefs[s])->def_struct;
|
|
vector<shared_ptr<ValType>> 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<ValType>(tt);
|
|
} else {
|
|
t = static_pointer_cast<ValType>(
|
|
static_pointer_cast<DefTemplate>(ndefs[s])->def_template);
|
|
}
|
|
}
|
|
if (!preview(TokenType::SCOPE)) {
|
|
return t;
|
|
}
|
|
if (t->type() != ValType::STRUCT) {
|
|
printf("error on line %d", tokens[pt].line), exit(0);
|
|
}
|
|
pt++;
|
|
return _createType(static_pointer_cast<StructType>(t));
|
|
}
|
|
|
|
vector<shared_ptr<ValType>> createTypes() {
|
|
vector<shared_ptr<ValType>> 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<pair<string, shared_ptr<TemplateType>>> createTems() {
|
|
vector<pair<string, shared_ptr<TemplateType>>> 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<TemplateType>();
|
|
auto d = make_shared<DefTemplate>();
|
|
d->def_template = x;
|
|
ndefs[s] = static_pointer_cast<Def>(d);
|
|
tems.push_back({s, x});
|
|
};
|
|
for (single(); preview(TokenType::COMMA); pt++, single()) {}
|
|
}
|
|
jump(TokenType::RT);
|
|
return tems;
|
|
}
|
|
|
|
vector<pair<string, shared_ptr<ValType>>> createPars(map<string, shared_ptr<ValType>>* vars) {
|
|
vector<pair<string, shared_ptr<ValType>>> pars;
|
|
jump(TokenType::LP);
|
|
if (!preview(TokenType::RP)) {
|
|
auto single = [&]() {
|
|
bool pub = 1;
|
|
if (preview(TokenType::PRIVATE)) {
|
|
pub = 0, pt++;
|
|
}
|
|
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<DefVar>();
|
|
d->def_var = t;
|
|
ndefs[s] = static_pointer_cast<Def>(d);
|
|
pars.push_back({s, t});
|
|
if (vars != nullptr && pub) (*vars)[s]=t;
|
|
};
|
|
for (single(); preview(TokenType::COMMA); pt++, single()) {}
|
|
}
|
|
jump(TokenType::RP);
|
|
return pars;
|
|
}
|
|
|
|
pair<string, shared_ptr<Struct>> createStruct() {
|
|
jump(TokenType::STRUCT);
|
|
string s;
|
|
vector<pair<string, shared_ptr<TemplateType>>> tems;
|
|
vector<pair<string, shared_ptr<ValType>>> pars;
|
|
auto t = make_shared<Struct>();
|
|
|
|
if (preview(TokenType::ID)) {
|
|
s = tokens[pt++].s;
|
|
if (preview(TokenType::LT)) {
|
|
tems = createTems();
|
|
}
|
|
pars = createPars(&t->vars);
|
|
}
|
|
for (const auto& pr : tems) {
|
|
t->c1.push_back(pr.second);
|
|
}
|
|
for (const auto& pr : pars) {
|
|
t->c2.push_back(pr.second);
|
|
}
|
|
|
|
jump(TokenType::LB);
|
|
vector<string> defs;
|
|
vector<shared_ptr<Struct>> subs;
|
|
while (!preview(TokenType::RB)) {
|
|
bool pub = 1;
|
|
if (preview(TokenType::PRIVATE)) {
|
|
pub = 0, 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<DefStruct>();
|
|
tt->def_struct = t;
|
|
ndefs[s] = static_pointer_cast<Def>(tt);
|
|
}
|
|
return {s, t};
|
|
}
|
|
|
|
pair<string, shared_ptr<ValType>> createVar() {
|
|
string s;
|
|
shared_ptr<ValType> t;
|
|
if (preview(TokenType::STRUCT)) {
|
|
auto pr = createStruct();
|
|
s = jump(TokenType::ID);
|
|
jump(TokenType::SEMI);
|
|
auto tt = make_shared<StructType>();
|
|
tt->str = pr.second;
|
|
t = static_pointer_cast<ValType>(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<DefVar>();
|
|
d->def_var = t;
|
|
ndefs[s] = static_pointer_cast<Def>(d);
|
|
return {s, t};
|
|
}
|
|
|
|
void work(vector<Token> _tokens) {
|
|
tokens = _tokens;
|
|
createVar();
|
|
} |