Skip to content

Commit

Permalink
accept parsers that produce different values
Browse files Browse the repository at this point in the history
  • Loading branch information
andogq committed Aug 31, 2024
1 parent fd3c10b commit 4fe15db
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 89 deletions.
14 changes: 7 additions & 7 deletions src/hir/expression/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ ast_node! {

impl<M: AstMetadata> Parsable for Array<M> {
fn register(parser: &mut Parser) {
assert!(
parser.register_prefix(Token::LeftSquare, |parser, compiler, lexer| {
assert!(parser.register_prefix::<Expression<UntypedAstMetadata>>(
Token::LeftSquare,
|parser, compiler, lexer| {
// Parse opening square bracket
let span_start = match lexer.next_spanned().unwrap() {
(Token::LeftSquare, span) => span.start,
Expand All @@ -30,7 +31,6 @@ impl<M: AstMetadata> Parsable for Array<M> {
let mut init = Vec::new();
let mut expect_item = true;
let span_end = loop {
dbg!("loop");
match (lexer.peek_token().unwrap(), expect_item) {
(Token::Comma, false) => {
expect_item = true;
Expand Down Expand Up @@ -58,8 +58,8 @@ impl<M: AstMetadata> Parsable for Array<M> {
span: span_start..span_end,
ty_info: None,
}))
})
);
}
));
}
}

Expand Down Expand Up @@ -129,7 +129,7 @@ mod test {
#[case::triple("[1, 2, 3]", 3)]
#[case::triple_trailing("[1, 2, 3,]", 3)]
fn flat(parser: Parser, #[case] source: &str, #[case] items: usize) {
let array = parser
let array: Expression<UntypedAstMetadata> = parser
.parse(
&mut Compiler::default(),
&mut Lexer::from(source),
Expand All @@ -142,7 +142,7 @@ mod test {

#[rstest]
fn nested(parser: Parser) {
let array = parser
let array: Expression<UntypedAstMetadata> = parser
.parse(
&mut Compiler::default(),
&mut Lexer::from("[[1,], [1, 2,], [1, 2, 3,],]"),
Expand Down
16 changes: 9 additions & 7 deletions src/hir/expression/assign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ ast_node! {

impl<M: AstMetadata> Parsable for Assign<M> {
fn register(parser: &mut Parser) {
assert!(
parser.register_infix(Token::Eq, |parser, compiler, lexer, left| {
assert!(parser.register_infix::<Expression<UntypedAstMetadata>>(
Token::Eq,
|parser, compiler, lexer, left| {
let (binding, binding_span) = match left {
Expression::Ident(Ident { binding, span, .. }) => (binding, span),
lhs => {
Expand All @@ -36,16 +37,17 @@ impl<M: AstMetadata> Parsable for Assign<M> {
}
}

let value = parser.parse(compiler, lexer, Precedence::Lowest)?;
let value: Expression<UntypedAstMetadata> =
parser.parse(compiler, lexer, Precedence::Lowest)?;

Ok(Expression::Assign(Assign {
span: binding_span.start..value.span().end,
binding,
value: Box::new(value),
ty_info: None,
}))
})
);
}
));
}
}

Expand Down Expand Up @@ -111,7 +113,7 @@ mod test {
fn success(parser: Parser, #[case] lhs: &str, #[case] rhs: &str) {
let mut compiler = Compiler::default();

let assign = parser
let assign: Expression<UntypedAstMetadata> = parser
.parse(
&mut compiler,
&mut Lexer::from(format!("{lhs} = {rhs}").as_str()),
Expand All @@ -128,7 +130,7 @@ mod test {

#[rstest]
fn invalid(parser: Parser) {
let result = parser.parse(
let result: Result<Expression<UntypedAstMetadata>, _> = parser.parse(
&mut Compiler::default(),
&mut Lexer::from("1 = otherident"),
Precedence::Lowest,
Expand Down
2 changes: 1 addition & 1 deletion src/hir/expression/boolean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ mod test {

Boolean::<UntypedAstMetadata>::register(&mut parser);

let boolean = parser
let boolean: Expression<UntypedAstMetadata> = parser
.parse(
&mut Compiler::default(),
&mut Lexer::from(source),
Expand Down
4 changes: 2 additions & 2 deletions src/hir/expression/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ mod test {
fn success(parser: Parser, #[case] source: &str, #[case] arg_count: usize) {
let mut compiler = Compiler::default();

let call = parser
let call: Expression<UntypedAstMetadata> = parser
.parse(&mut compiler, &mut Lexer::from(source), Precedence::Lowest)
.unwrap();

Expand All @@ -183,7 +183,7 @@ mod test {
#[case::single_comma_no_args("myfn(,)")]
fn fail(parser: Parser, #[case] source: &str) {
assert!(parser
.parse(
.parse::<Expression<UntypedAstMetadata>, _>(
&mut Compiler::default(),
&mut Lexer::from(source),
Precedence::Lowest
Expand Down
49 changes: 26 additions & 23 deletions src/hir/expression/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,31 @@ ast_node! {

impl<M: AstMetadata> Parsable for Cast<M> {
fn register(parser: &mut Parser) {
assert!(parser.register_infix(Token::As, |_, _, lexer, left| {
let as_span = match lexer.next_spanned().unwrap() {
(Token::As, span) => span,
(token, _) => {
return Err(ParseError::ExpectedToken {
expected: Box::new(Token::As),
found: Box::new(token),
reason: "expected to find cast expression".to_string(),
});
}
};

// Parse out type from right hand side
let (target_ty, target_ty_span) = parse_ty(lexer)?;

Ok(Expression::Cast(Cast {
value: Box::new(left),
target_ty,
span: as_span.start..target_ty_span.end,
ty_info: None,
}))
}));
assert!(parser.register_infix::<Expression<UntypedAstMetadata>>(
Token::As,
|_, _, lexer, left| {
let as_span = match lexer.next_spanned().unwrap() {
(Token::As, span) => span,
(token, _) => {
return Err(ParseError::ExpectedToken {
expected: Box::new(Token::As),
found: Box::new(token),
reason: "expected to find cast expression".to_string(),
});
}
};

// Parse out type from right hand side
let (target_ty, target_ty_span) = parse_ty(lexer)?;

Ok(Expression::Cast(Cast {
value: Box::new(left),
target_ty,
span: as_span.start..target_ty_span.end,
ty_info: None,
}))
}
));
}
}

Expand Down Expand Up @@ -115,7 +118,7 @@ mod test {
#[case::missing_type("1 as")]
#[case::repeated_as("1 as as")]
fn fail(parser: Parser, #[case] source: &str) {
let result = parser.parse(
let result: Result<Expression<UntypedAstMetadata>, _> = parser.parse(
&mut Compiler::default(),
&mut Lexer::from(source),
Precedence::Lowest,
Expand Down
4 changes: 2 additions & 2 deletions src/hir/expression/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ ast_node! {

impl<M: AstMetadata> Parsable for Ident<M> {
fn register(parser: &mut Parser) {
parser.register_prefix_test(
parser.register_prefix_test::<Expression<UntypedAstMetadata>>(
|token| matches!(token, Token::Ident(_)),
|_, compiler, lexer| {
let (value, span) = match lexer.next_spanned().unwrap() {
Expand Down Expand Up @@ -99,7 +99,7 @@ mod test_ident {

let mut compiler = Compiler::default();

let ident = parser
let ident: Expression<UntypedAstMetadata> = parser
.parse(
&mut compiler,
&mut Lexer::from("someident"),
Expand Down
2 changes: 1 addition & 1 deletion src/hir/expression/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ mod test {
#[case::non_ident_lhs("1[3]")]
fn fail(parser: Parser, #[case] source: &str) {
assert!(parser
.parse(
.parse::<Expression<UntypedAstMetadata>, _>(
&mut Compiler::default(),
&mut Lexer::from(source),
Precedence::Lowest
Expand Down
4 changes: 2 additions & 2 deletions src/hir/expression/integer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ ast_node! {

impl<M: AstMetadata> Parsable for Integer<M> {
fn register(parser: &mut Parser) {
parser.register_prefix_test(
parser.register_prefix_test::<Expression<UntypedAstMetadata>>(
|token| matches!(token, Token::Integer(_)),
|_, _, lexer| {
let (value, span) = match lexer.next_spanned().unwrap() {
Expand Down Expand Up @@ -70,7 +70,7 @@ mod test_integer {

Integer::<UntypedAstMetadata>::register(&mut parser);

let integer = parser
let integer: Expression<UntypedAstMetadata> = parser
.parse(
&mut Compiler::default(),
&mut Lexer::from(value.to_string().as_str()),
Expand Down
6 changes: 6 additions & 0 deletions src/stage/parse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,14 @@ pub enum ParseError {
#[error("the function must have a return statement")]
MissingReturn,

#[error("expected to parse a block")]
ExpectedBlock,

#[error("unexpectedly encountered end of file")]
UnexpectedEOF,

#[error("no parsers registered for type: {0}")]
NoRegisteredParsers(String),
}

pub fn parse(compiler: &mut Compiler, source: &str) -> Result<Program, ParseError> {
Expand Down
Loading

0 comments on commit 4fe15db

Please sign in to comment.