summaryrefslogtreecommitdiffstats
path: root/src/forth/parser.rs
diff options
context:
space:
mode:
authorBrian Cully <bjc@spork.org>2025-08-21 15:26:44 -0400
committerBrian Cully <bjc@spork.org>2025-08-21 18:53:35 -0400
commita1c946b747325b4d7df778ebc70112338482f143 (patch)
tree48a0d71eaf00a0198f95204327580228e268d9ef /src/forth/parser.rs
parentc4b52f5f0770d3a83d67815b18e3cd76b01f0258 (diff)
downloadautomathon-a1c946b747325b4d7df778ebc70112338482f143.tar.gz
automathon-a1c946b747325b4d7df778ebc70112338482f143.zip
factorial working
Diffstat (limited to 'src/forth/parser.rs')
-rw-r--r--src/forth/parser.rs26
1 files changed, 17 insertions, 9 deletions
diff --git a/src/forth/parser.rs b/src/forth/parser.rs
index ddc48a9..55ad64b 100644
--- a/src/forth/parser.rs
+++ b/src/forth/parser.rs
@@ -1,4 +1,4 @@
-use super::interp::{ByteCode, OpCode, WordCatalog, WordList};
+use super::interp::{ByteCode, OpCode, WordList};
use std::collections::HashMap;
use std::iter::{Enumerate, Iterator};
@@ -28,6 +28,9 @@ impl std::error::Error for ParseError {}
type ParseResult<T> = Result<T, ParseError>;
#[derive(Debug)]
+pub struct WordCatalog<'a>(pub(super) HashMap<&'a str, usize>);
+
+#[derive(Debug)]
pub enum IfClauses {
True(usize),
TrueFalse(usize, usize),
@@ -39,7 +42,8 @@ pub struct Parser<'a> {
enumerator: Enumerate<Chars<'a>>,
// list of all word definitions, in the order defined. the main
// routine is always in the first entry.
- wordlist: WordList,
+ // todo: don't be pub, have a method to extract a wordlist
+ pub wordlist: WordList,
// catalog of word to word index in `wordlist`
wordalog: WordCatalog<'a>,
// holds a stack of indices into `wordlist` that are currently
@@ -74,7 +78,7 @@ impl<'a> Parser<'a> {
let (end, _c) =
self.enumerator.by_ref()
.find(|(_i, c)| c.is_whitespace())?;
- let word = self.text.get(start..end).unwrap();
+ let word = &self.text[start..end];
Some((word, start, end))
}
@@ -98,7 +102,7 @@ impl<'a> Parser<'a> {
Ok(())
}
- fn parse(&mut self) -> ParseResult<()> {
+ pub fn parse(&mut self) -> ParseResult<()> {
while let Some((word, _start, end)) = self.next_word() {
if let Ok(i) = word.parse::<i32>() {
self.bc_push(OpCode::Num(i))?;
@@ -139,7 +143,6 @@ impl<'a> Parser<'a> {
self.defstack.pop().ok_or(ParseError::DefStackEmpty)?;
},
"if" => {
- eprintln!("got if, if_stack: {:?}", self.if_stack);
let i = self.wordlist.0.len();
self.wordlist.0.push(ByteCode(vec![]));
self.defstack.push(i);
@@ -147,7 +150,6 @@ impl<'a> Parser<'a> {
self.if_stack.push(IfClauses::True(i));
},
"else" => {
- eprintln!("got else, if_stack: {:?}", self.if_stack);
self.bc_push(OpCode::Ret)?;
self.defstack.pop();
@@ -163,24 +165,30 @@ impl<'a> Parser<'a> {
self.if_stack.push(IfClauses::TrueFalse(true_clause, i));
},
"then" => {
- eprintln!("got then, if_stack: {:?}", self.if_stack);
self.bc_push(OpCode::Ret)?;
self.defstack.pop();
match self.if_stack.pop() {
None => return Err(ParseError::MissingIf),
Some(IfClauses::True(true_clause)) => {
- eprintln!("single clause true at {}", true_clause);
self.bc_push(OpCode::If(true_clause, None))?;
},
Some(IfClauses::TrueFalse(true_clause, false_clause)) => {
- eprintln!("two clause true at {} and {}", true_clause, false_clause);
self.bc_push(OpCode::If(true_clause, Some(false_clause)))?;
}
}
},
"+" => self.bc_push(OpCode::Add)?,
"-" => self.bc_push(OpCode::Sub)?,
+ "*" => self.bc_push(OpCode::Mul)?,
+ "/" => self.bc_push(OpCode::Div)?,
+ "dup" => self.bc_push(OpCode::Dup)?,
+ "drop" => self.bc_push(OpCode::Drop)?,
+ "=" => self.bc_push(OpCode::EQ)?,
+ ">" => self.bc_push(OpCode::GT)?,
+ ">=" => self.bc_push(OpCode::GTE)?,
+ "<" => self.bc_push(OpCode::LT)?,
+ "<=" => self.bc_push(OpCode::LTE)?,
other => return Err(ParseError::UnknownWord(String::from(other))),
}
}