diff --git a/src/main.rs b/src/main.rs index 3eff845..ec733ce 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,7 +22,7 @@ fn main() { println!("Starting call to {n} with objcall = {o}"); call_stack.push((n, o)) } - Word::ConfirmCall(p) => { + Word::Confirm(p) => { let dat = call_stack.pop().unwrap(); println!( "Confirmed call to {} with return popping = {p} and objcall = {}", diff --git a/src/parser.rs b/src/parser.rs index b2c81d3..55b70e9 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -18,10 +18,17 @@ pub enum ParseError { InvalidToken(CodePos, String), StringInIdent(CodePos), UnexpectedEOF, - UnexpectedOpenParen(CodePos), + UnexpectedParen(CodePos), FunctionCallWithoutFn(CodePos), UnexpectedToken(CodePos, Token, String), ExpectedIdentifierAfterColon(CodePos), + ExpectedParen(CodePos), +} + +#[derive(Default)] +struct State { + is_objcall: bool, + paren_mode: Vec, } pub struct Parser<'a> { @@ -89,7 +96,8 @@ impl<'a> Parser<'a> { self.slice[0..self.index] .iter() .filter(|t| matches!(t, Token::Newline(_))) - .count(), + .count() + + 1, ), } } @@ -99,11 +107,6 @@ impl<'a> Parser<'a> { let mut words = Vec::new(); let mut file = None; - #[derive(Default)] - struct State { - is_objcall: bool, - paren_mode: Vec, - } let mut state = State { ..Default::default() }; @@ -111,11 +114,29 @@ impl<'a> Parser<'a> { while let Ok(token) = self.next() { match token { Token::Space => (), - Token::Exclam => words.push(Word::ConfirmCall(false)), - Token::Semicolon => words.push(Word::ConfirmCall(true)), + Token::Exclam => { + if state.paren_mode.pop().ok_or(ParseError::UnexpectedToken( + self.pos(), + Token::Semicolon, + String::new(), + ))? { + Err(ParseError::ExpectedParen(self.pos()))?; + } + words.push(Word::Confirm(false)) + } + Token::Semicolon => { + if state.paren_mode.pop().ok_or(ParseError::UnexpectedToken( + self.pos(), + Token::Semicolon, + String::new(), + ))? { + Err(ParseError::ExpectedParen(self.pos()))?; + } + words.push(Word::Confirm(true)) + } Token::Colon => { if words.last().is_some_and(|x| !matches!(x, Word::Const(_))) { - words.push(Word::ConfirmCall(false)); + words.push(Word::Confirm(false)); } state.is_objcall = true; } @@ -123,13 +144,18 @@ impl<'a> Parser<'a> { state .paren_mode .pop() - .ok_or(ParseError::UnexpectedOpenParen(self.pos()))?; + .ok_or(ParseError::UnexpectedParen(self.pos()))?; state.paren_mode.push(true); } Token::Close => { - words.push(Word::ConfirmCall( - self.next_matches(|x| *x == Token::Semicolon), - )); + if !state + .paren_mode + .pop() + .ok_or(ParseError::UnexpectedParen(self.pos()))? + { + Err(ParseError::UnexpectedParen(self.pos()))?; + } + words.push(Word::Confirm(self.next_matches(|x| *x == Token::Semicolon))); } Token::Begin => { words.push(Word::Block(self.read_level_at(self.index + 1)?)); @@ -201,6 +227,8 @@ impl<'a> Parser<'a> { self.read_level_at(self.index)?, ))) } + "if" => Ok(Some(Word::StartIf)), + "while" => Ok(Some(Word::StartWhile)), _ => Ok(None), } } diff --git a/src/word.rs b/src/word.rs index 8a81a29..4ebcc4f 100644 --- a/src/word.rs +++ b/src/word.rs @@ -21,7 +21,9 @@ pub enum Argdef { pub enum Word { Const(Value), StartCall(String, bool), - ConfirmCall(bool), + StartIf, + StartWhile, + Confirm(bool), Block(Vec), Function(String, Vec, Vec, Vec), Return, diff --git a/std.aea b/std.aea index 7ad1e24..5361b49 100644 --- a/std.aea +++ b/std.aea @@ -1,6 +1,7 @@ print "Hi 1" ; -"Hi 1" print; +"Hi 1" print() +"hi 2" print ; print("Hi 2");