diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..a6731b3 --- /dev/null +++ b/.clang-format @@ -0,0 +1,147 @@ +Language: Cpp +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: Left +AlignConsecutiveMacros: None +AlignConsecutiveAssignments: None +AlignConsecutiveBitFields: None +AlignConsecutiveDeclarations: None +AlignEscapedNewlines: Left +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortEnumsOnASingleLine: false +AllowShortBlocksOnASingleLine: Empty +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: [] +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false +BreakBeforeBinaryOperators: All +BreakBeforeConceptDeclarations: true +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeComma +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: true +BreakConstructorInitializers: BeforeComma +BreakStringLiterals: true +ColumnLimit: 99 +QualifierAlignment: Left +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: Always +ExperimentalAutoDetectBinPacking: false +PackConstructorInitializers: NextLine +ConstructorInitializerAllOnOneLineOrOnePerLine: false +AllowAllConstructorInitializersOnNextLine: false +FixNamespaceComments: true +ForEachMacros: [] +IfMacros: [] +IncludeBlocks: Merge +IndentAccessModifiers: false +IndentCaseLabels: false +IndentCaseBlocks: false +IndentGotoLabels: false +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequires: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertTrailingCommas: Wrapped +InsertBraces: true +KeepEmptyLinesAtTheStartOfBlocks: false +LambdaBodyIndentation: Signature +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Left +PPIndentWidth: -1 +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: false +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterOverloadedOperator: false + BeforeNonEmptyParentheses: false +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Cpp11 +TabWidth: 4 +UseCRLF: false +UseTab: Always + diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..6539c24 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,827 @@ +#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 +}; + +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() { + freopen("test.txt", "r", stdin); + read(); + printTokens(); + // return 0; + work(); + return 0; +} \ No newline at end of file