Binary and hex notation

This commit is contained in:
Bobby Lucero 2023-05-27 20:12:30 -04:00
parent 3e5ba29283
commit 92cd4e542a
7 changed files with 165 additions and 26 deletions

View File

@ -20,4 +20,6 @@ private:
bool isEqual(sptr(Object) a, sptr(Object) b);
std::string stringify(sptr(Object) object);
bool isWholeNumer(double num);
};

View File

@ -58,5 +58,8 @@ private:
std::vector<char> src;
private:
bool matchOn(char expected);
void advance();
char peekNext();
void advance(int by = 1);
};

View File

@ -2,6 +2,7 @@
#include <iostream>
#include <vector>
#include <bitset>
std::vector<std::string> splitString(const std::string& input, std::string delimiter) {
std::vector<std::string> tokens;
@ -50,3 +51,17 @@ std::string replaceSubstring(const std::string& str, const std::string& findSubs
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;
}

View File

@ -1 +1,3 @@
10 + 10
//10 + 10
//0xFF + 0xFF
0xFF + 0xFF00 == 0xFFFF

View File

@ -7,11 +7,23 @@
#include <iomanip>
#include <limits>
#include "../headers/Interpreter.h"
#include "../headers/helperFunctions/HelperFunctions.h"
sptr(Object) Interpreter::visitLiteralExpr(sptr(LiteralExpr) expr) {
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);
}
@ -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))
{
switch (expression->oper.type) {
case PLUS:
std::string left_string = std::dynamic_pointer_cast<String>(left)->value;
std::string right_string = std::dynamic_pointer_cast<String>(right)->value;
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
{
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) {
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
{
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();
str.erase(str.find_last_not_of('0') + 1, std::string::npos);
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;
}
}

View File

@ -124,6 +124,7 @@ std::vector<Token> Lexer::Tokenize(std::string source){
advance();
while(!src.empty() && src[0] != '"')
{
if(src[0] == '\n') line++;
str += src[0];
advance();
@ -148,33 +149,80 @@ std::vector<Token> Lexer::Tokenize(std::string source){
}
else
{
bool isNotation = false;
bool notationInvalidated = false;
char notationChar;
//Multi char tokens
if(std::isdigit(t))
{
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];
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
{
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});
@ -224,7 +272,19 @@ bool Lexer::matchOn(char expected)
return true;
}
void Lexer::advance()
void Lexer::advance(int by)
{
for (int i = 0; i < by; ++i) {
src.erase(src.begin());
}
}
char Lexer::peekNext()
{
if(src.size() > 1)
{
return src[1];
}
}

View File

@ -27,7 +27,7 @@ void Bob::runPrompt()
for(;;)
{
string line;
cout << "-> ";
cout << "\033[0;36m" << "-> " << "\033[0;37m";
std::getline(std::cin, line);
if(std::cin.eof())
@ -52,10 +52,13 @@ void Bob::run(string source)
Parser p(tokens);
shared_ptr<Expr> expr = p.parse();
interpreter.interpret(expr);
//cout << "=========================" << endl;
ASTPrinter printer;
//cout << dynamic_pointer_cast<String>(printer.print(expr))->value << endl;
for(Token t : tokens){
cout << "{type: " << t.type << ", value: " << t.lexeme << "}" << endl;
//cout << "{type: " << t.type << ", value: " << t.lexeme << "}" << endl;
}