#include "cpp.h" #include "bnf.h" #include "cppbnf.h" #include "debug.h" #include "lexer.h" #include "grammer.h" #include "minicc.h" #include #include #include #include #include using namespace Gram; CPP::CPP(){} CPP::~CPP(){} // Phase 1: Map physical character set to basic source character set void CPP::source_charset_map() { // TODO } // Phase 2: Escape backslashed line endings void CPP::backslash_escape() { // TODO } // Phase 3: Parse preprocessing tokens, TODO: discard comments std::vector CPP::preprocessing_tokenize(const std::string& s) { auto bnf{SubBNF(CPPBNF::GetCppBNFLex(), "preprocessing-token")}; Lex::Lexer lexer(bnf, "preprocessing-token"); return lexer.Lex(s); } // Phase 4: Preprocessing void CPP::preprocess() { // TODO } // Phase 5: Map chars and strings to execution charset void CPP::execution_charset_map() { // TODO } // Phase 6: Concatenate adjacent string literals void CPP::concatenate_strings() { // TODO } std::string CPP::valueOfNode(index_t node_index, const std::vector& Tree) { std::string result; std::vector todo(1, int32_t(node_index)); while (!todo.empty()) { int32_t current_index = todo.back(); todo.pop_back(); // visit node if token if (ChildIdIsToken(current_index)) { result += m_code[TokenIdFromChildId(current_index)]; } else { const TreeNode &node{Tree[current_index]}; // iterate backwards in childs, to get depth-first search in tree, from the beginning std::for_each(node.child_ids.rbegin(), node.child_ids.rend(), [&](int32_t child){ todo.push_back(child); }); } } return result; }; namespace { std::unordered_set pp_types { "identifier", "pp-number", "character-literal", "user-defined-character-literal", "string-literal", "user-defined-string-literal", "preprocessing-op-or-punc" }; std::unordered_set keywords { "alignas", "alignof", "asm", "auto", "bool", "break", "case", "catch", "char", "char8_t", "char16_t", "char32_t", "class", "concept", "const", "consteval", "constexpr", "constinit", "const_cast", "continue", "co_await", "co_return", "co_yield", "decltype", "default", "delete", "do", "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable", "namespace", "new", "noexcept", "nullptr", "operator", "private", "protected", "public", "register", "reinterpret_cast", "requires", "return", "short", "signed", "sizeof", "static", "static_assert", "static_cast", "struct", "switch", "template", "this", "thread_local", "throw", "true", "try", "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", "void", "volatile", "wchar_t", "while", }; } // Phase 7.a: Create tokens from preprocessing tokens std::vector CPP::tokens_from_pptokens(const std::vector& pp_tokens) { std::vector result; // "identifier" + value -> "identifier" + value, except identifiers from table 5.11, p.14 -> keyword as value, value // "pp-number" + value -> "literal" + value // "character-literal" -> "literal" + value // "user-defined-character-literal" -> "literal" + value // "string-literal" -> "literal" + value // "user-defined-string-literal" -> "literal" + value // "preprocessing-op-or-punc" -> value+value (operator,punctuator) for (auto& token: pp_tokens) { if (pp_types.find(token.type) != pp_types.end()) { if (token.type == "identifier") { if (keywords.find(token.value) != keywords.end()) result.emplace_back(Token{token.value, token.value}); else result.emplace_back(Token{"identifier"s, token.value}); } else if (token.type == "preprocessing-op-or-punc") result.emplace_back(Token{token.value, token.value}); else result.emplace_back(Token{"literal", token.value}); } else throw std::runtime_error("Unhandled preprocessing token: "s + token.value + " ("s + token.type + ")"s); } return result; } // Phase 7.b: Grammar Analysis std::vector CPP::analysis(const std::vector& tokens) { auto bnf = SubBNF(CPPBNF::GetCppBNFGram(), "translation-unit"); Gram::Compiler compiler(bnf, "translation-unit"); return compiler.compile(tokens); } namespace { CPP::map_type map_translation_unit { //{"top-level-declaration-seq", [](){}}, {"top-level-declaration-seq/top-level-declaration/declaration/function-definition", [](){}}, }; } // anonymous namespace void CPP::traverse(index_t node_id, map_type& map) { // TODO } // Phase 7.c: Translate void CPP::translate() { if (m_nodes.size() == 0) throw std::runtime_error("ICE: Tree is empty"); traverse(0, map_translation_unit); } // Phase 8: Instantiate objects void CPP::instantiate() { // TODO } // Phase 9: Link libraries void CPP::link() { // TODO } // phases of translation, according to standard void CPP::compile(const std::string& code) { source_charset_map(); backslash_escape(); auto pp_tokens = preprocessing_tokenize(code); preprocess(); execution_charset_map(); concatenate_strings(); auto tokens = tokens_from_pptokens(pp_tokens); m_nodes = analysis(tokens); translate(); instantiate(); link(); } std::vector CPP::getCode() { // TODO return { 0x48, 0xc7, 0xc0, 0x3c, 0x00, 0x00, 0x00, // mov $0x3c,%rax # syscall 60 0x48, 0x31, 0xff, // xor %rdi,%rdi # exit code 0 0x0f, 0x05, // syscall }; } std::vector CPP::getData() { return {}; // TODO }