Implement instruction class
This commit is contained in:
parent
02afb71c84
commit
fc035bd7a7
|
@ -4,7 +4,7 @@ project(biscuit_interpreter)
|
||||||
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
add_executable(biscuit_interpreter)
|
add_executable(biscuit_interpreter src/common.hpp)
|
||||||
|
|
||||||
target_sources( biscuit_interpreter PRIVATE
|
target_sources( biscuit_interpreter PRIVATE
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
|
|
19
src/common.hpp
Normal file
19
src/common.hpp
Normal file
|
@ -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
|
|
@ -1,6 +1,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
#include "keywords.hpp"
|
#include "keywords.hpp"
|
||||||
|
|
||||||
const std::vector<Keyword> keywords =
|
const std::vector<Keyword> keywords =
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include "parse.hpp"
|
|
||||||
|
#include "common.hpp"
|
||||||
|
|
||||||
struct Keyword
|
struct Keyword
|
||||||
{
|
{
|
||||||
|
|
14
src/main.cpp
14
src/main.cpp
|
@ -1,10 +1,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <array>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <exception>
|
|
||||||
|
|
||||||
#include "parse.hpp"
|
#include "parse.hpp"
|
||||||
|
|
||||||
|
@ -31,12 +28,14 @@ int main(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
std::ifstream infile = get_infile(argc, argv);
|
std::ifstream infile = get_infile(argc, argv);
|
||||||
std::string word;
|
std::string word;
|
||||||
|
std::vector<Token> tokens;
|
||||||
|
|
||||||
while(infile >> word)
|
while(infile >> word)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Symbol sym(word);
|
Token token(word);
|
||||||
sym.print();
|
tokens.push_back(token);
|
||||||
}
|
}
|
||||||
catch(MalformedIdentifierExcept& exc)
|
catch(MalformedIdentifierExcept& exc)
|
||||||
{
|
{
|
||||||
|
@ -50,12 +49,15 @@ int main(int argc, char * argv[])
|
||||||
<< "\nAborting..." << std::endl;
|
<< "\nAborting..." << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
catch(WrongSymbolExcept& exc)
|
catch(WrongTokenExcept& exc)
|
||||||
{
|
{
|
||||||
std::cout << "Wrong symbol type\n Aborting..." << std::endl;
|
std::cout << "Wrong symbol type\n Aborting..." << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Instruction instr(tokens);
|
||||||
|
instr.print();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <array>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "keywords.hpp"
|
#include "keywords.hpp"
|
||||||
#include "parse.hpp"
|
#include "parse.hpp"
|
||||||
|
#include "common.hpp"
|
||||||
|
|
||||||
|
|
||||||
bool is_keyword(std::string str)
|
bool is_keyword(std::string str)
|
||||||
{
|
{
|
||||||
|
@ -85,6 +87,7 @@ bool Token::parse_as_identifier(const std::string &str)
|
||||||
{
|
{
|
||||||
type = TokenType::IDENTIFIER;
|
type = TokenType::IDENTIFIER;
|
||||||
val_string = str;
|
val_string = str;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -105,44 +108,81 @@ void Token::print() const
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case TokenType::IDENTIFIER:
|
case TokenType::IDENTIFIER:
|
||||||
std::cout << "Identifier: \"" << val_string << "\"";
|
std::cerr << "Identifier: \"" << val_string << "\"";
|
||||||
break;
|
break;
|
||||||
case TokenType::KEYWORD:
|
case TokenType::KEYWORD:
|
||||||
std::cout << "Keyword: \"" << val_string << "\"";
|
std::cerr << "Keyword: \"" << val_string << "\"";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TokenType::LITERAL:
|
case TokenType::LITERAL:
|
||||||
std::cout << "Literal of type ";
|
std::cerr << "Literal of type ";
|
||||||
if(literal_type == ValueType::DECIMAL)
|
if(literal_type == ValueType::DECIMAL)
|
||||||
std::cout << "decimal: " << val_float;
|
std::cerr << "decimal: " << val_float;
|
||||||
else if(literal_type == ValueType::STRING)
|
else if(literal_type == ValueType::STRING)
|
||||||
std::cout << "string: \"" << val_string << "\"";
|
std::cerr << "string: \"" << val_string << "\"";
|
||||||
break;
|
break;
|
||||||
case TokenType::ID_OR_LIT:
|
case TokenType::ID_OR_LIT:
|
||||||
std::cerr << "Identifier or Literal?! Something went terribly wrong!!";
|
std::cerr << "Identifier or Literal?! Something went terribly wrong!!";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << std::endl;
|
std::cerr << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Instruction::Instruction(std::vector<Token>& _token_list)
|
Instruction::Instruction(std::vector<Token>& _token_list)
|
||||||
{
|
{
|
||||||
|
// move over the tokens
|
||||||
tokens = std::move(_token_list);
|
tokens = std::move(_token_list);
|
||||||
|
|
||||||
// resolve our keyword
|
// resolve our keyword
|
||||||
auto keyword_it = std::find(keywords.begin(), keywords.end(), tokens[0].val_string);
|
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
|
// Throw if unknown
|
||||||
if(keyword_it == keywords.end())
|
if(keyword_it == keywords.end())
|
||||||
throw UnknownKeywordExcept(tokens[0].val_string);
|
throw UnknownKeywordExcept(tokens[0].val_string);
|
||||||
else
|
else
|
||||||
keyword_ptr = &*keyword_it;
|
keyword_ptr = &(*keyword_it);
|
||||||
|
|
||||||
// Make sure the keyword gets the number of arguments it needs
|
// 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))
|
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);
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,22 +4,9 @@
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "keywords.hpp"
|
#include "keywords.hpp"
|
||||||
|
#include "common.hpp"
|
||||||
enum TokenType
|
|
||||||
{
|
|
||||||
KEYWORD,
|
|
||||||
IDENTIFIER,
|
|
||||||
LITERAL,
|
|
||||||
ID_OR_LIT
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ValueType
|
|
||||||
{
|
|
||||||
STRING,
|
|
||||||
DECIMAL,
|
|
||||||
ANY
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MalformedIdentifierExcept : public std::exception
|
struct MalformedIdentifierExcept : public std::exception
|
||||||
{
|
{
|
||||||
|
@ -46,17 +33,17 @@ struct WrongArgumentCountExcept : public std::exception
|
||||||
struct WrongTokenExcept : public std::exception
|
struct WrongTokenExcept : public std::exception
|
||||||
{
|
{
|
||||||
TokenType expected, got;
|
TokenType expected, got;
|
||||||
std::string keyword_name;
|
std::string keyword_name, token_str;
|
||||||
WrongTokenExcept(std::string _name, const TokenType& _expected, const TokenType& _got)
|
WrongTokenExcept(std::string _keyword_name, std::string _token_str, const TokenType& _expected, const TokenType& _got)
|
||||||
: expected(_expected), got(_got), keyword_name(_name) {}
|
: expected(_expected), got(_got), keyword_name(_keyword_name), token_str(_token_str) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TypeErrorExcept : public std::exception
|
struct TypeErrorExcept : public std::exception
|
||||||
{
|
{
|
||||||
ValueType expected, got;
|
ValueType expected, got;
|
||||||
std::string keyword_name;
|
std::string keyword_name, token_str;
|
||||||
TypeErrorExcept(std::string _name, const ValueType& _expected, const ValueType& _got)
|
TypeErrorExcept(std::string _keyword_name, std::string _token_str, const ValueType& _expected, const ValueType& _got)
|
||||||
: expected(_expected), got(_got), keyword_name(_name) {}
|
: expected(_expected), got(_got), keyword_name(_keyword_name), token_str(_token_str) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -84,11 +71,12 @@ public:
|
||||||
class Instruction
|
class Instruction
|
||||||
{
|
{
|
||||||
std::vector<Token> tokens;
|
std::vector<Token> tokens;
|
||||||
Keyword *keyword_ptr;
|
const Keyword * keyword_ptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Try to parse a list of symbols as instructions
|
// Try to parse a list of symbols as instructions
|
||||||
Instruction(std::vector<Token>& _token_list);
|
Instruction(std::vector<Token>& _token_list);
|
||||||
|
void print();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
#ifndef BISCUIT_RUNTIME_HPP_INCLUDED
|
|
||||||
#define BISCUIT_RUNTIME_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
struct Context
|
|
||||||
{
|
|
||||||
std::vector<
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in a new issue