diff --git a/src/code_gen.rs b/src/code_gen.rs new file mode 100644 index 0000000..6b23041 --- /dev/null +++ b/src/code_gen.rs @@ -0,0 +1,183 @@ +use std::{collections::HashMap, ops::AddAssign}; + +use color_eyre::eyre::Error; + +use crate::{ + lexer::Keyword, + parser::{LispAtom, SExpression}, +}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum InstructionFrom { + ROM, + RAM, + ALU, + RegisterC, + RegisterD, + + RegisterSP, + RegisterSB, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum InstructionTo { + JumpAddressUpper, + JumpAddressLower, + + Jump, + + RamAddressUpper, + RamAddressLower, + + RAM, + + Flags, + + RegisterA, + RegisterB, + RegisterC, + RegisterD, + + RegisterSP, + RegisterSB, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +struct Command { + data_from: InstructionFrom, + data_to: InstructionTo, + data: i8, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Scope { + variables: Vec, + stack_position: usize, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct EightBitLang { + instructions: Vec, + labels: Option>, +} + +pub trait GenerateCode { + fn to_code(self, codegen_scope: &mut Scope) -> Result + where + Self: Sized; + + type Error; +} + +impl GenerateCode for SExpression { + fn to_code(self, codegen_scope: &mut Scope) -> Result { + match self { + SExpression::Atom(a) => a.to_code(codegen_scope), + _ => todo!(), + } + } + + type Error = Error; +} + +impl GenerateCode for LispAtom { + fn to_code(self, codegen_scope: &mut Scope) -> Result { + match self { + LispAtom::Keyword(keyword) => keyword.to_code(codegen_scope), + LispAtom::Integer(number) => number.to_code(codegen_scope), + _ => todo!(), + } + } + + type Error = Error; +} + +impl GenerateCode for isize { + fn to_code(self, codegen_scope: &mut Scope) -> Result { + if let Err(_e) = i8::try_from(self) { + return Err(Error::msg("Yo integer too big brah")); + } + + return Ok(EightBitLang::push(self as i8, codegen_scope)); + } + + type Error = Error; +} + +impl GenerateCode for Keyword { + fn to_code(self, _codegen_scope: &mut Scope) -> Result { + match self { + _ => todo!(), + } + } + + type Error = Error; +} + +impl AddAssign for EightBitLang { + fn add_assign(&mut self, mut rhs: Self) { + let mut labels = self.labels.clone().unwrap(); + if rhs.labels.is_some() || self.labels.is_some() { + if self.labels.is_none() { + labels = rhs.labels.unwrap(); + } else if rhs.labels.is_none() { + } else { + labels = HashMap::new(); + for label in rhs.labels.unwrap() { + labels.insert(label.0, label.1 + self.instructions.len()); + } + } + self.labels = Some(labels); + } + self.instructions.append(&mut rhs.instructions); + } +} + +impl From for EightBitLang { + fn from(value: Command) -> Self { + Self { + instructions: vec![value], + labels: None, + } + } +} + +impl EightBitLang { + fn push(value: i8, codegen_scope: &mut Scope) -> Self { + use InstructionFrom as IF; + use InstructionTo as IT; + + codegen_scope.stack_position += 1; + + let mut commands = Vec::new(); + commands.push(Command::new(IF::RegisterSP, IT::RegisterA, 0x00)); + commands.push(Command::new(IF::ROM, IT::RegisterB, 0x01)); + commands.push(Command::new(IF::ALU, IT::RegisterSP, 0x00)); + commands.push(Command::new(IF::RegisterSP, IT::RamAddressLower, 0x00)); + commands.push(Command::new(IF::ROM, IT::RAM, value)); + + Self { + instructions: commands, + labels: None, + } + } +} + +impl Command { + fn new(data_from: InstructionFrom, data_to: InstructionTo, data: i8) -> Self { + Self { + data_from, + data_to, + data, + } + } +} + +impl Scope { + pub fn new() -> Self { + Self { + variables: Vec::new(), + stack_position: 0, + } + } +} diff --git a/src/ir.rs b/src/ir.rs new file mode 100644 index 0000000..7c5e3db --- /dev/null +++ b/src/ir.rs @@ -0,0 +1,253 @@ +use std::{ + collections::HashMap, + ops::{Add, AddAssign}, +}; + +use color_eyre::eyre::Error; + +use crate::{ + lexer::{Keyword, Macro}, + parser::{LispAtom, SExpression, NIL}, +}; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct IRepr { + commands: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +enum Command { + PushInt(isize), + PushSum, + PopR1, + PopR2, + PopOut, + PushRelative(usize), + + Enter, + Leave, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Scope { + stack_position: usize, + stack_positions: Vec, + variables: HashMap, +} + +pub fn generate_code(expressions: Vec) -> Result { + let mut scope = Scope { + stack_position: 0, + stack_positions: vec![], + variables: HashMap::new(), + }; + + let mut sum = IRepr::new(); + + for expression in expressions { + sum += expression.to_irepr(&mut scope)? + } + + Ok(sum) +} + +trait ToIR { + fn to_irepr(self, ir_scope: &mut Scope) -> Result; +} + +trait ToIRMacro { + fn to_irepr(self, ir_scope: &mut Scope, expressions: SExpression) -> Result; +} + +impl ToIR for SExpression { + fn to_irepr(self, ir_scope: &mut Scope) -> Result { + Ok(match self { + Self::Atom(a) => a.to_irepr(ir_scope)?, + Self::Pair(a, b) => match *a { + Self::Atom(LispAtom::Macro(m)) => m.to_irepr(ir_scope, *b)?, + a => b.to_irepr(ir_scope)? + a.to_irepr(ir_scope)?, + }, + }) + } +} + +impl ToIR for LispAtom { + fn to_irepr(self, ir_scope: &mut Scope) -> Result { + match self { + Self::Integer(number) => number.to_irepr(ir_scope), + Self::Keyword(keyword) => keyword.to_irepr(ir_scope), + Self::Identifier(identifier) => { + if !ir_scope.variables.contains_key(&identifier) { + todo!(); + } + ir_scope.stack_position += 1; + Ok(IRepr { + commands: vec![ + Command::PushRelative(ir_scope.variables[&identifier]), + ] + }) + } + _ => todo!(), + } + } +} + +impl ToIR for Keyword { + fn to_irepr(self, ir_scope: &mut Scope) -> Result { + match self { + Self::Nil => Ok(IRepr { commands: vec![] }), + Self::Add => { + ir_scope.stack_position -= 1; + Ok(IRepr { + commands: vec![Command::PopR1, Command::PopR2, Command::PushSum], + }) + } + Self::Out => { + ir_scope.stack_position -= 1; + Ok(IRepr { + commands: vec![Command::PopOut], + }) + } + } + } +} + +impl ToIR for isize { + fn to_irepr(self, ir_scope: &mut Scope) -> Result { + ir_scope.stack_position += 1; + return Ok(Command::PushInt(self).to_irepr()); + } +} + +impl ToIRMacro for Macro { + fn to_irepr(self, ir_scope: &mut Scope, expression: SExpression) -> Result { + match self { + Self::Let => { + println!("Parsing a let expression"); + let (mut varlist, mut body) = match expression { + SExpression::Atom(_a) => todo!(), + SExpression::Pair(a, b) => (*a, *b), + }; + + let mut commands = IRepr { + commands: vec![Command::Enter], + }; + + ir_scope.stack_positions.push(ir_scope.stack_position); + ir_scope.stack_position = 0; + + while varlist != NIL { + let var = match varlist { + SExpression::Atom(_) => panic!("Let defined wrong"), + SExpression::Pair(a, b) => { + varlist = *b; + *a + } + }; + match var { + SExpression::Atom(a) => { + let name = match a { + LispAtom::Identifier(ident) => ident, + _ => todo!(), + }; + ir_scope.variables.insert(name, ir_scope.stack_position); + ir_scope.stack_position += 1; + commands += Command::PushInt(0); + } + SExpression::Pair(name, car) => { + let name = match *name { + SExpression::Atom(a) => match a { + LispAtom::Identifier(ident) => ident, + _ => todo!(), + }, + _ => todo!(), + }; + commands += car.to_irepr(ir_scope)?; + ir_scope.variables.insert(name, ir_scope.stack_position); + } + } + } + + dbg!(&commands); + dbg!(&ir_scope); + + while body != NIL { + match body { + SExpression::Atom(_a) => todo!(), + SExpression::Pair(a, b) => { + commands += a.to_irepr(ir_scope)?; + body = *b; + } + } + } + + dbg!(&commands); + dbg!(&ir_scope); + + commands += Command::Leave; + + todo!() + } + _ => todo!(), + } + } +} + +impl Command { + fn to_irepr(self) -> IRepr { + IRepr { + commands: vec![self], + } + } +} + +impl IRepr { + fn new() -> IRepr { + return IRepr { commands: vec![] }; + } +} + +impl AddAssign for IRepr { + fn add_assign(&mut self, rhs: Self) { + self.commands.extend(rhs.commands); + } +} + +impl AddAssign> for IRepr { + fn add_assign(&mut self, rhs: Vec) { + self.commands.extend(rhs); + } +} + +impl Add> for IRepr { + fn add(mut self, rhs: Vec) -> Self::Output { + self += rhs; + return self; + } + + type Output = Self; +} + +impl AddAssign for IRepr { + fn add_assign(&mut self, rhs: Command) { + self.commands.push(rhs); + } +} + +impl Add for IRepr { + fn add(mut self, rhs: Command) -> Self::Output { + self += rhs; + return self; + } + + type Output = Self; +} + +impl Add for IRepr { + fn add(mut self, rhs: Self) -> Self::Output { + self += rhs; + return self; + } + + type Output = Self; +} diff --git a/src/lexer.rs b/src/lexer.rs index e684847..b89b020 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -1,27 +1,43 @@ -use std::str::FromStr; +use std::{fmt::Display, str::FromStr}; use thiserror::Error; -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq, Clone)] pub enum TokenType { OpenParantheses, ClosedParantheses, - Integer(usize), + Dot, + Integer(isize), String(String), Identifier(String), + Keyword(Keyword), + Macro(Macro), } -#[derive(Debug)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Token { - row: usize, - col: usize, + pub row: usize, + pub col: usize, - token_type: TokenType, + pub token_type: TokenType, } #[derive(Debug)] pub struct TokenString { - tokens: Vec, + pub tokens: Vec, +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum Keyword { + Add, + Out, + Nil, +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum Macro { + Let, + Defun, } #[derive(Debug)] @@ -38,9 +54,9 @@ struct UnfinishedTokenString { #[derive(Error, Debug)] #[error("Syntax error at: {row}:{col}. {message}")] pub struct LexerError { - row: usize, - col: usize, - message: String, + pub row: usize, + pub col: usize, + pub message: String, } impl FromStr for TokenString { @@ -51,7 +67,7 @@ impl FromStr for TokenString { tokens: Vec::new(), eof: false, - row: 0, + row: 1, col: 1, }; @@ -84,10 +100,12 @@ impl Lexer for UnfinishedTokenString { use TokenType as TT; let token_type = match self.input[self.position] as char { - '(' => Ok(TT::OpenParantheses), - ')' => Ok(TT::ClosedParantheses), - 'a'..='z' | 'A'..='Z' => Ok(TT::Identifier(self.lex_identifier())), + '(' => { self.next_char(); Ok(TT::OpenParantheses) }, + ')' => { self.next_char(); Ok(TT::ClosedParantheses) }, + '.' => { self.next_char(); Ok(TT::Dot) }, + 'a'..='z' | 'A'..='Z' | ':' => Ok(self.lex_identifier()), '0'..='9' | '-' => Ok(TT::Integer(self.lex_integer())), + '"' => Ok(TT::String(self.lex_string())), v => Err(format!("Expected new token, found: {v}")), }; @@ -107,8 +125,6 @@ impl Lexer for UnfinishedTokenString { }; self.tokens.push(token); - - self.next_char(); self.skip_whitespace(); } @@ -140,11 +156,61 @@ impl UnfinishedTokenString { } } - fn lex_identifier(&mut self) -> String { - todo!() + fn lex_identifier(&mut self) -> TokenType { + let mut ident: String = String::new(); + while !self.eof && self.input[self.position].is_ascii_alphanumeric() { + ident += &String::from_utf8_lossy(&[self.input[self.position]]); + self.next_char(); + } + + use Keyword as K; + use Macro as M; + use TokenType as TT; + match ident.as_str() { + "add" => TT::Keyword(K::Add), + "out" => TT::Keyword(K::Out), + "nil" => TT::Keyword(K::Nil), + "let" => TT::Macro(M::Let), + "defun" => TT::Macro(M::Defun), + _ => TT::Identifier(ident), + } } - fn lex_integer(&mut self) -> usize { - todo!() + fn lex_integer(&mut self) -> isize { + let mut number: String = String::new(); + while !self.eof && self.input[self.position].is_ascii_digit() { + number += &String::from_utf8_lossy(&[self.input[self.position]]); + self.next_char(); + } + number.parse().unwrap() + } + + fn lex_string(&mut self) -> String { + let mut string: String = String::new(); + self.next_char(); + while !self.eof && !(self.input[self.position] == '"' as u8) { + string += &String::from_utf8_lossy(&[self.input[self.position]]); + self.next_char(); + } + string + } +} + +impl Display for Keyword { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Add => write!(f, "add"), + Self::Nil => write!(f, "nil"), + Self::Out => write!(f, "out"), + } + } +} + +impl Display for Macro { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Let => write!(f, "let"), + Self::Defun => write!(f, "defun"), + } } } diff --git a/src/main.rs b/src/main.rs index a2df24b..8b449aa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,32 +1,47 @@ // mod assembler; +mod code_gen; +mod ir; mod lexer; -// mod parser; +mod parser; mod error; use color_eyre::eyre::Result; // pub use error::*; +use ir::IRepr; use lexer::TokenString; +use parser::SExpression; + +use crate::{ + code_gen::{EightBitLang, GenerateCode, Scope}, + ir::generate_code, +}; fn main() -> Result<()> { // let code = "(+ 1 (+ 5 5))".to_string(); color_eyre::install()?; - let code = "()".to_string(); + // let code = r#"(mul 2 (add 3 4))"#.to_string(); - let lexed: TokenString = code.parse()?; + // let code = "(add 3 4) (add 1 2)"; + let code = "(let ((a 3)) (out (add 1 a)) (out (add 2 a)))"; - dbg!(lexed); + let lexed: TokenString = dbg!((code.parse())?); - Ok(()) + let parsed: Vec = (lexed.try_into())?; + println!("{parsed:?}"); + let code: IRepr = generate_code(parsed)?; + + // let code: EightBitLang = code.to_code(&mut Scope::new())?; + + dbg!(code); /* - let parsed = dbg!(parser::Parser::parse(code).unwrap()); - let assembled = assembler::Assembler::assemble(parsed).unwrap(); for byte in assembled { print!("{byte:#X}, "); } println!(""); */ + Ok(()) } diff --git a/src/parser.rs b/src/parser.rs index 2294c82..9dc9bd8 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,143 +1,134 @@ -use crate::*; +use std::fmt::Display; -#[derive(Debug)] -pub struct Parser { - row: usize, - column: usize, - lines: Vec>, +use color_eyre::eyre::Error; + +use crate::lexer::{Keyword, Macro, Token, TokenString, TokenType}; + +pub static NIL: SExpression = SExpression::Atom(LispAtom::Keyword(Keyword::Nil)); + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum SExpression { + Pair(Box, Box), + Atom(LispAtom), } -#[derive(Debug, Clone)] -pub(crate) struct Instruction { - pub name: String, - pub arguments: Vec, +#[derive(Debug, Clone, PartialEq, Eq)] +struct State { + expression: Vec, + index: usize, + _functions: Vec, } -#[derive(Debug, Clone)] -pub(crate) enum Value { - Instruction(Instruction), - StringLiteral(String), - IntegerLiteral(u32), +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum LispAtom { + Integer(isize), + String(String), Identifier(String), + Keyword(Keyword), + Macro(Macro), } -impl Parser { - pub fn parse(stream: String) -> Result { - let mut parser = Parser { - row: 0, - column: 0, - lines: stream - .split('\n') - .map(|a| a.chars().collect::>()) - .collect::>(), +impl TryFrom for Vec { + fn try_from(value: TokenString) -> Result { + let list = value.tokens; + + let mut expressions = vec![]; + + let mut state = State { + expression: list, + index: 0, + _functions: Vec::new(), }; - parser.instruction() + + while state.index != state.expression.len() { + expressions.push(SExpression::parse_sexpression(&mut state)?); + state.index += 1; + } + + Ok(expressions) } - fn increment(&mut self) -> Option<()> { - self.column += 1; - if self.column == self.lines[self.row].len() { - self.row += 1; - if self.row == self.lines.len() { - self.row -= 1; - self.column -= 1; - return None; + type Error = Error; +} + +impl SExpression { + fn parse_sexpression(state: &mut State) -> Result { + let expr = match &state.expression[state.index].token_type { + TokenType::OpenParantheses => Self::parse_expression(state), + TokenType::Integer(val) => Ok(Self::Atom(LispAtom::Integer(val.to_owned()))), + TokenType::String(val) => Ok(Self::Atom(LispAtom::String(val.to_owned()))), + TokenType::Identifier(val) => Ok(Self::Atom(LispAtom::Identifier(val.to_owned()))), + TokenType::Keyword(val) => Ok(Self::Atom(LispAtom::Keyword(val.to_owned()))), + TokenType::Macro(val) => Ok(Self::Atom(LispAtom::Macro(val.to_owned()))), + _other => Err(Error::msg(format!( + "Did not expect symbol at row {} col {}", + state.expression[state.index].row, state.expression[state.index].col + ))), + }; + + dbg!(expr) + } + + fn parse_expression(state: &mut State) -> Result { + if state.expression[state.index].token_type != TokenType::OpenParantheses { + return Err(Error::msg(format!( + "Error: Expected ( at row {} col {}", + state.expression[state.index].row, state.expression[state.index].col + ))); + } + state.index += 1; + + let expression_1 = dbg!(Self::parse_sexpression(state)?); + state.index += 1; + + // Is pair + if state.expression[state.index].token_type == TokenType::Dot { + state.index += 1; + let expression_2 = Self::parse_sexpression(state)?; + return Ok(Self::Pair(Box::new(expression_1), Box::new(expression_2))); + } else { + // Is list + let mut elements = vec![expression_1]; + + while state.expression[state.index].token_type != TokenType::ClosedParantheses { + elements.push(Self::parse_sexpression(state)?); + state.index += 1; } - self.column = 0; - } - return Some(()); - } - fn jump_whitespace(&mut self) -> Option<()> { - self.increment()?; - while self.lines[self.row][self.column].is_whitespace() { - self.increment()?; - } - Some(()) - } + elements.reverse(); - fn instruction(&mut self) -> Result { - if self.lines[self.row][self.column] != '(' { - return Err(Error::SyntaxError(SyntaxError { - row: self.row, - column: self.column, - message: "SyntaxError: Expected '('".to_string(), - })); - } - - self.jump_whitespace(); - - let name = self.identifier()?; - - let mut arguments = Vec::new(); - - while self.lines[self.row][self.column] != ')' { - match self.lines[self.row][self.column] { - '\"' => arguments.push(Value::StringLiteral(self.string_literal()?)), - '(' => arguments.push(Value::Instruction(self.instruction()?)), - character => { - if character.is_numeric() { - arguments.push(Value::IntegerLiteral(self.integer_literal()?)); - } else { - arguments.push(Value::Identifier(self.identifier()?)); - } - } - } - } - - self.jump_whitespace(); - - return Ok(Instruction { name, arguments }); - } - - fn string_literal(&mut self) -> Result { - self.increment(); - - let mut accumulator = String::new(); - - while self.lines[self.row][self.column] != '"' { - accumulator.push(self.lines[self.row][self.column]); - self.increment(); - } - - self.jump_whitespace(); - - Ok(accumulator) - } - - fn integer_literal(&mut self) -> Result { - let mut accumulator = String::new(); - - while self.lines[self.row][self.column].is_numeric() { - accumulator.push(self.lines[self.row][self.column]); - self.increment(); - } - - self.jump_whitespace(); - - match accumulator.parse() { - Ok(v) => Ok(v), - Err(_e) => Err(Error::SyntaxError(SyntaxError { - row: self.row, - column: self.column, - message: "Couldn't parse integer literal".to_string(), - })), + let pair = Self::make_pair_list(elements); + return Ok(pair); } } - fn identifier(&mut self) -> Result { - let mut accumulator = String::new(); - - let mut current = self.lines[self.row][self.column]; - - while !"()\"".contains(current) && !current.is_whitespace() { - accumulator.push(self.lines[self.row][self.column]); - self.increment(); - current = self.lines[self.row][self.column]; + fn make_pair_list(mut expressions: Vec) -> SExpression { + if expressions.len() == 1 { + return SExpression::Pair(Box::new(expressions[0].clone()), Box::new(NIL.clone())); } - self.jump_whitespace(); - - Ok(accumulator) + return SExpression::Pair( + Box::new( + expressions + .pop() + .expect("The length should be more than one"), + ), + Box::new(Self::make_pair_list(expressions)), + ); + } +} + +impl Display for SExpression { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Pair(a, b) => write!(f, "({a} . {b})"), + Self::Atom(a) => match a { + LispAtom::String(a) => write!(f, "\"{a}\""), + LispAtom::Integer(a) => write!(f, "{a}"), + LispAtom::Keyword(a) => write!(f, "{a}"), + LispAtom::Identifier(a) => write!(f, "{a}"), + LispAtom::Macro(a) => write!(f, "{a}"), + }, + } } } diff --git a/src/parser_old.rs b/src/parser_old.rs new file mode 100644 index 0000000..49ded85 --- /dev/null +++ b/src/parser_old.rs @@ -0,0 +1,143 @@ +use crate::{error::{Error, SyntaxError}, *}; + +#[derive(Debug)] +pub struct Parser { + row: usize, + column: usize, + lines: Vec>, +} + +#[derive(Debug, Clone)] +pub(crate) struct Instruction { + pub name: String, + pub arguments: Vec, +} + +#[derive(Debug, Clone)] +pub(crate) enum Value { + Instruction(Instruction), + StringLiteral(String), + IntegerLiteral(u32), + Identifier(String), +} + +impl Parser { + pub fn parse(stream: String) -> Result { + let mut parser = Parser { + row: 0, + column: 0, + lines: stream + .split('\n') + .map(|a| a.chars().collect::>()) + .collect::>(), + }; + parser.instruction() + } + + fn increment(&mut self) -> Option<()> { + self.column += 1; + if self.column == self.lines[self.row].len() { + self.row += 1; + if self.row == self.lines.len() { + self.row -= 1; + self.column -= 1; + return None; + } + self.column = 0; + } + return Some(()); + } + + fn jump_whitespace(&mut self) -> Option<()> { + self.increment()?; + while self.lines[self.row][self.column].is_whitespace() { + self.increment()?; + } + Some(()) + } + + fn instruction(&mut self) -> Result { + if self.lines[self.row][self.column] != '(' { + return Err(Error::SyntaxError(SyntaxError { + row: self.row, + column: self.column, + message: "SyntaxError: Expected '('".to_string(), + }).into()); + } + + self.jump_whitespace(); + + let name = self.identifier()?; + + let mut arguments = Vec::new(); + + while self.lines[self.row][self.column] != ')' { + match self.lines[self.row][self.column] { + '\"' => arguments.push(Value::StringLiteral(self.string_literal()?)), + '(' => arguments.push(Value::Instruction(self.instruction()?)), + character => { + if character.is_numeric() { + arguments.push(Value::IntegerLiteral(self.integer_literal()?)); + } else { + arguments.push(Value::Identifier(self.identifier()?)); + } + } + } + } + + self.jump_whitespace(); + + return Ok(Instruction { name, arguments }); + } + + fn string_literal(&mut self) -> Result { + self.increment(); + + let mut accumulator = String::new(); + + while self.lines[self.row][self.column] != '"' { + accumulator.push(self.lines[self.row][self.column]); + self.increment(); + } + + self.jump_whitespace(); + + Ok(accumulator) + } + + fn integer_literal(&mut self) -> Result { + let mut accumulator = String::new(); + + while self.lines[self.row][self.column].is_numeric() { + accumulator.push(self.lines[self.row][self.column]); + self.increment(); + } + + self.jump_whitespace(); + + match accumulator.parse() { + Ok(v) => Ok(v), + Err(_e) => Err(Error::SyntaxError(SyntaxError { + row: self.row, + column: self.column, + message: "Couldn't parse integer literal".to_string(), + }).into()), + } + } + + fn identifier(&mut self) -> Result { + let mut accumulator = String::new(); + + let mut current = self.lines[self.row][self.column]; + + while !"()\"".contains(current) && !current.is_whitespace() { + accumulator.push(self.lines[self.row][self.column]); + self.increment(); + current = self.lines[self.row][self.column]; + } + + self.jump_whitespace(); + + Ok(accumulator) + } +}