Skip to content

Commit

Permalink
feat: parse eval instruction
Browse files Browse the repository at this point in the history
  • Loading branch information
dxrcy committed Dec 4, 2024
1 parent f44b11c commit 7b89f4c
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 3 deletions.
30 changes: 30 additions & 0 deletions src/debugger/eval.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use miette::Result;

use crate::{
air::AirStmt,
lexer::{cursor::Cursor, TokenKind},
runtime::RunState,
symbol::InstrKind,
AsmParser,
};

pub fn run(state: &mut RunState, line: String) {
let stmt = parse(line);

println!("{:#?}", stmt);

todo!();
}

fn parse(line: String) -> Result<AirStmt> {
// TODO(fix): This is a TERRIBLE solution. Ideally cursor doesn't take &'static str ??
let line = Box::leak(line.into_boxed_str());

let mut parser = AsmParser::new_simple(line)?;

let stmt = parser.parse_simple()?;

println!("{:#?}", stmt);

todo!();
}
5 changes: 3 additions & 2 deletions src/debugger/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod command;
mod eval;
mod parse;
mod source;

Expand Down Expand Up @@ -339,8 +340,8 @@ impl Debugger {

Command::Eval { instruction } => {
self.was_pc_changed = true;
dprintln!(Always, "<{}>", instruction);
dprintln!(Always, "unimplemented: eval")
dprintln!(Always, "Eval: <{}>", instruction);
eval::run(state, instruction);
}

Command::BreakAdd { location } => {
Expand Down
64 changes: 63 additions & 1 deletion src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,33 @@ pub fn preprocess(src: &'static str) -> Result<Vec<Token>> {
Ok(res)
}

fn preprocess_simple(src: &'static str) -> Result<Vec<Token>> {
let mut res: Vec<Token> = Vec::new();
let mut cur = Cursor::new(src);

loop {
let token = cur.advance_real()?;
match token.kind {
TokenKind::Instr(_) | TokenKind::Trap(_) => res.push(token),

TokenKind::Comment | TokenKind::Whitespace => continue,
TokenKind::Eof => break,

TokenKind::Dir(_)
| TokenKind::Label
| TokenKind::Lit(_)
| TokenKind::Reg(_)
| TokenKind::Byte(_)
| TokenKind::Breakpoint => {
// TODO(feat): Handle error
panic!("unexpected token `{:?}`", token.kind);
}
}
}

Ok(res)
}

fn unescape(s: &str) -> Cow<str> {
if s.find('\\').is_none() {
return Cow::Borrowed(s);
Expand Down Expand Up @@ -137,6 +164,16 @@ impl AsmParser {
})
}

pub fn new_simple(src: &'static str) -> Result<Self> {
let toks = preprocess_simple(src)?;
Ok(AsmParser {
src,
toks: toks.into_iter().peekable(),
air: Air::new(),
line: 1,
})
}

fn get_span(&self, span: Span) -> &str {
&self.src[span.offs()..span.end()]
}
Expand Down Expand Up @@ -200,6 +237,31 @@ impl AsmParser {
Ok(self.air)
}

pub fn parse_simple(&mut self) -> Result<AirStmt> {
let Some(tok) = self.toks.next() else {
// TODO(feat): Handle error
panic!("unexpected eof (possibly unreachable)");
};

match tok.kind {
TokenKind::Instr(instr_kind) => self.parse_instr(instr_kind),
TokenKind::Trap(trap_kind) => self.parse_trap(trap_kind),

// Does not exist in preprocessed token stream
TokenKind::Comment
| TokenKind::Whitespace
| TokenKind::Eof
| TokenKind::Dir(_)
| TokenKind::Label
| TokenKind::Lit(_)
| TokenKind::Reg(_)
| TokenKind::Byte(_)
| TokenKind::Breakpoint => {
unreachable!("Found invalid token kind in preprocessed stream");
}
}
}

/// Return label or leave iter untouched and return None
fn optional_label(&mut self) -> Option<Token> {
match self.toks.peek() {
Expand All @@ -209,7 +271,7 @@ impl AsmParser {
}

/// Process several tokens to form valid AIR statement
fn parse_instr(&mut self, kind: InstrKind) -> Result<AirStmt> {
pub fn parse_instr(&mut self, kind: InstrKind) -> Result<AirStmt> {
use crate::symbol::InstrKind;
match kind {
InstrKind::Push => {
Expand Down

0 comments on commit 7b89f4c

Please sign in to comment.