Binary and hex notation
This commit is contained in:
parent
3e5ba29283
commit
92cd4e542a
@ -20,4 +20,6 @@ private:
|
|||||||
bool isEqual(sptr(Object) a, sptr(Object) b);
|
bool isEqual(sptr(Object) a, sptr(Object) b);
|
||||||
|
|
||||||
std::string stringify(sptr(Object) object);
|
std::string stringify(sptr(Object) object);
|
||||||
|
|
||||||
|
bool isWholeNumer(double num);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -58,5 +58,8 @@ private:
|
|||||||
std::vector<char> src;
|
std::vector<char> src;
|
||||||
private:
|
private:
|
||||||
bool matchOn(char expected);
|
bool matchOn(char expected);
|
||||||
void advance();
|
|
||||||
|
char peekNext();
|
||||||
|
|
||||||
|
void advance(int by = 1);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
std::vector<std::string> splitString(const std::string& input, std::string delimiter) {
|
std::vector<std::string> splitString(const std::string& input, std::string delimiter) {
|
||||||
std::vector<std::string> tokens;
|
std::vector<std::string> tokens;
|
||||||
@ -50,3 +51,17 @@ std::string replaceSubstring(const std::string& str, const std::string& findSubs
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isHexDigit(char c) {
|
||||||
|
return (std::isdigit(c) || (std::isxdigit(c) && std::islower(c)));
|
||||||
|
}
|
||||||
|
|
||||||
|
u_long binaryStringToLong(const std::string& binaryString) {
|
||||||
|
std::string binaryDigits = binaryString.substr(2); // Remove the '0b' prefix
|
||||||
|
u_long result = 0;
|
||||||
|
for (char ch : binaryDigits) {
|
||||||
|
result <<= 1;
|
||||||
|
result += (ch - '0');
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@ -1 +1,3 @@
|
|||||||
10 + 10
|
//10 + 10
|
||||||
|
//0xFF + 0xFF
|
||||||
|
0xFF + 0xFF00 == 0xFFFF
|
||||||
@ -7,11 +7,23 @@
|
|||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include "../headers/Interpreter.h"
|
#include "../headers/Interpreter.h"
|
||||||
|
#include "../headers/helperFunctions/HelperFunctions.h"
|
||||||
|
|
||||||
|
|
||||||
sptr(Object) Interpreter::visitLiteralExpr(sptr(LiteralExpr) expr) {
|
sptr(Object) Interpreter::visitLiteralExpr(sptr(LiteralExpr) expr) {
|
||||||
if(expr->isNull) return msptr(None)();
|
if(expr->isNull) return msptr(None)();
|
||||||
if(expr->isNumber) return msptr(Number)(std::stod(expr->value));
|
if(expr->isNumber){
|
||||||
|
double num;
|
||||||
|
if(expr->value[1] == 'b')
|
||||||
|
{
|
||||||
|
num = binaryStringToLong(expr->value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
num = std::stod(expr->value);
|
||||||
|
}
|
||||||
|
return msptr(Number)(num);
|
||||||
|
}
|
||||||
return msptr(String)(expr->value);
|
return msptr(String)(expr->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,10 +98,38 @@ sptr(Object) Interpreter::visitBinaryExpr(sptr(BinaryExpr) expression)
|
|||||||
}
|
}
|
||||||
else if(std::dynamic_pointer_cast<String>(left) && std::dynamic_pointer_cast<String>(right))
|
else if(std::dynamic_pointer_cast<String>(left) && std::dynamic_pointer_cast<String>(right))
|
||||||
{
|
{
|
||||||
|
switch (expression->oper.type) {
|
||||||
|
case PLUS:
|
||||||
std::string left_string = std::dynamic_pointer_cast<String>(left)->value;
|
std::string left_string = std::dynamic_pointer_cast<String>(left)->value;
|
||||||
std::string right_string = std::dynamic_pointer_cast<String>(right)->value;
|
std::string right_string = std::dynamic_pointer_cast<String>(right)->value;
|
||||||
return msptr(String)(left_string + right_string);
|
return msptr(String)(left_string + right_string);
|
||||||
}
|
}
|
||||||
|
throw std::runtime_error("Cannot use '" + expression->oper.lexeme + "' on two strings");
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(std::dynamic_pointer_cast<String>(left) && std::dynamic_pointer_cast<Number>(right))
|
||||||
|
{
|
||||||
|
switch (expression->oper.type) {
|
||||||
|
case STAR:
|
||||||
|
std::string left_string = std::dynamic_pointer_cast<String>(left)->value;
|
||||||
|
double right_number = std::dynamic_pointer_cast<Number>(right)->value;
|
||||||
|
if(isWholeNumer(right_number))
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
for (int i = 0; i < (int)right_number; ++i) {
|
||||||
|
ss << left_string;
|
||||||
|
}
|
||||||
|
return msptr(String)(ss.str());
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw std::runtime_error("String multiplier must be whole number");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw std::runtime_error("Cannot use '" + expression->oper.lexeme + "' on a string and a number");
|
||||||
|
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Operands must be of same type when using: " + expression->oper.lexeme);
|
throw std::runtime_error("Operands must be of same type when using: " + expression->oper.lexeme);
|
||||||
@ -158,7 +198,7 @@ bool Interpreter::isEqual(sptr(Object) a, sptr(Object) b) {
|
|||||||
void Interpreter::interpret(std::shared_ptr<Expr> expr) {
|
void Interpreter::interpret(std::shared_ptr<Expr> expr) {
|
||||||
|
|
||||||
sptr(Object) value = evaluate(std::move(expr));
|
sptr(Object) value = evaluate(std::move(expr));
|
||||||
std::cout << stringify(value) << std::endl;
|
std::cout << "\033[0;32m" << stringify(value) << std::endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,7 +221,7 @@ std::string Interpreter::stringify(std::shared_ptr<Object> object) {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ss << std::fixed << std::setprecision(std::numeric_limits<double>::digits10) << num->value;\
|
ss << std::fixed << std::setprecision(std::numeric_limits<double>::digits10 - 1) << num->value;
|
||||||
std::string str = ss.str();
|
std::string str = ss.str();
|
||||||
str.erase(str.find_last_not_of('0') + 1, std::string::npos);
|
str.erase(str.find_last_not_of('0') + 1, std::string::npos);
|
||||||
if (str.back() == '.') {
|
if (str.back() == '.') {
|
||||||
@ -201,6 +241,20 @@ std::string Interpreter::stringify(std::shared_ptr<Object> object) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Interpreter::isWholeNumer(double num) {
|
||||||
|
double integral = num;
|
||||||
|
double fractional = std::modf(num, &integral);
|
||||||
|
|
||||||
|
if(std::abs(fractional) < std::numeric_limits<double>::epsilon())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -124,6 +124,7 @@ std::vector<Token> Lexer::Tokenize(std::string source){
|
|||||||
advance();
|
advance();
|
||||||
while(!src.empty() && src[0] != '"')
|
while(!src.empty() && src[0] != '"')
|
||||||
{
|
{
|
||||||
|
|
||||||
if(src[0] == '\n') line++;
|
if(src[0] == '\n') line++;
|
||||||
str += src[0];
|
str += src[0];
|
||||||
advance();
|
advance();
|
||||||
@ -148,33 +149,80 @@ std::vector<Token> Lexer::Tokenize(std::string source){
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
bool isNotation = false;
|
||||||
|
bool notationInvalidated = false;
|
||||||
|
char notationChar;
|
||||||
//Multi char tokens
|
//Multi char tokens
|
||||||
if(std::isdigit(t))
|
if(std::isdigit(t))
|
||||||
{
|
{
|
||||||
std::string num;
|
std::string num;
|
||||||
while(!src.empty() && std::isdigit(src[0]))
|
|
||||||
|
if(src[0] != '0') notationInvalidated = true;
|
||||||
|
|
||||||
|
while(!src.empty())
|
||||||
{
|
{
|
||||||
|
if(std::isdigit(src[0]))
|
||||||
|
{
|
||||||
|
if(src[0] == '0' && !notationInvalidated)
|
||||||
|
{
|
||||||
|
if(peekNext() == 'b' || peekNext() == 'x') {
|
||||||
|
num += "0";
|
||||||
|
num += peekNext();
|
||||||
|
notationChar = peekNext();
|
||||||
|
advance(2);
|
||||||
|
isNotation = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
num += src[0];
|
||||||
|
advance();
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if(!isNotation) {
|
||||||
|
if (!src.empty() && src[0] == '.') {
|
||||||
|
advance();
|
||||||
|
if (!src.empty() && std::isdigit(src[0])) {
|
||||||
|
num += '.';
|
||||||
|
while (!src.empty() && std::isdigit(src[0])) {
|
||||||
num += src[0];
|
num += src[0];
|
||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("LEXER: malformed number at: " + std::to_string(this->line));
|
||||||
|
}
|
||||||
|
|
||||||
if(!src.empty() && src[0] == '.')
|
|
||||||
{
|
|
||||||
advance();
|
|
||||||
if(!src.empty() && std::isdigit(src[0]))
|
|
||||||
{
|
|
||||||
num += '.';
|
|
||||||
while(!src.empty() && std::isdigit(src[0]))
|
|
||||||
{
|
|
||||||
num += src[0];
|
|
||||||
advance();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw std::runtime_error("LEXER: malformed number at: " + std::to_string(this->line));
|
if(!src.empty() && ishexnumber(src[0]))
|
||||||
|
{
|
||||||
|
if(notationChar == 'b') {
|
||||||
|
while (!src.empty() && (src[0] == '0' || src[0] == '1')) {
|
||||||
|
num += src[0];
|
||||||
|
advance();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if(notationChar == 'x')
|
||||||
|
{
|
||||||
|
while (!src.empty() && ishexnumber(src[0])) {
|
||||||
|
|
||||||
|
num += src[0];
|
||||||
|
advance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw std::runtime_error("LEXER: malformed notation at: " + std::to_string(this->line));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tokens.push_back(Token{NUMBER, num, line});
|
tokens.push_back(Token{NUMBER, num, line});
|
||||||
@ -224,7 +272,19 @@ bool Lexer::matchOn(char expected)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lexer::advance()
|
void Lexer::advance(int by)
|
||||||
{
|
{
|
||||||
|
for (int i = 0; i < by; ++i) {
|
||||||
src.erase(src.begin());
|
src.erase(src.begin());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char Lexer::peekNext()
|
||||||
|
{
|
||||||
|
if(src.size() > 1)
|
||||||
|
{
|
||||||
|
return src[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@ void Bob::runPrompt()
|
|||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
string line;
|
string line;
|
||||||
cout << "-> ";
|
cout << "\033[0;36m" << "-> " << "\033[0;37m";
|
||||||
std::getline(std::cin, line);
|
std::getline(std::cin, line);
|
||||||
|
|
||||||
if(std::cin.eof())
|
if(std::cin.eof())
|
||||||
@ -52,10 +52,13 @@ void Bob::run(string source)
|
|||||||
Parser p(tokens);
|
Parser p(tokens);
|
||||||
shared_ptr<Expr> expr = p.parse();
|
shared_ptr<Expr> expr = p.parse();
|
||||||
interpreter.interpret(expr);
|
interpreter.interpret(expr);
|
||||||
|
//cout << "=========================" << endl;
|
||||||
|
ASTPrinter printer;
|
||||||
|
|
||||||
|
//cout << dynamic_pointer_cast<String>(printer.print(expr))->value << endl;
|
||||||
|
|
||||||
for(Token t : tokens){
|
for(Token t : tokens){
|
||||||
cout << "{type: " << t.type << ", value: " << t.lexeme << "}" << endl;
|
//cout << "{type: " << t.type << ", value: " << t.lexeme << "}" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user