From fc035bd7a78bdb5683c21c628a5fe4699dd6d5d6 Mon Sep 17 00:00:00 2001 From: Hans Date: Sat, 6 Nov 2021 02:31:33 +0100 Subject: [PATCH] Implement instruction class --- CMakeLists.txt | 2 +- src/common.hpp | 19 +++++++++++++++ src/keywords.cpp | 1 + src/keywords.hpp | 3 ++- src/main.cpp | 14 ++++++----- src/parse.cpp | 62 +++++++++++++++++++++++++++++++++++++++--------- src/parse.hpp | 32 ++++++++----------------- src/runtime.hpp | 11 --------- 8 files changed, 92 insertions(+), 52 deletions(-) create mode 100644 src/common.hpp delete mode 100644 src/runtime.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f2a16a..03df932 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(biscuit_interpreter) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -add_executable(biscuit_interpreter) +add_executable(biscuit_interpreter src/common.hpp) target_sources( biscuit_interpreter PRIVATE src/main.cpp diff --git a/src/common.hpp b/src/common.hpp new file mode 100644 index 0000000..b64eada --- /dev/null +++ b/src/common.hpp @@ -0,0 +1,19 @@ +#ifndef BISCUIT_INTERPRETER_COMMON_HPP +#define BISCUIT_INTERPRETER_COMMON_HPP + +enum TokenType +{ + KEYWORD, + IDENTIFIER, + LITERAL, + ID_OR_LIT +}; + +enum ValueType +{ + STRING, + DECIMAL, + ANY +}; + +#endif //BISCUIT_INTERPRETER_COMMON_HPP diff --git a/src/keywords.cpp b/src/keywords.cpp index 38ddd42..7612481 100644 --- a/src/keywords.cpp +++ b/src/keywords.cpp @@ -1,6 +1,7 @@ #include #include +#include "common.hpp" #include "keywords.hpp" const std::vector keywords = diff --git a/src/keywords.hpp b/src/keywords.hpp index 385cab0..3230335 100644 --- a/src/keywords.hpp +++ b/src/keywords.hpp @@ -4,7 +4,8 @@ #include #include #include -#include "parse.hpp" + +#include "common.hpp" struct Keyword { diff --git a/src/main.cpp b/src/main.cpp index 247b465..76757a1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,10 +1,7 @@ #include -#include #include -#include #include #include -#include #include "parse.hpp" @@ -31,12 +28,14 @@ int main(int argc, char * argv[]) { std::ifstream infile = get_infile(argc, argv); std::string word; + std::vector tokens; + while(infile >> word) { try { - Symbol sym(word); - sym.print(); + Token token(word); + tokens.push_back(token); } catch(MalformedIdentifierExcept& exc) { @@ -50,12 +49,15 @@ int main(int argc, char * argv[]) << "\nAborting..." << std::endl; exit(EXIT_FAILURE); } - catch(WrongSymbolExcept& exc) + catch(WrongTokenExcept& exc) { std::cout << "Wrong symbol type\n Aborting..." << std::endl; exit(EXIT_FAILURE); } } + Instruction instr(tokens); + instr.print(); + return 0; } diff --git a/src/parse.cpp b/src/parse.cpp index 2d2c777..631ec86 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -1,9 +1,11 @@ #include #include -#include +#include #include "keywords.hpp" #include "parse.hpp" +#include "common.hpp" + bool is_keyword(std::string str) { @@ -85,6 +87,7 @@ bool Token::parse_as_identifier(const std::string &str) { type = TokenType::IDENTIFIER; val_string = str; + return true; } return false; } @@ -105,44 +108,81 @@ void Token::print() const switch(type) { case TokenType::IDENTIFIER: - std::cout << "Identifier: \"" << val_string << "\""; + std::cerr << "Identifier: \"" << val_string << "\""; break; case TokenType::KEYWORD: - std::cout << "Keyword: \"" << val_string << "\""; + std::cerr << "Keyword: \"" << val_string << "\""; break; case TokenType::LITERAL: - std::cout << "Literal of type "; + std::cerr << "Literal of type "; if(literal_type == ValueType::DECIMAL) - std::cout << "decimal: " << val_float; + std::cerr << "decimal: " << val_float; else if(literal_type == ValueType::STRING) - std::cout << "string: \"" << val_string << "\""; + std::cerr << "string: \"" << val_string << "\""; break; case TokenType::ID_OR_LIT: std::cerr << "Identifier or Literal?! Something went terribly wrong!!"; } - std::cout << std::endl; + std::cerr << std::endl; } Instruction::Instruction(std::vector& _token_list) { + // move over the tokens tokens = std::move(_token_list); - // resolve our keyword - auto keyword_it = std::find(keywords.begin(), keywords.end(), tokens[0].val_string); + // resolve our keyword + auto keyword_it = std::find_if(keywords.begin(), keywords.end(), [&, this](auto& v){ + if(v.name == tokens[0].val_string) + return true; + else + return false; + }); // Throw if unknown if(keyword_it == keywords.end()) throw UnknownKeywordExcept(tokens[0].val_string); else - keyword_ptr = &*keyword_it; + keyword_ptr = &(*keyword_it); // Make sure the keyword gets the number of arguments it needs if(keyword_ptr->expected_num_args != -1 && (keyword_ptr->expected_num_args != tokens.size() - 1)) throw WrongArgumentCountExcept(keyword_ptr->name, keyword_ptr->expected_num_args, tokens.size() - 1); - + // Check the arguments supplied are the right kind of tokens + for(int i = 0; i < keyword_ptr->expected_num_args; i++) + { + if(keyword_ptr->expected_token_types[i] != tokens[i+1].type) + throw WrongTokenExcept(keyword_ptr->name, tokens[i+1].val_string, keyword_ptr->expected_token_types[i], + tokens[i+1].type); + } + + // if arbitrary number of args are expected, they're all one type + if(keyword_ptr->expected_num_args == -1) + { + for (auto it = tokens.begin() + 1; it != tokens.end(); it++) + { + if (keyword_ptr->expected_token_types[0] != it->type) + throw WrongTokenExcept(keyword_ptr->name, it->val_string, keyword_ptr->expected_token_types[0], + it->type); + } + } + + // If all checks succeeded, we consider this Instruction valid. Note that type checking occurs later at + // runtime, when the instruction is executed. + // We now get rid of the keyword token to save some space. + tokens.erase(tokens.begin()); +} + +void Instruction::print() +{ + std::cerr << "INSTRUCTION: " << keyword_ptr->name << "\n"; + for(auto& token : tokens) + token.print(); + + std::cerr << std::endl; } diff --git a/src/parse.hpp b/src/parse.hpp index aea1bf8..9bce45e 100644 --- a/src/parse.hpp +++ b/src/parse.hpp @@ -4,22 +4,9 @@ #include #include #include + #include "keywords.hpp" - -enum TokenType -{ - KEYWORD, - IDENTIFIER, - LITERAL, - ID_OR_LIT -}; - -enum ValueType -{ - STRING, - DECIMAL, - ANY -}; +#include "common.hpp" struct MalformedIdentifierExcept : public std::exception { @@ -46,17 +33,17 @@ struct WrongArgumentCountExcept : public std::exception struct WrongTokenExcept : public std::exception { TokenType expected, got; - std::string keyword_name; - WrongTokenExcept(std::string _name, const TokenType& _expected, const TokenType& _got) - : expected(_expected), got(_got), keyword_name(_name) {} + std::string keyword_name, token_str; + WrongTokenExcept(std::string _keyword_name, std::string _token_str, const TokenType& _expected, const TokenType& _got) + : expected(_expected), got(_got), keyword_name(_keyword_name), token_str(_token_str) {} }; struct TypeErrorExcept : public std::exception { ValueType expected, got; - std::string keyword_name; - TypeErrorExcept(std::string _name, const ValueType& _expected, const ValueType& _got) - : expected(_expected), got(_got), keyword_name(_name) {} + std::string keyword_name, token_str; + TypeErrorExcept(std::string _keyword_name, std::string _token_str, const ValueType& _expected, const ValueType& _got) + : expected(_expected), got(_got), keyword_name(_keyword_name), token_str(_token_str) {} }; @@ -84,11 +71,12 @@ public: class Instruction { std::vector tokens; - Keyword *keyword_ptr; + const Keyword * keyword_ptr; public: // Try to parse a list of symbols as instructions Instruction(std::vector& _token_list); + void print(); }; #endif diff --git a/src/runtime.hpp b/src/runtime.hpp deleted file mode 100644 index 434deb3..0000000 --- a/src/runtime.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef BISCUIT_RUNTIME_HPP_INCLUDED -#define BISCUIT_RUNTIME_HPP_INCLUDED - -#include - -struct Context -{ - std::vector< -}; - -#endif