From 73c4808c44f75b7d6546f00f70779fcbf8e28754 Mon Sep 17 00:00:00 2001 From: Mel Date: Sun, 24 Oct 2021 02:03:29 +0200 Subject: Postfix parsing --- grammar.ebnf | 5 +++- src/interpret/walker.rs | 3 ++ src/lex/lexer.rs | 2 ++ src/lex/token.rs | 2 ++ src/parse/ast/expression.rs | 28 +++++++++++++++++- src/parse/ast/nodes.rs | 18 ++++++++++++ src/parse/parser.rs | 69 +++++++++++++++++++++++++++++++++------------ 7 files changed, 107 insertions(+), 20 deletions(-) diff --git a/grammar.ebnf b/grammar.ebnf index 7428788..7e59e74 100644 --- a/grammar.ebnf +++ b/grammar.ebnf @@ -25,7 +25,8 @@ EqualityExpression = ComparisonExpression { ("==" | "!=") ComparisonExpression } ComparisonExpression = TermExpression { ("<" | "<=" | ">" | ">=") TermExpression }; TermExpression = FactorExpression { ("+" | "-") FactorExpression }; FactorExpression = UnaryExpression { ("*" | "/") UnaryExpression }; -UnaryExpression = ( "-" | "!" ) UnaryExpression | UnitExpression ; +UnaryExpression = ( "-" | "!" ) UnaryExpression | PostfixExpression ; +PostfixExpression = UnitExpression { ( "(" [FnCallArguments] ")" | "[" Expression "]" | "." IDENTIFIER ) }; (* Unaffected Expressions *) @@ -45,6 +46,8 @@ LoopExpression = "loop" ["if" Expression] Block; FnHeader = (FnParameters) ["->" Type]; FnParameters = ("self" | FnParameter) { "," FnParameter}; +FnCallArguments = Expression { "," Expression }; + (* Utils *) Block = "{" { Statement } [Expression] "}"; 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, }, + Call(Box), + ArrayAccess(Box), + MemberAccess(Box), Group(Box), Block(Box), Fn(Box), @@ -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 @@ -87,6 +87,24 @@ pub struct TypedIdentifier { pub type_constraint: Option, } +#[derive(Debug, Clone)] +pub struct CallNode { + pub called: Expression, + pub arguments: Vec, +} + +#[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, 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 { @@ -183,12 +173,55 @@ impl> Parser { right: Box::new(self.unary_expression()?), } } else { - self.unit_expression()? + self.postfix_expression()? }; Ok(expression) } + fn postfix_expression(&mut self) -> Result { + 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 { if let Some(token) = self.tokens.peek() { match token.variant { -- cgit 1.4.1