Implement strings

This commit is contained in:
Daniel M 2022-01-28 21:25:01 +01:00
parent 39b55b51da
commit abf9eb73c8
3 changed files with 57 additions and 3 deletions

View File

@ -1,10 +1,11 @@
use std::collections::HashMap; use std::{collections::HashMap, rc::Rc};
use crate::{parser::{Expr, BinOpType, UnOpType, Ast, Stmt, parse}, lexer::lex}; use crate::{parser::{Expr, BinOpType, UnOpType, Ast, Stmt, parse}, lexer::lex};
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub enum Value { pub enum Value {
I64(i64), I64(i64),
Str(Rc<String>),
} }
pub struct Interpreter { pub struct Interpreter {
@ -50,6 +51,9 @@ impl Interpreter {
match self.resolve_expr(condition) { match self.resolve_expr(condition) {
Value::I64(val) if val == 0 => break, Value::I64(val) if val == 0 => break,
Value::I64(_) => (), Value::I64(_) => (),
Value::Str(text) if text.is_empty() => break,
Value::Str(_) => (),
} }
// Execute loop body // Execute loop body
@ -70,6 +74,7 @@ impl Interpreter {
fn resolve_expr(&mut self, expr: &Expr) -> Value { fn resolve_expr(&mut self, expr: &Expr) -> Value {
match expr { match expr {
Expr::I64(val) => Value::I64(*val), Expr::I64(val) => Value::I64(*val),
Expr::Str(name) => Value::Str(name.clone()),
Expr::BinOp(bo, lhs, rhs) => self.resolve_binop(bo, &lhs, &rhs), Expr::BinOp(bo, lhs, rhs) => self.resolve_binop(bo, &lhs, &rhs),
Expr::UnOp(uo, val) => self.resolve_unop(uo, &val), Expr::UnOp(uo, val) => self.resolve_unop(uo, &val),
Expr::Ident(name) => { Expr::Ident(name) => {
@ -118,7 +123,7 @@ impl Interpreter {
BinOpType::Le => Value::I64(if lhs <= rhs { 1 } else { 0 }), BinOpType::Le => Value::I64(if lhs <= rhs { 1 } else { 0 }),
BinOpType::Assign => unreachable!(), BinOpType::Assign => unreachable!(),
}, },
// _ => panic!("Value types are not compatible"), _ => panic!("Value types are not compatible"),
} }
} }
@ -128,6 +133,7 @@ impl Interpreter {
Value::I64(val) => match uo { Value::I64(val) => match uo {
UnOpType::Neg => Value::I64(-val), UnOpType::Neg => Value::I64(-val),
} }
_ => panic!("Invalid unary operation for type"),
} }
} }

View File

@ -7,6 +7,9 @@ pub enum Token {
/// Integer literal (64-bit) /// Integer literal (64-bit)
I64(i64), I64(i64),
/// String literal ("Some string")
Str(String),
/// Left parenthesis ('(') /// Left parenthesis ('(')
LParen, LParen,
@ -180,6 +183,46 @@ impl<'a> Lexer<'a> {
'}' => tokens.push(Token::RBrace), '}' => tokens.push(Token::RBrace),
'$' => tokens.push(Token::Dollar), '$' => tokens.push(Token::Dollar),
'"' => {
let mut text = String::new();
let mut escape = false;
// Do as long as a next char exists and it is not '"'
loop {
if escape {
escape = false;
match self.next() {
Some('\\') => text.push('\\'),
Some('n') => text.push('\n'),
Some('r') => text.push('\r'),
Some('t') => text.push('\t'),
ch => panic!("Invalid string escape: '{:?}'", ch),
}
} else {
match self.peek() {
Some('"') => {
self.next();
break;
}
Some('\\') => {
self.next();
escape = true;
}
None => panic!("String is never terminated (missing '\"')"),
_ => text.push(self.next().unwrap()),
}
}
}
tokens.push(Token::Str(text));
}
'a'..='z' | 'A'..='Z' | '_' => { 'a'..='z' | 'A'..='Z' | '_' => {
let mut ident = String::from(ch); let mut ident = String::from(ch);

View File

@ -1,4 +1,4 @@
use std::iter::Peekable; use std::{iter::Peekable, rc::Rc};
use crate::lexer::Token; use crate::lexer::Token;
@ -82,6 +82,8 @@ pub enum Stmt {
pub enum Expr { pub enum Expr {
/// Integer literal (64-bit) /// Integer literal (64-bit)
I64(i64), I64(i64),
/// String literal
Str(Rc<String>),
/// Identifier (variable name) /// Identifier (variable name)
Ident(String), Ident(String),
/// Binary operation. Consists of type, left hand side and right hand side /// Binary operation. Consists of type, left hand side and right hand side
@ -93,6 +95,7 @@ pub enum Expr {
/* /*
## Grammar ## Grammar
### Expressions ### Expressions
LITERAL = I64 | Str
expr_primary = LITERAL | IDENT | "(" expr ")" | "-" expr_primary expr_primary = LITERAL | IDENT | "(" expr ")" | "-" expr_primary
expr_mul = expr_primary (("*" | "/" | "%") expr_primary)* expr_mul = expr_primary (("*" | "/" | "%") expr_primary)*
expr_add = expr_mul (("+" | "-") expr_mul)* expr_add = expr_mul (("+" | "-") expr_mul)*
@ -265,6 +268,8 @@ impl<T: Iterator<Item = Token>> Parser<T> {
match self.next() { match self.next() {
Token::I64(val) => Expr::I64(val), Token::I64(val) => Expr::I64(val),
Token::Str(text) => Expr::Str(text.into()),
Token::Ident(name) => Expr::Ident(name), Token::Ident(name) => Expr::Ident(name),
Token::LParen => { Token::LParen => {