about summary refs log tree commit diff
path: root/src/parse/parser.rs
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/parse/parser.rs
parent249abe9c33dfd08afa6b09f3e53be91b0f445561 (diff)
downloadrabbithole-73c4808c44f75b7d6546f00f70779fcbf8e28754.tar.zst
rabbithole-73c4808c44f75b7d6546f00f70779fcbf8e28754.zip
Postfix parsing
Diffstat (limited to 'src/parse/parser.rs')
-rw-r--r--src/parse/parser.rs69
1 files changed, 51 insertions, 18 deletions
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 {