diff --git a/parser/src/lexer.rs b/parser/src/lexer.rs index 58fe932..fa0133d 100644 --- a/parser/src/lexer.rs +++ b/parser/src/lexer.rs @@ -78,6 +78,8 @@ pub enum Token<'a> { While, #[token("loop")] Loop, + #[token("ptr")] + Ptr, #[regex(r"[a-zA-Z_]\w*")] Ident(&'a str), @@ -131,6 +133,7 @@ impl<'a> Display for Token<'a> { Token::Else => f.write_str("else"), Token::While => f.write_str("while"), Token::Loop => f.write_str("loop"), + Token::Ptr => f.write_str("ptr"), Token::Ident(ident) => write!(f, "identifier `{ident}`"), Token::String(str) => write!(f, "\"{str}\""), Token::Integer(int) => write!(f, "{int}"), diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 1ea885b..64e3f80 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -19,7 +19,10 @@ pub fn parse(_str: &str, _file_name: PathBuf) -> Result { pub fn test() { let src = " fn main() { - u64 hello = 4 + //-(*5); + //&5; + //2 + &8; + *6 * *8; // :) } "; diff --git a/parser/src/parser.rs b/parser/src/parser.rs index 0f915f7..7fa35ce 100644 --- a/parser/src/parser.rs +++ b/parser/src/parser.rs @@ -31,7 +31,7 @@ fn ty_parser<'src>() -> impl Parser, Ty, Error = Error<'src>> + Clon }) .labelled("primitive type"); - let ptr = just(Token::Asterisk) + let ptr = just(Token::Ptr) .ignore_then(ty_parser.clone()) .map_with_span(|ty: Ty, span| Ty { kind: TyKind::Ptr(Box::new(ty)), @@ -63,15 +63,15 @@ fn expr_parser<'src>() -> impl Parser, Expr, Error = Error<'src>> + }) .labelled("literal"); - // A list of expressions - let items = expr + let expr_list = expr .clone() - .chain(just(Token::Comma).ignore_then(expr.clone()).repeated()) - .then_ignore(just(Token::Comma).or_not()) + .separated_by(just(Token::Comma)) + .allow_trailing() .or_not() - .map(|item| item.unwrap_or_default()); + .map(|item| item.unwrap_or_default()) + .boxed(); - let array = items + let array = expr_list .clone() .delimited_by(just(Token::BracketO), just(Token::BracketC)) .map(Expr::Array); @@ -82,11 +82,13 @@ fn expr_parser<'src>() -> impl Parser, Expr, Error = Error<'src>> + .or(expr .clone() .delimited_by(just(Token::ParenO), just(Token::ParenC))) + .debug("atom") .boxed(); let call = atom + .clone() .then( - items + expr_list .delimited_by(just(Token::ParenO), just(Token::ParenC)) .repeated(), ) @@ -95,23 +97,36 @@ fn expr_parser<'src>() -> impl Parser, Expr, Error = Error<'src>> + callee: Box::new(callee), args, }) - }); + }) + .labelled("call") + .boxed(); - // let _unary_op = just(Token::Minus) - // .to(UnaryOpKind::Neg) - // .or(just(Token::Bang).to(UnaryOpKind::Not)) - // .or(just(Token::Asterisk).to(UnaryOpKind::Deref)) - // .or(just(Token::Ampersand).to(UnaryOpKind::AddrOf)); - - // todo: unary + let unary_op = choice(( + just(Token::Minus).to(UnaryOpKind::Neg), + just(Token::Bang).to(UnaryOpKind::Not), + just(Token::Ampersand).to(UnaryOpKind::AddrOf), + just(Token::Asterisk).to(UnaryOpKind::Deref), + )) + .repeated() + .then(call) + .foldr(|kind, rhs| { + Expr::UnaryOp(UnaryOp { + expr: Box::new(rhs), + kind, + span: 0..0, // lol todo + }) + }) + .labelled("unary") + .debug("unary") + .boxed(); let op = just(Token::Asterisk) .to(BinOpKind::Mul) .or(just(Token::Slash).to(BinOpKind::Div)); - let product = call + let product = unary_op .clone() - .then(op.then(call).repeated()) + .then(op.then(unary_op).repeated()) .foldl(|a, (kind, b)| { Expr::BinOp(BinOp { kind, @@ -135,7 +150,10 @@ fn expr_parser<'src>() -> impl Parser, Expr, Error = Error<'src>> + rhs: Box::new(b), span: 0..0, // lol todo }) - }); + }) + .labelled("product") + .debug("product") + .boxed(); // Comparison ops (equal, not-equal) have equal precedence let op = just(Token::EqEq) @@ -170,7 +188,8 @@ fn statement_parser<'src>() -> impl Parser, Stmt, Error = Error<'src rhs: Some(rhs), span: Default::default(), }) - }); + }) + .boxed(); let assignment = expr_parser() .then_ignore(just(Token::Eq)) @@ -215,7 +234,8 @@ fn statement_parser<'src>() -> impl Parser, Stmt, Error = Error<'src span, }) }) - .map(Stmt::IfStmt); + .map(Stmt::IfStmt) + .boxed(); var_decl .or(assignment) @@ -307,7 +327,7 @@ where I: 'src, I: Iterator, Span)>, { - file_parser(file_name).parse_recovery(Stream::from_iter(len..len + 1, lexer)) + file_parser(file_name).parse_recovery_verbose(Stream::from_iter(len..len + 1, lexer)) } #[cfg(test)] @@ -392,7 +412,7 @@ mod tests { #[test] fn types() { - let r = parse("fn types() -> *u64 { Test test = 2; *u64 int = 25; }"); + let r = parse("fn types() -> ptr u64 { Test test = 2; ptr u64 int = 25; }"); insta::assert_debug_snapshot!(r); } } diff --git a/parser/src/snapshots/parser__parser__tests__types.snap b/parser/src/snapshots/parser__parser__tests__types.snap index ae0b0c8..f84cca4 100644 --- a/parser/src/snapshots/parser__parser__tests__types.snap +++ b/parser/src/snapshots/parser__parser__tests__types.snap @@ -1,6 +1,5 @@ --- source: parser/src/parser.rs -assertion_line: 382 expression: r --- ( @@ -14,22 +13,22 @@ expression: r params: [], ret_ty: Some( Ty { - span: 14..18, + span: 14..21, kind: Ptr( Ty { - span: 15..18, + span: 18..21, kind: U64, }, ), }, ), - span: 0..52, + span: 0..58, body: [ VarDecl( VarDecl { name: "test", ty: Ty { - span: 21..25, + span: 24..28, kind: Name( "Test", ), @@ -38,7 +37,7 @@ expression: r Literal( Integer( 2, - 33..34, + 36..37, ), ), ), @@ -49,10 +48,10 @@ expression: r VarDecl { name: "int", ty: Ty { - span: 36..40, + span: 39..46, kind: Ptr( Ty { - span: 37..40, + span: 43..46, kind: U64, }, ), @@ -61,7 +60,7 @@ expression: r Literal( Integer( 25, - 47..49, + 53..55, ), ), ), diff --git a/parser/src/snapshots/parser__parser__tests__unary.snap b/parser/src/snapshots/parser__parser__tests__unary.snap new file mode 100644 index 0000000..9fb6dbd --- /dev/null +++ b/parser/src/snapshots/parser__parser__tests__unary.snap @@ -0,0 +1,116 @@ +--- +source: parser/src/parser.rs +expression: r +--- +( + Some( + File { + name: "parser__parser__tests", + items: [ + FnDecl( + FnDecl { + name: "main", + params: [], + ret_ty: None, + span: 0..63, + body: [ + Expr( + UnaryOp( + UnaryOp { + expr: UnaryOp( + UnaryOp { + expr: Literal( + Integer( + 5, + 19..20, + ), + ), + kind: Deref, + span: 0..0, + }, + ), + kind: Neg, + span: 0..0, + }, + ), + ), + Expr( + UnaryOp( + UnaryOp { + expr: Literal( + Integer( + 5, + 28..29, + ), + ), + kind: AddrOf, + span: 0..0, + }, + ), + ), + Expr( + BinOp( + BinOp { + kind: Add, + lhs: Literal( + Integer( + 2, + 35..36, + ), + ), + rhs: UnaryOp( + UnaryOp { + expr: Literal( + Integer( + 8, + 40..41, + ), + ), + kind: AddrOf, + span: 0..0, + }, + ), + span: 0..0, + }, + ), + ), + Expr( + BinOp( + BinOp { + kind: Mul, + lhs: UnaryOp( + UnaryOp { + expr: Literal( + Integer( + 6, + 48..49, + ), + ), + kind: Deref, + span: 0..0, + }, + ), + rhs: UnaryOp( + UnaryOp { + expr: Literal( + Integer( + 8, + 53..54, + ), + ), + kind: Deref, + span: 0..0, + }, + ), + span: 0..0, + }, + ), + ), + ], + }, + ), + ], + }, + ), + [], +)