From 02afb71c84209edc6e56c4424a2aae4e30b9ad2b Mon Sep 17 00:00:00 2001 From: hans Date: Sat, 6 Nov 2021 00:24:04 +0100 Subject: [PATCH] Initial commit --- .gitignore | 1 + CMakeLists.txt | 14 ++++ biscuit_doc.odt | Bin 0 -> 13876 bytes examples/helloworld.bisc | 2 + src/.ycm_extra_conf.py | 18 +++++ src/keywords.cpp | 18 +++++ src/keywords.hpp | 20 ++++++ src/main.cpp | 61 ++++++++++++++++ src/parse.cpp | 148 +++++++++++++++++++++++++++++++++++++++ src/parse.hpp | 94 +++++++++++++++++++++++++ src/runtime.hpp | 11 +++ 11 files changed, 387 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 biscuit_doc.odt create mode 100644 examples/helloworld.bisc create mode 100644 src/.ycm_extra_conf.py create mode 100644 src/keywords.cpp create mode 100644 src/keywords.hpp create mode 100644 src/main.cpp create mode 100644 src/parse.cpp create mode 100644 src/parse.hpp create mode 100644 src/runtime.hpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..378eac2 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..2f2a16a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.10) + +project(biscuit_interpreter) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +add_executable(biscuit_interpreter) + +target_sources( biscuit_interpreter PRIVATE + src/main.cpp + src/parse.cpp + src/keywords.cpp ) + +include_directories(${CMAKE_SOURCE_DIR}) diff --git a/biscuit_doc.odt b/biscuit_doc.odt new file mode 100644 index 0000000000000000000000000000000000000000..3036d759dcec47b91128df9f9ba62bae13745598 GIT binary patch literal 13876 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 R2Qu{gzv6r3a$ +#include + +#include "keywords.hpp" + +const std::vector keywords = +{ + { + .name = "print", + .expected_num_args = -1, + .expected_token_types = {TokenType::ID_OR_LIT}, + .expected_value_types = {ValueType::ANY} + }, + { + .name = "exit", + .expected_num_args = 0 + } +}; diff --git a/src/keywords.hpp b/src/keywords.hpp new file mode 100644 index 0000000..385cab0 --- /dev/null +++ b/src/keywords.hpp @@ -0,0 +1,20 @@ +#ifndef BISCUIT_KEYWORDS_HPP_INCLUDED +#define BISCUIT_KEYWORDS_HPP_INCLUDED + +#include +#include +#include +#include "parse.hpp" + +struct Keyword +{ + const std::string name; + const int expected_num_args; // -1 means: 1 to infinity, in which case all args are of same type + + const std::vector expected_token_types; + const std::vector expected_value_types; +}; + +extern const std::vector keywords; + +#endif diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..247b465 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "parse.hpp" + +std::ifstream get_infile(int argc, char ** argv) +{ + if(argc != 2) + { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + exit(EXIT_FAILURE); + } + + std::ifstream infile(argv[1]); + + if(!infile) + { + std::cerr << "Could not open '" << argv[1] << "'" << std::endl; + exit(EXIT_FAILURE); + } + + return infile; +} + +int main(int argc, char * argv[]) +{ + std::ifstream infile = get_infile(argc, argv); + std::string word; + while(infile >> word) + { + try + { + Symbol sym(word); + sym.print(); + } + catch(MalformedIdentifierExcept& exc) + { + std::cout << "Malformed identifier: '" << exc.malformed_str << "'" + << "\nAborting..." << std::endl; + exit(EXIT_FAILURE); + } + catch(UnknownKeywordExcept& exc) + { + std::cout << "Unknown Keyword: '" << exc.unknown_keyword << "'" + << "\nAborting..." << std::endl; + exit(EXIT_FAILURE); + } + catch(WrongSymbolExcept& exc) + { + std::cout << "Wrong symbol type\n Aborting..." << std::endl; + exit(EXIT_FAILURE); + } + } + + return 0; +} diff --git a/src/parse.cpp b/src/parse.cpp new file mode 100644 index 0000000..2d2c777 --- /dev/null +++ b/src/parse.cpp @@ -0,0 +1,148 @@ +#include +#include +#include + +#include "keywords.hpp" +#include "parse.hpp" + +bool is_keyword(std::string str) +{ + for(char &c : str) + c = std::tolower(c); + + for(auto &keyword : keywords) + if(str == keyword.name) + return true; + return 0; +} + +bool is_string_literal(const std::string& str) +{ + if(str[0] == '#') + return true; + else + return false; +} + +bool is_decimal_literal(const std::string& str) +{ + for(const char &c : str) + if(!std::isdigit(c) && c != '.') + return false; + + return true; +} + +bool is_identifier(const std::string& str) +{ + for(const char& c : str) + if(!(std::isalpha(c) || c == '_')) + return false; + return true; +} + + +bool Token::parse_as_keyword(const std::string &str) +{ + if(!is_keyword(str)) + return false; + + type = TokenType::KEYWORD; + val_string = str; + + return true; +} + + +bool Token::parse_as_literal(const std::string &str) +{ + if(is_string_literal(str)) + { + type = TokenType::LITERAL; + literal_type = ValueType::STRING; + auto str_copy = str; + str_copy.erase(0, 1); + val_string = str_copy; + return true; + } + else if(is_decimal_literal(str)) + { + type = TokenType::LITERAL; + literal_type = ValueType::DECIMAL; + val_float = std::stof(str); + val_string = str; + return true; + } + else + { + return false; + } +} + +bool Token::parse_as_identifier(const std::string &str) +{ + if(is_identifier(str)) + { + type = TokenType::IDENTIFIER; + val_string = str; + } + return false; +} + +Token::Token(const std::string &str) +{ + if (parse_as_keyword(str)); + else if(parse_as_literal(str)); + else if(parse_as_identifier(str)); + else + { + throw MalformedIdentifierExcept(str); + } +} + +void Token::print() const +{ + switch(type) + { + case TokenType::IDENTIFIER: + std::cout << "Identifier: \"" << val_string << "\""; + break; + case TokenType::KEYWORD: + std::cout << "Keyword: \"" << val_string << "\""; + break; + + case TokenType::LITERAL: + std::cout << "Literal of type "; + if(literal_type == ValueType::DECIMAL) + std::cout << "decimal: " << val_float; + else if(literal_type == ValueType::STRING) + std::cout << "string: \"" << val_string << "\""; + break; + case TokenType::ID_OR_LIT: + std::cerr << "Identifier or Literal?! Something went terribly wrong!!"; + } + + std::cout << std::endl; +} + + + +Instruction::Instruction(std::vector& _token_list) +{ + tokens = std::move(_token_list); + + // resolve our keyword + auto keyword_it = std::find(keywords.begin(), keywords.end(), tokens[0].val_string); + + // Throw if unknown + if(keyword_it == keywords.end()) + throw UnknownKeywordExcept(tokens[0].val_string); + else + 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); + + +} diff --git a/src/parse.hpp b/src/parse.hpp new file mode 100644 index 0000000..aea1bf8 --- /dev/null +++ b/src/parse.hpp @@ -0,0 +1,94 @@ +#ifndef BISCUIT_PARSE_HPP_INCLUDED +#define BISCUIT_PARSE_HPP_INCLUDED + +#include +#include +#include +#include "keywords.hpp" + +enum TokenType +{ + KEYWORD, + IDENTIFIER, + LITERAL, + ID_OR_LIT +}; + +enum ValueType +{ + STRING, + DECIMAL, + ANY +}; + +struct MalformedIdentifierExcept : public std::exception +{ + std::string malformed_str; + MalformedIdentifierExcept(const std::string& arg_str) + : malformed_str(arg_str) {} +}; + +struct UnknownKeywordExcept : public std::exception +{ + std::string unknown_keyword; + UnknownKeywordExcept(const std::string& arg_str) + : unknown_keyword(arg_str) {} +}; + +struct WrongArgumentCountExcept : public std::exception +{ + int expected, got; + std::string keyword_name; + WrongArgumentCountExcept(std::string _name, int _expected, int _got) + : expected(_expected), got(_got), keyword_name(_name) {} +}; + +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) {} +}; + +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) {} +}; + + +struct Token +{ +private: + bool parse_as_keyword(const std::string &str); + + bool parse_as_literal(const std::string &str); + + // if a word is not a keyword or literal, it must be identifier + bool parse_as_identifier(const std::string &str); + +public: + enum TokenType type; + enum ValueType literal_type; + float val_float; + std::string val_string; + + Token(const std::string &str); + + void print() const; +}; + +class Instruction +{ + std::vector tokens; + Keyword *keyword_ptr; + +public: + // Try to parse a list of symbols as instructions + Instruction(std::vector& _token_list); +}; + +#endif diff --git a/src/runtime.hpp b/src/runtime.hpp new file mode 100644 index 0000000..434deb3 --- /dev/null +++ b/src/runtime.hpp @@ -0,0 +1,11 @@ +#ifndef BISCUIT_RUNTIME_HPP_INCLUDED +#define BISCUIT_RUNTIME_HPP_INCLUDED + +#include + +struct Context +{ + std::vector< +}; + +#endif