Implement String Literals
- String literals can be stored in variables, but are fully immutable and are not compatible with any operators
This commit is contained in:
parent
8cf6177cbc
commit
d8f5b876ac
@ -1,3 +1,5 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
/// Types for binary operators
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum BinOpType {
|
||||
@ -78,6 +80,8 @@ pub enum UnOpType {
|
||||
pub enum Expression {
|
||||
/// Integer literal (64-bit)
|
||||
I64(i64),
|
||||
/// String literal
|
||||
String(Rc<String>),
|
||||
/// Variable
|
||||
Var(String),
|
||||
/// Binary operation. Consists of type, left hand side and right hand side
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
use std::{collections::HashMap, fmt::Display};
|
||||
use std::{collections::HashMap, fmt::Display, rc::Rc};
|
||||
|
||||
use crate::{ast::{Expression, BinOpType, UnOpType, Ast, Statement, If}, parser::parse, lexer::lex};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum Value {
|
||||
I64(i64),
|
||||
String(Rc<String>),
|
||||
}
|
||||
|
||||
pub struct Interpreter {
|
||||
@ -57,7 +58,7 @@ impl Interpreter {
|
||||
|
||||
Statement::Print(expr) => {
|
||||
let result = self.resolve_expr(expr);
|
||||
println!("{}", result);
|
||||
print!("{}", result);
|
||||
}
|
||||
|
||||
Statement::If(If {condition, body_true, body_false}) => {
|
||||
@ -75,6 +76,7 @@ impl Interpreter {
|
||||
fn resolve_expr(&mut self, expr: &Expression) -> Value {
|
||||
match expr {
|
||||
Expression::I64(val) => Value::I64(*val),
|
||||
Expression::String(text) => Value::String(text.clone()),
|
||||
Expression::BinOp(bo, lhs, rhs) => self.resolve_binop(bo, lhs, rhs),
|
||||
Expression::UnOp(uo, operand) => self.resolve_unop(uo, operand),
|
||||
Expression::Var(name) => self.resolve_var(name),
|
||||
@ -95,7 +97,7 @@ impl Interpreter {
|
||||
(Value::I64(val), UnOpType::Negate) => Value::I64(-val),
|
||||
(Value::I64(val), UnOpType::BNot) => Value::I64(!val),
|
||||
(Value::I64(val), UnOpType::LNot) => Value::I64(if val == 0 { 1 } else { 0 }),
|
||||
// _ => panic!("Value type is not compatible with unary operation"),
|
||||
_ => panic!("Value type is not compatible with unary operation"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,7 +144,7 @@ impl Interpreter {
|
||||
|
||||
BinOpType::Declare | BinOpType::Assign => unreachable!(),
|
||||
},
|
||||
// _ => panic!("Value types are not compatible"),
|
||||
_ => panic!("Value types are not compatible"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -151,6 +153,7 @@ impl Display for Value {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Value::I64(val) => write!(f, "{}", val),
|
||||
Value::String(text) => write!(f, "{}", text),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
35
src/lexer.rs
35
src/lexer.rs
@ -106,6 +106,41 @@ impl<'a> Lexer<'a> {
|
||||
tokens.push(Token::I64(sval.parse().unwrap()));
|
||||
}
|
||||
|
||||
'"' => {
|
||||
// Opening " was consumed in match
|
||||
|
||||
let mut text = String::new();
|
||||
|
||||
loop {
|
||||
match self.peek() {
|
||||
'"' => break,
|
||||
'\0' => panic!("Encountered EoF while lexing string. Missing closing '\"'"),
|
||||
_ => {
|
||||
|
||||
match self.next() {
|
||||
'\\' => {
|
||||
match self.next() {
|
||||
'n' => text.push('\n'),
|
||||
'r' => text.push('\r'),
|
||||
't' => text.push('\t'),
|
||||
'\\' => text.push('\\'),
|
||||
'"' => text.push('"'),
|
||||
ch => panic!("Invalid backslash escape: '{}'", ch),
|
||||
}
|
||||
}
|
||||
ch => text.push(ch),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Consume closing "
|
||||
self.next();
|
||||
|
||||
tokens.push(Token::String(text))
|
||||
|
||||
}
|
||||
|
||||
// Lex characters as identifier
|
||||
ch @ ('a'..='z' | 'A'..='Z' | '_') => {
|
||||
let mut ident = String::from(ch);
|
||||
|
||||
@ -182,6 +182,9 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
||||
// Literal i64
|
||||
Token::I64(val) => Expression::I64(val),
|
||||
|
||||
// Literal String
|
||||
Token::String(text) => Expression::String(text.into()),
|
||||
|
||||
Token::Ident(name) => Expression::Var(name),
|
||||
|
||||
// Parentheses grouping
|
||||
|
||||
@ -5,6 +5,9 @@ pub enum Token {
|
||||
/// Integer literal (64-bit)
|
||||
I64(i64),
|
||||
|
||||
/// String literal
|
||||
String(String),
|
||||
|
||||
/// Identifier (name for variables, functions, ...)
|
||||
Ident(String),
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user