Small refactoring for parser
This commit is contained in:
parent
948d41fb45
commit
2312deec5b
@ -15,20 +15,20 @@ pub fn parse<T: Iterator<Item = Token>, A: IntoIterator<IntoIter = T>>(tokens: A
|
|||||||
|
|
||||||
struct Parser<T: Iterator<Item = Token>> {
|
struct Parser<T: Iterator<Item = Token>> {
|
||||||
tokens: Peekable<T>,
|
tokens: Peekable<T>,
|
||||||
stringstore: StringStore,
|
string_store: StringStore,
|
||||||
varstack: Vec<Sid>,
|
var_stack: Vec<Sid>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Iterator<Item = Token>> Parser<T> {
|
impl<T: Iterator<Item = Token>> Parser<T> {
|
||||||
/// Create a new parser to parse the given Token Stream
|
/// Create a new parser to parse the given Token Stream
|
||||||
pub fn new<A: IntoIterator<IntoIter = T>>(tokens: A) -> Self {
|
pub fn new<A: IntoIterator<IntoIter = T>>(tokens: A) -> Self {
|
||||||
let tokens = tokens.into_iter().peekable();
|
let tokens = tokens.into_iter().peekable();
|
||||||
let stringstore = StringStore::new();
|
let string_store = StringStore::new();
|
||||||
let varstack = Vec::new();
|
let var_stack = Vec::new();
|
||||||
Self {
|
Self {
|
||||||
tokens,
|
tokens,
|
||||||
stringstore,
|
string_store,
|
||||||
varstack,
|
var_stack,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,14 +36,14 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
let main = self.parse_scoped_block();
|
let main = self.parse_scoped_block();
|
||||||
Ast {
|
Ast {
|
||||||
main,
|
main,
|
||||||
stringstore: self.stringstore,
|
stringstore: self.string_store,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse tokens into an abstract syntax tree. This will continuously parse statements until
|
/// Parse tokens into an abstract syntax tree. This will continuously parse statements until
|
||||||
/// encountering end-of-file or a block end '}' .
|
/// encountering end-of-file or a block end '}' .
|
||||||
fn parse_scoped_block(&mut self) -> BlockScope {
|
fn parse_scoped_block(&mut self) -> BlockScope {
|
||||||
let framepointer = self.varstack.len();
|
let framepointer = self.var_stack.len();
|
||||||
let mut prog = Vec::new();
|
let mut prog = Vec::new();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@ -56,7 +56,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
T!['{'] => {
|
T!['{'] => {
|
||||||
self.next();
|
self.next();
|
||||||
prog.push(Statement::Block(self.parse_scoped_block()));
|
prog.push(Statement::Block(self.parse_scoped_block()));
|
||||||
if !matches!(self.next(), T!['}']) {
|
if self.next() != T!['}'] {
|
||||||
panic!("Error parsing block: Expectected closing braces '}}'");
|
panic!("Error parsing block: Expectected closing braces '}}'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,7 +66,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.varstack.truncate(framepointer);
|
self.var_stack.truncate(framepointer);
|
||||||
|
|
||||||
prog
|
prog
|
||||||
}
|
}
|
||||||
@ -82,7 +82,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
let expr = self.parse_expr();
|
let expr = self.parse_expr();
|
||||||
|
|
||||||
// After a statement, there must be a semicolon
|
// After a statement, there must be a semicolon
|
||||||
if !matches!(self.next(), T![;]) {
|
if self.next() != T![;] {
|
||||||
panic!("Expected semicolon after statement");
|
panic!("Expected semicolon after statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,8 +98,8 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
match &mut expr {
|
match &mut expr {
|
||||||
Expression::BinOp(BinOpType::Declare, lhs, _) => match lhs.as_mut() {
|
Expression::BinOp(BinOpType::Declare, lhs, _) => match lhs.as_mut() {
|
||||||
Expression::Var(sid, sp) => {
|
Expression::Var(sid, sp) => {
|
||||||
*sp = self.varstack.len();
|
*sp = self.var_stack.len();
|
||||||
self.varstack.push(*sid);
|
self.var_stack.push(*sid);
|
||||||
}
|
}
|
||||||
_ => panic!("Left hand side of declaration must be variable"),
|
_ => panic!("Left hand side of declaration must be variable"),
|
||||||
},
|
},
|
||||||
@ -109,7 +109,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
let stmt = Statement::Expr(expr);
|
let stmt = Statement::Expr(expr);
|
||||||
|
|
||||||
// After a statement, there must be a semicolon
|
// After a statement, there must be a semicolon
|
||||||
if !matches!(self.next(), T![;]) {
|
if self.next() != T![;] {
|
||||||
panic!("Expected semicolon after statement");
|
panic!("Expected semicolon after statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,34 +120,34 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
|
|
||||||
/// Parse an if statement from the tokens
|
/// Parse an if statement from the tokens
|
||||||
fn parse_if(&mut self) -> If {
|
fn parse_if(&mut self) -> If {
|
||||||
if !matches!(self.next(), T![if]) {
|
if self.next() != T![if] {
|
||||||
panic!("Error lexing if: Expected if token");
|
panic!("Error lexing if: Expected if token");
|
||||||
}
|
}
|
||||||
|
|
||||||
let condition = self.parse_expr();
|
let condition = self.parse_expr();
|
||||||
|
|
||||||
if !matches!(self.next(), T!['{']) {
|
if self.next() != T!['{'] {
|
||||||
panic!("Error lexing if: Expected '{{'")
|
panic!("Error lexing if: Expected '{{'")
|
||||||
}
|
}
|
||||||
|
|
||||||
let body_true = self.parse_scoped_block();
|
let body_true = self.parse_scoped_block();
|
||||||
|
|
||||||
if !matches!(self.next(), T!['}']) {
|
if self.next() != T!['}'] {
|
||||||
panic!("Error lexing if: Expected '}}'")
|
panic!("Error lexing if: Expected '}}'")
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut body_false = BlockScope::default();
|
let mut body_false = BlockScope::default();
|
||||||
|
|
||||||
if matches!(self.peek(), T![else]) {
|
if self.peek() == &T![else] {
|
||||||
self.next();
|
self.next();
|
||||||
|
|
||||||
if !matches!(self.next(), T!['{']) {
|
if self.next() != T!['{'] {
|
||||||
panic!("Error lexing if: Expected '{{'")
|
panic!("Error lexing if: Expected '{{'")
|
||||||
}
|
}
|
||||||
|
|
||||||
body_false = self.parse_scoped_block();
|
body_false = self.parse_scoped_block();
|
||||||
|
|
||||||
if !matches!(self.next(), T!['}']) {
|
if self.next() != T!['}'] {
|
||||||
panic!("Error lexing if: Expected '}}'")
|
panic!("Error lexing if: Expected '}}'")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,7 +161,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
|
|
||||||
/// Parse a loop statement from the tokens
|
/// Parse a loop statement from the tokens
|
||||||
fn parse_loop(&mut self) -> Loop {
|
fn parse_loop(&mut self) -> Loop {
|
||||||
if !matches!(self.next(), T![loop]) {
|
if self.next() != T![loop] {
|
||||||
panic!("Error lexing loop: Expected loop token");
|
panic!("Error lexing loop: Expected loop token");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
T![;] => {
|
T![;] => {
|
||||||
advancement = Some(self.parse_expr());
|
advancement = Some(self.parse_expr());
|
||||||
|
|
||||||
if !matches!(self.next(), T!['{']) {
|
if self.next() != T!['{'] {
|
||||||
panic!("Error lexing loop: Expected '{{'")
|
panic!("Error lexing loop: Expected '{{'")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,7 +188,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
_ => panic!("Error lexing loop: Expected ';' or '{{'"),
|
_ => panic!("Error lexing loop: Expected ';' or '{{'"),
|
||||||
}
|
}
|
||||||
|
|
||||||
if !matches!(self.next(), T!['}']) {
|
if self.next() != T!['}'] {
|
||||||
panic!("Error lexing loop: Expected '}}'")
|
panic!("Error lexing loop: Expected '}}'")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,33 +240,30 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
T![i64(val)] => Expression::I64(val),
|
T![i64(val)] => Expression::I64(val),
|
||||||
|
|
||||||
// Literal String
|
// Literal String
|
||||||
T![str(text)] => Expression::String(self.stringstore.intern_or_lookup(&text)),
|
T![str(text)] => Expression::String(self.string_store.intern_or_lookup(&text)),
|
||||||
|
|
||||||
|
// Array literal. Square brackets containing the array size as expression
|
||||||
T!['['] => {
|
T!['['] => {
|
||||||
let size = self.parse_expr();
|
let size = self.parse_expr();
|
||||||
|
|
||||||
if !matches!(self.next(), T![']']) {
|
if self.next() != T![']'] {
|
||||||
panic!("Error parsing array literal: Expected closing bracket")
|
panic!("Error parsing array literal: Expected closing bracket")
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression::ArrayLiteral(size.into())
|
Expression::ArrayLiteral(size.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
T![ident(name)] if matches!(self.peek(), T!['[']) => {
|
// Array sccess, aka indexing. An ident followed by square brackets containing the
|
||||||
let sid = self.stringstore.intern_or_lookup(&name);
|
// index as an expression
|
||||||
let stackpos = self
|
T![ident(name)] if self.peek() == &T!['['] => {
|
||||||
.varstack
|
let sid = self.string_store.intern_or_lookup(&name);
|
||||||
.iter()
|
let stackpos = self.get_stackpos(sid);
|
||||||
.rev()
|
|
||||||
.position(|it| *it == sid)
|
|
||||||
.map(|it| self.varstack.len() - it - 1)
|
|
||||||
.unwrap_or(usize::MAX);
|
|
||||||
|
|
||||||
self.next();
|
self.next();
|
||||||
|
|
||||||
let index = self.parse_expr();
|
let index = self.parse_expr();
|
||||||
|
|
||||||
if !matches!(self.next(), T![']']) {
|
if self.next() != T![']'] {
|
||||||
panic!("Error parsing array access: Expected closing bracket")
|
panic!("Error parsing array access: Expected closing bracket")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,14 +271,8 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
T![ident(name)] => {
|
T![ident(name)] => {
|
||||||
let sid = self.stringstore.intern_or_lookup(&name);
|
let sid = self.string_store.intern_or_lookup(&name);
|
||||||
let stackpos = self
|
let stackpos = self.get_stackpos(sid);
|
||||||
.varstack
|
|
||||||
.iter()
|
|
||||||
.rev()
|
|
||||||
.position(|it| *it == sid)
|
|
||||||
.map(|it| self.varstack.len() - it - 1)
|
|
||||||
.unwrap_or(usize::MAX);
|
|
||||||
Expression::Var(sid, stackpos)
|
Expression::Var(sid, stackpos)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,7 +281,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
let inner_expr = self.parse_expr();
|
let inner_expr = self.parse_expr();
|
||||||
|
|
||||||
// Verify that there is a closing parenthesis
|
// Verify that there is a closing parenthesis
|
||||||
if !matches!(self.next(), T![')']) {
|
if self.next() != T![')'] {
|
||||||
panic!("Error parsing primary expr: Exepected closing parenthesis ')'");
|
panic!("Error parsing primary expr: Exepected closing parenthesis ')'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,6 +310,15 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_stackpos(&self, varid: Sid) -> usize {
|
||||||
|
self.var_stack
|
||||||
|
.iter()
|
||||||
|
.rev()
|
||||||
|
.position(|it| *it == varid)
|
||||||
|
.map(|it| self.var_stack.len() - it - 1)
|
||||||
|
.unwrap_or(usize::MAX)
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the next Token without removing it
|
/// Get the next Token without removing it
|
||||||
fn peek(&mut self) -> &Token {
|
fn peek(&mut self) -> &Token {
|
||||||
self.tokens.peek().unwrap_or(&T![EoF])
|
self.tokens.peek().unwrap_or(&T![EoF])
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user