array indexing and a bunch of other stuff

This commit is contained in:
nora 2022-06-26 15:44:39 +02:00
parent e7597dab07
commit 94229110cc
5 changed files with 172 additions and 20 deletions

View file

@ -33,6 +33,7 @@ pub enum BinaryOp {
Add,
Sub,
Comma,
Index, // lhs[rhs]
}
#[derive(Debug, DebugPls)]

View file

@ -51,7 +51,8 @@ where
lex: PeekMoreIterator<I>,
}
macro_rules! expect {
// HACK: It's called `_parser` as a workaround this being ambiguous with the `#[expect]` attribute
macro_rules! expect_parser {
($self:ident, $pat:pat) => {
match $self.next_t()? {
($pat, span) => span,
@ -68,6 +69,8 @@ macro_rules! expect {
};
}
use expect_parser as expect;
macro_rules! eat {
($self:ident, $pat:pat) => {
match $self.peek_t() {
@ -77,6 +80,8 @@ macro_rules! eat {
};
}
use eat;
/// Can be called for the start of a sequence of tokens that could be a type.
#[rustfmt::skip]
fn is_tok_start_of_ty(tok: &Tok<'_>) -> bool {

View file

@ -4,7 +4,7 @@
use crate::{
ast::{Atom, BinaryOp, Expr, ExprBinary, ExprUnary, UnaryOp},
parser::{Parser, ParserError, Result},
parser::{expect, Parser, ParserError, Result},
pre::Punctuator as P,
token::{Constant, Token as Tok},
Span, Spanned,
@ -25,6 +25,13 @@ where
&(Tok::Constant(Constant::Int(int)), span) => (Atom::Int(int), span),
&(Tok::Constant(Constant::Float(float)), span) => (Atom::Float(float), span),
&(Tok::Constant(Constant::Char(char)), span) => (Atom::Char(char), span),
&(Tok::Punct(P::ParenOpen), _) => {
// TODO: casts... yikes
self.next_t()?;
let lhs = self.expr_bp(0);
expect!(self, Tok::Punct(P::ParenClose));
return lhs;
}
&(Tok::Punct(punct), span) => {
let r_bp = prefix_binding_power(&Tok::Punct(punct));
let Some(op) = unary_op_from_token(&Tok::Punct(punct)) else { panic!() };
@ -61,27 +68,52 @@ where
Ok(&tok) => tok,
Err(_) => break,
};
let Some(op) = binary_op_from_token(&tok) else { break; };
self.next_t()?;
let (l_bp, r_bp) = infix_binding_power(&tok);
if l_bp < min_bp {
break;
if let Some(l_bp) = postfix_binding_power(&tok) {
if l_bp < min_bp {
break;
}
let (tok, _) = self.next_t()?;
if let Tok::Punct(P::BracketOpen) = tok {
let rhs = self.expr_bp(0)?;
let span = expect!(self, Tok::Punct(P::BracketClose));
let span = lhs.1.extend(span);
lhs = (
Expr::Binary(ExprBinary {
lhs: Box::new(lhs),
rhs: Box::new(rhs),
op: BinaryOp::Index,
}),
span,
);
}
continue;
}
let rhs = self.expr_bp(r_bp)?;
if let Some(op) = binary_op_from_token(&tok) {
let (l_bp, r_bp) = infix_binding_power(&tok);
if l_bp < min_bp {
break;
}
let span = lhs.1.extend(rhs.1);
self.next_t()?;
lhs = (
Expr::Binary(ExprBinary {
lhs: Box::new(lhs),
rhs: Box::new(rhs),
op,
}),
span,
)
let rhs = self.expr_bp(r_bp)?;
let span = lhs.1.extend(rhs.1);
lhs = (
Expr::Binary(ExprBinary {
lhs: Box::new(lhs),
rhs: Box::new(rhs),
op,
}),
span,
);
continue;
}
break;
}
Ok(lhs)
@ -122,3 +154,10 @@ fn infix_binding_power(tok: &Tok<'_>) -> (u8, u8) {
_ => panic!("invalid token in expression! {tok:?}"),
}
}
fn postfix_binding_power(tok: &Tok<'_>) -> Option<u8> {
match tok {
Tok::Punct(P::BracketOpen) => Some(45),
_ => None,
}
}

View file

@ -0,0 +1,103 @@
---
source: parser/src/parser/tests.rs
expression: parsed_pretty
---
Ok([
(
Decl(
Normal(NormalDecl {
decl_spec: DeclSpec {
ty: Int,
attrs: "(empty)",
},
init_declarators: [
(
InitDecl {
declarator: Declarator {
decl: Ident(("x", 5..6)),
pointer: false,
},
init: Some((
Binary(ExprBinary {
lhs: (Atom(Int(1)), 9..10),
rhs: (Atom(Int(1)), 13..14),
op: Add,
}),
9..14,
)),
},
5..6,
),
],
}),
),
1..6,
),
(
Decl(
Normal(NormalDecl {
decl_spec: DeclSpec {
ty: Int,
attrs: "(empty)",
},
init_declarators: [
(
InitDecl {
declarator: Declarator {
decl: Ident(("y", 21..22)),
pointer: false,
},
init: Some((
Binary(ExprBinary {
lhs: (Atom(Int(1)), 26..27),
rhs: (
Binary(ExprBinary {
lhs: (Atom(Int(2)), 31..32),
rhs: (Atom(Int(3)), 35..36),
op: Sub,
}),
31..36,
),
op: Add,
}),
26..36,
)),
},
21..22,
),
],
}),
),
17..22,
),
(
Decl(
Normal(NormalDecl {
decl_spec: DeclSpec {
ty: Int,
attrs: "(empty)",
},
init_declarators: [
(
InitDecl {
declarator: Declarator {
decl: Ident(("z", 45..46)),
pointer: false,
},
init: Some((
Binary(ExprBinary {
lhs: (Atom(Ident("array")), 50..55),
rhs: (Atom(Int(9)), 56..57),
op: Index,
}),
50..58,
)),
},
45..46,
),
],
}),
),
41..46,
),
])

View file

@ -1,6 +1,6 @@
use std::fmt::Debug;
use super::{Parser, Tok};
use super::Tok;
use crate::Span;
fn lex_and_pre(src: &str) -> impl Iterator<Item = (Tok<'_>, Span)> + '_ {
@ -63,10 +63,14 @@ int function();
}
#[test]
fn small_expression() {
fn small_expressions() {
parse_test!(
r#"
int x = 1 + 1;
int y = (1 + (2 - 3));
int z = (array[9]);
"#
);
}