Implement strings
This commit is contained in:
parent
39b55b51da
commit
abf9eb73c8
@ -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};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum Value {
|
||||
I64(i64),
|
||||
Str(Rc<String>),
|
||||
}
|
||||
|
||||
pub struct Interpreter {
|
||||
@ -50,6 +51,9 @@ impl Interpreter {
|
||||
match self.resolve_expr(condition) {
|
||||
Value::I64(val) if val == 0 => break,
|
||||
Value::I64(_) => (),
|
||||
|
||||
Value::Str(text) if text.is_empty() => break,
|
||||
Value::Str(_) => (),
|
||||
}
|
||||
|
||||
// Execute loop body
|
||||
@ -70,6 +74,7 @@ impl Interpreter {
|
||||
fn resolve_expr(&mut self, expr: &Expr) -> Value {
|
||||
match expr {
|
||||
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::UnOp(uo, val) => self.resolve_unop(uo, &val),
|
||||
Expr::Ident(name) => {
|
||||
@ -118,7 +123,7 @@ impl Interpreter {
|
||||
BinOpType::Le => Value::I64(if lhs <= rhs { 1 } else { 0 }),
|
||||
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 {
|
||||
UnOpType::Neg => Value::I64(-val),
|
||||
}
|
||||
_ => panic!("Invalid unary operation for type"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
43
src/lexer.rs
43
src/lexer.rs
@ -7,6 +7,9 @@ pub enum Token {
|
||||
/// Integer literal (64-bit)
|
||||
I64(i64),
|
||||
|
||||
/// String literal ("Some string")
|
||||
Str(String),
|
||||
|
||||
/// Left parenthesis ('(')
|
||||
LParen,
|
||||
|
||||
@ -180,6 +183,46 @@ impl<'a> Lexer<'a> {
|
||||
'}' => tokens.push(Token::RBrace),
|
||||
'$' => 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' | '_' => {
|
||||
let mut ident = String::from(ch);
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use std::iter::Peekable;
|
||||
use std::{iter::Peekable, rc::Rc};
|
||||
|
||||
use crate::lexer::Token;
|
||||
|
||||
@ -82,6 +82,8 @@ pub enum Stmt {
|
||||
pub enum Expr {
|
||||
/// Integer literal (64-bit)
|
||||
I64(i64),
|
||||
/// String literal
|
||||
Str(Rc<String>),
|
||||
/// Identifier (variable name)
|
||||
Ident(String),
|
||||
/// Binary operation. Consists of type, left hand side and right hand side
|
||||
@ -93,6 +95,7 @@ pub enum Expr {
|
||||
/*
|
||||
## Grammar
|
||||
### Expressions
|
||||
LITERAL = I64 | Str
|
||||
expr_primary = LITERAL | IDENT | "(" expr ")" | "-" expr_primary
|
||||
expr_mul = expr_primary (("*" | "/" | "%") expr_primary)*
|
||||
expr_add = expr_mul (("+" | "-") expr_mul)*
|
||||
@ -265,6 +268,8 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
||||
match self.next() {
|
||||
Token::I64(val) => Expr::I64(val),
|
||||
|
||||
Token::Str(text) => Expr::Str(text.into()),
|
||||
|
||||
Token::Ident(name) => Expr::Ident(name),
|
||||
|
||||
Token::LParen => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user