aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2021-10-24 02:03:29 +0200
committerMel <einebeere@gmail.com>2021-10-24 02:03:29 +0200
commit73c4808c44f75b7d6546f00f70779fcbf8e28754 (patch)
treef44e26fad3f37e62c0f5a35e2fafbe2d20f6da55 /src
parent249abe9c33dfd08afa6b09f3e53be91b0f445561 (diff)
downloadrabbithole-73c4808c44f75b7d6546f00f70779fcbf8e28754.tar.zst
rabbithole-73c4808c44f75b7d6546f00f70779fcbf8e28754.zip
Postfix parsing
Diffstat (limited to 'src')
-rw-r--r--src/interpret/walker.rs3
-rw-r--r--src/lex/lexer.rs2
-rw-r--r--src/lex/token.rs2
-rw-r--r--src/parse/ast/expression.rs28
-rw-r--r--src/parse/ast/nodes.rs18
-rw-r--r--src/parse/parser.rs69
6 files changed, 103 insertions, 19 deletions
diff --git a/src/interpret/walker.rs b/src/interpret/walker.rs
index db37a26..ac3a092 100644
--- a/src/interpret/walker.rs
+++ b/src/interpret/walker.rs
@@ -109,6 +109,9 @@ impl Walker {
Ok(new_value)
}
+ Expression::Call(_) => todo!("Calls not implemented yet."),
+ Expression::ArrayAccess(_) => todo!("Arrays not implemented yet."),
+ Expression::MemberAccess(_) => todo!("Structures not implemented yet."),
Expression::Group(node) => self.walk_expression(node),
Expression::Literal(token) => {
let value = match token {
diff --git a/src/lex/lexer.rs b/src/lex/lexer.rs
index 41384a9..edd1ff0 100644
--- a/src/lex/lexer.rs
+++ b/src/lex/lexer.rs
@@ -83,6 +83,8 @@ impl Iterator for Lexer<'_> {
')' => GroupClose,
'{' => BlockOpen,
'}' => BlockClose,
+ '[' => ArrayOpen,
+ ']' => ArrayClose,
'.' => Dot,
',' => Comma,
':' => {
diff --git a/src/lex/token.rs b/src/lex/token.rs
index 2fb5d5b..3c6d5c6 100644
--- a/src/lex/token.rs
+++ b/src/lex/token.rs
@@ -40,6 +40,8 @@ pub enum TokenVariant {
GroupClose,
BlockOpen,
BlockClose,
+ ArrayOpen,
+ ArrayClose,
// Literals
Int(u32),
diff --git a/src/parse/ast/expression.rs b/src/parse/ast/expression.rs
index c7f6d9b..1eec69d 100644
--- a/src/parse/ast/expression.rs
+++ b/src/parse/ast/expression.rs
@@ -1,7 +1,8 @@
use std::fmt::{self, Display, Formatter};
use super::nodes::{
- BinaryOperator, BlockNode, FnNode, Identifier, IfNode, Literal, LoopNode, UnaryOperator,
+ ArrayAccessNode, BinaryOperator, BlockNode, CallNode, FnNode, Identifier, IfNode, Literal,
+ LoopNode, MemberAccessNode, UnaryOperator,
};
#[derive(Debug, Clone)]
@@ -15,6 +16,9 @@ pub enum Expression {
op: UnaryOperator,
right: Box<Expression>,
},
+ Call(Box<CallNode>),
+ ArrayAccess(Box<ArrayAccessNode>),
+ MemberAccess(Box<MemberAccessNode>),
Group(Box<Expression>),
Block(Box<BlockNode>),
Fn(Box<FnNode>),
@@ -48,6 +52,28 @@ impl Expression {
writeln!(f, "{}- Right:", pad)?;
right.nested_fmt(f, depth + 1)?;
}
+ Expression::Call(node) => {
+ writeln!(f, "{}Function Call:", pad)?;
+ writeln!(f, "{}- Called:", pad)?;
+ node.called.nested_fmt(f, depth + 1)?;
+ for (i, e) in node.arguments.iter().enumerate() {
+ writeln!(f, "{}- Argument {}:", pad, i)?;
+ e.nested_fmt(f, depth + 1)?;
+ }
+ }
+ Expression::ArrayAccess(node) => {
+ writeln!(f, "{}Array Access:", pad)?;
+ writeln!(f, "{}- Array:", pad)?;
+ node.array.nested_fmt(f, depth + 1)?;
+ writeln!(f, "{}- Index:", pad)?;
+ node.index.nested_fmt(f, depth + 1)?;
+ }
+ Expression::MemberAccess(node) => {
+ writeln!(f, "{}Member Access:", pad)?;
+ writeln!(f, "{}- Object:", pad)?;
+ node.object.nested_fmt(f, depth + 1)?;
+ writeln!(f, "{}- Member Name: {}", pad, node.member_name)?;
+ }
Expression::Group(node) => {
writeln!(f, "{}Group:", pad)?;
node.nested_fmt(f, depth + 1)?;
diff --git a/src/parse/ast/nodes.rs b/src/parse/ast/nodes.rs
index 2a4f7c0..617a01c 100644
--- a/src/parse/ast/nodes.rs
+++ b/src/parse/ast/nodes.rs
@@ -88,6 +88,24 @@ pub struct TypedIdentifier {
}
#[derive(Debug, Clone)]
+pub struct CallNode {
+ pub called: Expression,
+ pub arguments: Vec<Expression>,
+}
+
+#[derive(Debug, Clone)]
+pub struct ArrayAccessNode {
+ pub array: Expression,
+ pub index: Expression,
+}
+
+#[derive(Debug, Clone)]
+pub struct MemberAccessNode {
+ pub object: Expression,
+ pub member_name: Identifier,
+}
+
+#[derive(Debug, Clone)]
pub struct FnNode {
pub header: FnHeader,
pub body: BlockNode,
diff --git a/src/parse/parser.rs b/src/parse/parser.rs
index 4a84101..2083f75 100644
--- a/src/parse/parser.rs
+++ b/src/parse/parser.rs
@@ -1,24 +1,14 @@
use super::ast::expression::Expression;
-use super::ast::nodes::LoopNode;
-use super::ast::nodes::UnaryOperator;
+use super::ast::nodes::{LoopNode, UnaryOperator};
use super::ast::statement::Statement;
use super::ast::Program;
-use crate::check;
-use crate::consume;
-use crate::consume_if;
-use crate::inner;
-use crate::lex::token::Token;
use crate::lex::token::TokenVariant::*;
-use crate::parse::ast::nodes::BinaryOperator;
-use crate::parse::ast::nodes::BlockNode;
-use crate::parse::ast::nodes::ConditionalBlock;
-use crate::parse::ast::nodes::FnHeader;
-use crate::parse::ast::nodes::FnNode;
-use crate::parse::ast::nodes::IfNode;
-use crate::parse::ast::nodes::Literal;
-use crate::parse::ast::nodes::TypedIdentifier;
-use anyhow::anyhow;
-use anyhow::Result;
+use crate::parse::ast::nodes::{
+ ArrayAccessNode, BinaryOperator, BlockNode, CallNode, ConditionalBlock, FnHeader, FnNode,
+ IfNode, Literal, MemberAccessNode, TypedIdentifier,
+};
+use crate::{check, consume, consume_if, inner, lex::token::Token};
+use anyhow::{anyhow, Result};
use std::iter::Peekable;
pub struct Parser<T: Iterator> {
@@ -183,12 +173,55 @@ impl<T: Iterator<Item = Token>> Parser<T> {
right: Box::new(self.unary_expression()?),
}
} else {
- self.unit_expression()?
+ self.postfix_expression()?
};
Ok(expression)
}
+ fn postfix_expression(&mut self) -> Result<Expression> {
+ let mut left = self.unit_expression()?;
+
+ while let Some(token) = consume_if!(self, GroupOpen | ArrayOpen | Dot) {
+ match token.variant {
+ GroupOpen => loop {
+ let mut arguments = Vec::new();
+
+ loop {
+ arguments.push(self.expression()?);
+
+ if consume_if!(self, Comma).is_none() {
+ consume!(self, GroupClose)?;
+ break;
+ }
+ }
+
+ left = Expression::Call(Box::new(CallNode {
+ called: left,
+ arguments,
+ }))
+ },
+ ArrayOpen => {
+ let index = self.expression()?;
+ consume!(self, ArrayClose)?;
+
+ left = Expression::ArrayAccess(Box::new(ArrayAccessNode { array: left, index }))
+ }
+ Dot => {
+ let member_name = inner!(consume!(self, Ident(_))?, Ident);
+
+ left = Expression::MemberAccess(Box::new(MemberAccessNode {
+ object: left,
+ member_name,
+ }))
+ }
+ _ => unreachable!(),
+ }
+ }
+
+ Ok(left)
+ }
+
fn unit_expression(&mut self) -> Result<Expression> {
if let Some(token) = self.tokens.peek() {
match token.variant {