diff --git a/crates/aiken-lang/src/parser.rs b/crates/aiken-lang/src/parser.rs index f384de20..408f6068 100644 --- a/crates/aiken-lang/src/parser.rs +++ b/crates/aiken-lang/src/parser.rs @@ -1,5 +1,5 @@ mod annotation; -pub mod definitions; +pub mod definition; pub mod error; pub mod expr; pub mod extra; @@ -9,7 +9,7 @@ pub mod token; mod utils; pub use annotation::parser as annotation; -pub use definitions::parser as definitions; +pub use definition::parser as definition; pub use expr::parser as expression; pub use pattern::parser as pattern; @@ -26,7 +26,7 @@ pub fn module( let stream = chumsky::Stream::from_iter(ast::Span::create(tokens.len()), tokens.into_iter()); - let definitions = definitions().parse(stream)?; + let definitions = definition().repeated().then_ignore(end()).parse(stream)?; let module = ast::UntypedModule { kind, diff --git a/crates/aiken-lang/src/parser/definitions/constant.rs b/crates/aiken-lang/src/parser/definition/constant.rs similarity index 100% rename from crates/aiken-lang/src/parser/definitions/constant.rs rename to crates/aiken-lang/src/parser/definition/constant.rs diff --git a/crates/aiken-lang/src/parser/definitions/data_type.rs b/crates/aiken-lang/src/parser/definition/data_type.rs similarity index 100% rename from crates/aiken-lang/src/parser/definitions/data_type.rs rename to crates/aiken-lang/src/parser/definition/data_type.rs diff --git a/crates/aiken-lang/src/parser/definitions/function.rs b/crates/aiken-lang/src/parser/definition/function.rs similarity index 100% rename from crates/aiken-lang/src/parser/definitions/function.rs rename to crates/aiken-lang/src/parser/definition/function.rs diff --git a/crates/aiken-lang/src/parser/definitions/import.rs b/crates/aiken-lang/src/parser/definition/import.rs similarity index 79% rename from crates/aiken-lang/src/parser/definitions/import.rs rename to crates/aiken-lang/src/parser/definition/import.rs index af401954..6ac7186c 100644 --- a/crates/aiken-lang/src/parser/definitions/import.rs +++ b/crates/aiken-lang/src/parser/definition/import.rs @@ -55,3 +55,29 @@ pub fn parser() -> impl Parser impl Parser, Error = ParseError> { +pub fn parser() -> impl Parser { choice(( import(), data_type(), @@ -29,6 +29,4 @@ pub fn parser() -> impl Parser, Error = Parse test(), constant(), )) - .repeated() - .then_ignore(end()) } diff --git a/crates/aiken-lang/src/parser/definition/snapshots/import_alias.snap b/crates/aiken-lang/src/parser/definition/snapshots/import_alias.snap new file mode 100644 index 00000000..72220ba3 --- /dev/null +++ b/crates/aiken-lang/src/parser/definition/snapshots/import_alias.snap @@ -0,0 +1,18 @@ +--- +source: crates/aiken-lang/src/parser/definition/import.rs +description: "Code:\n\nuse aiken/list as foo" +--- +Use( + Use { + as_name: Some( + "foo", + ), + location: 0..21, + module: [ + "aiken", + "list", + ], + package: (), + unqualified: [], + }, +) diff --git a/crates/aiken-lang/src/parser/definition/snapshots/import_basic.snap b/crates/aiken-lang/src/parser/definition/snapshots/import_basic.snap new file mode 100644 index 00000000..49015b8f --- /dev/null +++ b/crates/aiken-lang/src/parser/definition/snapshots/import_basic.snap @@ -0,0 +1,16 @@ +--- +source: crates/aiken-lang/src/parser/definition/import.rs +description: "Code:\n\nuse aiken/list" +--- +Use( + Use { + as_name: None, + location: 0..14, + module: [ + "aiken", + "list", + ], + package: (), + unqualified: [], + }, +) diff --git a/crates/aiken-lang/src/parser/definition/snapshots/import_unqualified.snap b/crates/aiken-lang/src/parser/definition/snapshots/import_unqualified.snap new file mode 100644 index 00000000..d001f3bc --- /dev/null +++ b/crates/aiken-lang/src/parser/definition/snapshots/import_unqualified.snap @@ -0,0 +1,33 @@ +--- +source: crates/aiken-lang/src/parser/definition/import.rs +description: "Code:\n\nuse std/address.{Address as A, thing as w}\n" +--- +Use( + Use { + as_name: None, + location: 0..42, + module: [ + "std", + "address", + ], + package: (), + unqualified: [ + UnqualifiedImport { + location: 17..29, + name: "Address", + as_name: Some( + "A", + ), + layer: Value, + }, + UnqualifiedImport { + location: 31..41, + name: "thing", + as_name: Some( + "w", + ), + layer: Value, + }, + ], + }, +) diff --git a/crates/aiken-lang/src/parser/definitions/test.rs b/crates/aiken-lang/src/parser/definition/test.rs similarity index 100% rename from crates/aiken-lang/src/parser/definitions/test.rs rename to crates/aiken-lang/src/parser/definition/test.rs diff --git a/crates/aiken-lang/src/parser/definitions/type_alias.rs b/crates/aiken-lang/src/parser/definition/type_alias.rs similarity index 100% rename from crates/aiken-lang/src/parser/definitions/type_alias.rs rename to crates/aiken-lang/src/parser/definition/type_alias.rs diff --git a/crates/aiken-lang/src/parser/definitions/validator.rs b/crates/aiken-lang/src/parser/definition/validator.rs similarity index 100% rename from crates/aiken-lang/src/parser/definitions/validator.rs rename to crates/aiken-lang/src/parser/definition/validator.rs diff --git a/crates/aiken-lang/src/parser/expr/if_else.rs b/crates/aiken-lang/src/parser/expr/if_else.rs index 0d186818..6cc76344 100644 --- a/crates/aiken-lang/src/parser/expr/if_else.rs +++ b/crates/aiken-lang/src/parser/expr/if_else.rs @@ -46,3 +46,25 @@ pub fn parser<'a>( } }) } + +#[cfg(test)] +mod tests { + use chumsky::Parser; + + use crate::assert_expr; + + #[test] + fn if_else_basic() { + assert_expr!( + r#" + if True { + 1 + 1 + } else if a < 1 { + 3 + } else { + 4 + } + "# + ); + } +} diff --git a/crates/aiken-lang/src/parser/expr/int.rs b/crates/aiken-lang/src/parser/expr/int.rs index aa73a32d..e81db141 100644 --- a/crates/aiken-lang/src/parser/expr/int.rs +++ b/crates/aiken-lang/src/parser/expr/int.rs @@ -14,3 +14,38 @@ pub fn parser() -> impl Parser { } }) } + +#[cfg(test)] +mod tests { + use chumsky::Parser; + + use crate::assert_expr; + + #[test] + fn int_literal() { + assert_expr!("1"); + } + + #[test] + fn int_negative() { + assert_expr!("-1"); + } + + #[test] + fn int_numeric_underscore() { + assert_expr!( + r#" + { + let i = 1_234_567 + let j = 1_000_000 + let k = -10_000 + } + "# + ); + } + + #[test] + fn int_hex_bytes() { + assert_expr!(r#"0x01"#); + } +} diff --git a/crates/aiken-lang/src/parser/expr/list.rs b/crates/aiken-lang/src/parser/expr/list.rs index 8e76eb9f..c6a3b2d5 100644 --- a/crates/aiken-lang/src/parser/expr/list.rs +++ b/crates/aiken-lang/src/parser/expr/list.rs @@ -30,7 +30,6 @@ pub fn parser( #[cfg(test)] mod tests { - use chumsky::Parser; use crate::assert_expr; diff --git a/crates/aiken-lang/src/parser/expr/snapshots/if_else_basic.snap b/crates/aiken-lang/src/parser/expr/snapshots/if_else_basic.snap new file mode 100644 index 00000000..32cbd034 --- /dev/null +++ b/crates/aiken-lang/src/parser/expr/snapshots/if_else_basic.snap @@ -0,0 +1,66 @@ +--- +source: crates/aiken-lang/src/parser/expr/if_else.rs +description: "Code:\n\nif True {\n 1 + 1\n} else if a < 1 {\n 3\n} else {\n 4\n}\n" +--- +If { + location: 0..54, + branches: [ + IfBranch { + condition: Var { + location: 3..7, + name: "True", + }, + body: BinOp { + location: 12..17, + name: AddInt, + left: Int { + location: 12..13, + value: "1", + base: Decimal { + numeric_underscore: false, + }, + }, + right: Int { + location: 16..17, + value: "1", + base: Decimal { + numeric_underscore: false, + }, + }, + }, + location: 3..19, + }, + IfBranch { + condition: BinOp { + location: 28..33, + name: LtInt, + left: Var { + location: 28..29, + name: "a", + }, + right: Int { + location: 32..33, + value: "1", + base: Decimal { + numeric_underscore: false, + }, + }, + }, + body: Int { + location: 38..39, + value: "3", + base: Decimal { + numeric_underscore: false, + }, + }, + location: 28..41, + }, + ], + final_else: Int { + location: 51..52, + value: "4", + base: Decimal { + numeric_underscore: false, + }, + }, +} diff --git a/crates/aiken-lang/src/parser/expr/snapshots/int_hex_bytes.snap b/crates/aiken-lang/src/parser/expr/snapshots/int_hex_bytes.snap new file mode 100644 index 00000000..56ab77ec --- /dev/null +++ b/crates/aiken-lang/src/parser/expr/snapshots/int_hex_bytes.snap @@ -0,0 +1,9 @@ +--- +source: crates/aiken-lang/src/parser/expr/int.rs +description: "Code:\n\n0x01" +--- +Int { + location: 0..4, + value: "1", + base: Hexadecimal, +} diff --git a/crates/aiken-lang/src/parser/expr/snapshots/int_literal.snap b/crates/aiken-lang/src/parser/expr/snapshots/int_literal.snap new file mode 100644 index 00000000..da7cb54b --- /dev/null +++ b/crates/aiken-lang/src/parser/expr/snapshots/int_literal.snap @@ -0,0 +1,11 @@ +--- +source: crates/aiken-lang/src/parser/expr/int.rs +description: "Code:\n\n1" +--- +Int { + location: 0..1, + value: "1", + base: Decimal { + numeric_underscore: false, + }, +} diff --git a/crates/aiken-lang/src/parser/expr/snapshots/int_negative.snap b/crates/aiken-lang/src/parser/expr/snapshots/int_negative.snap new file mode 100644 index 00000000..fcf40a1d --- /dev/null +++ b/crates/aiken-lang/src/parser/expr/snapshots/int_negative.snap @@ -0,0 +1,15 @@ +--- +source: crates/aiken-lang/src/parser/expr/int.rs +description: "Code:\n\n-1" +--- +UnOp { + op: Negate, + location: 0..2, + value: Int { + location: 1..2, + value: "1", + base: Decimal { + numeric_underscore: false, + }, + }, +} diff --git a/crates/aiken-lang/src/parser/expr/snapshots/int_numeric_underscore.snap b/crates/aiken-lang/src/parser/expr/snapshots/int_numeric_underscore.snap new file mode 100644 index 00000000..566e732e --- /dev/null +++ b/crates/aiken-lang/src/parser/expr/snapshots/int_numeric_underscore.snap @@ -0,0 +1,61 @@ +--- +source: crates/aiken-lang/src/parser/expr/int.rs +description: "Code:\n\n{\n let i = 1_234_567\n let j = 1_000_000\n let k = -10_000\n}\n" +--- +Sequence { + location: 4..59, + expressions: [ + Assignment { + location: 4..21, + value: Int { + location: 12..21, + value: "1234567", + base: Decimal { + numeric_underscore: true, + }, + }, + pattern: Var { + location: 8..9, + name: "i", + }, + kind: Let, + annotation: None, + }, + Assignment { + location: 24..41, + value: Int { + location: 32..41, + value: "1000000", + base: Decimal { + numeric_underscore: true, + }, + }, + pattern: Var { + location: 28..29, + name: "j", + }, + kind: Let, + annotation: None, + }, + Assignment { + location: 44..59, + value: UnOp { + op: Negate, + location: 52..59, + value: Int { + location: 53..59, + value: "10000", + base: Decimal { + numeric_underscore: true, + }, + }, + }, + pattern: Var { + location: 48..49, + name: "k", + }, + kind: Let, + annotation: None, + }, + ], +} diff --git a/crates/aiken-lang/src/parser/expr/when/guard.rs b/crates/aiken-lang/src/parser/expr/when/guard.rs index afcc118f..95459ebc 100644 --- a/crates/aiken-lang/src/parser/expr/when/guard.rs +++ b/crates/aiken-lang/src/parser/expr/when/guard.rs @@ -2,7 +2,7 @@ use chumsky::prelude::*; use crate::{ ast, - parser::{definitions, error::ParseError, token::Token}, + parser::{definition, error::ParseError, token::Token}, }; pub fn parser() -> impl Parser { @@ -17,7 +17,7 @@ pub fn parser() -> impl Parser { + let $crate::parser::lexer::LexInfo { tokens, .. } = $crate::parser::lexer::run(indoc::indoc! { $code }).unwrap(); + + let stream = chumsky::Stream::from_iter($crate::ast::Span::create(tokens.len()), tokens.into_iter()); + + let result = $crate::parser::definition().parse(stream).unwrap(); + + insta::with_settings!({ + description => concat!("Code:\n\n", indoc::indoc! { $code }), + prepend_module_to_snapshot => false, + omit_expression => true + }, { + insta::assert_debug_snapshot!(result); + }); + }; +} diff --git a/crates/aiken-lang/src/tests/parser.rs b/crates/aiken-lang/src/tests/parser.rs index 3f5e5096..c10705c9 100644 --- a/crates/aiken-lang/src/tests/parser.rs +++ b/crates/aiken-lang/src/tests/parser.rs @@ -72,24 +72,6 @@ fn double_validator() { ); } -#[test] -fn import() { - assert_module!( - r#" - use std/list - "# - ); -} - -#[test] -fn unqualified_imports() { - assert_module!( - r#" - use std/address.{Address as A, thing as w} - "# - ); -} - #[test] fn import_alias() { assert_module!( @@ -186,25 +168,6 @@ fn pipeline() { ); } -#[test] -fn if_expression() { - assert_module!( - r#" - fn ifs() { - if True { - 1 + 1 - } else if a < 4 { - 5 - } else if a || b { - 6 - } else { - 3 - } - } - "# - ); -} - #[test] fn let_bindings() { assert_module!( @@ -445,30 +408,6 @@ fn tuple_type_alias() { ); } -#[test] -fn int_parsing_hex_bytes() { - assert_module!( - r#" - fn foo() { - #[ 0x01, 0xa2, 0x03 ] - } - "# - ); -} - -#[test] -fn test_parsing_numeric_underscore() { - assert_module!( - r#" - fn foo() { - let i = 1_234_567 - let j = 1_000_000 - let k = -10_000 - } - "# - ); -} - #[test] fn first_class_binop() { assert_module!( diff --git a/crates/aiken-lang/src/tests/snapshots/if_expression.snap b/crates/aiken-lang/src/tests/snapshots/if_expression.snap deleted file mode 100644 index e2b3b319..00000000 --- a/crates/aiken-lang/src/tests/snapshots/if_expression.snap +++ /dev/null @@ -1,109 +0,0 @@ ---- -source: crates/aiken-lang/src/tests/parser.rs -description: "Code:\n\nfn ifs() {\n if True {\n 1 + 1\n } else if a < 4 {\n 5\n } else if a || b {\n 6\n } else {\n 3\n }\n}\n" ---- -Module { - name: "", - docs: [], - type_info: (), - definitions: [ - Fn( - Function { - arguments: [], - body: If { - location: 13..106, - branches: [ - IfBranch { - condition: Var { - location: 16..20, - name: "True", - }, - body: BinOp { - location: 27..32, - name: AddInt, - left: Int { - location: 27..28, - value: "1", - base: Decimal { - numeric_underscore: false, - }, - }, - right: Int { - location: 31..32, - value: "1", - base: Decimal { - numeric_underscore: false, - }, - }, - }, - location: 16..36, - }, - IfBranch { - condition: BinOp { - location: 45..50, - name: LtInt, - left: Var { - location: 45..46, - name: "a", - }, - right: Int { - location: 49..50, - value: "4", - base: Decimal { - numeric_underscore: false, - }, - }, - }, - body: Int { - location: 57..58, - value: "5", - base: Decimal { - numeric_underscore: false, - }, - }, - location: 45..62, - }, - IfBranch { - condition: BinOp { - location: 71..77, - name: Or, - left: Var { - location: 71..72, - name: "a", - }, - right: Var { - location: 76..77, - name: "b", - }, - }, - body: Int { - location: 84..85, - value: "6", - base: Decimal { - numeric_underscore: false, - }, - }, - location: 71..89, - }, - ], - final_else: Int { - location: 101..102, - value: "3", - base: Decimal { - numeric_underscore: false, - }, - }, - }, - doc: None, - location: 0..8, - name: "ifs", - public: false, - return_annotation: None, - return_type: (), - end_position: 107, - can_error: true, - }, - ), - ], - kind: Validator, -} diff --git a/crates/aiken-lang/src/tests/snapshots/import.snap b/crates/aiken-lang/src/tests/snapshots/import.snap deleted file mode 100644 index 2137b635..00000000 --- a/crates/aiken-lang/src/tests/snapshots/import.snap +++ /dev/null @@ -1,24 +0,0 @@ ---- -source: crates/aiken-lang/src/tests/parser.rs -description: "Code:\n\nuse std/list\n" ---- -Module { - name: "", - docs: [], - type_info: (), - definitions: [ - Use( - Use { - as_name: None, - location: 0..12, - module: [ - "std", - "list", - ], - package: (), - unqualified: [], - }, - ), - ], - kind: Validator, -} diff --git a/crates/aiken-lang/src/tests/snapshots/int_parsing_hex_bytes.snap b/crates/aiken-lang/src/tests/snapshots/int_parsing_hex_bytes.snap deleted file mode 100644 index e5969d3f..00000000 --- a/crates/aiken-lang/src/tests/snapshots/int_parsing_hex_bytes.snap +++ /dev/null @@ -1,36 +0,0 @@ ---- -source: crates/aiken-lang/src/tests/parser.rs -description: "Code:\n\nfn foo() {\n #[ 0x01, 0xa2, 0x03 ]\n}\n" ---- -Module { - name: "", - docs: [], - type_info: (), - definitions: [ - Fn( - Function { - arguments: [], - body: ByteArray { - location: 13..34, - bytes: [ - 1, - 162, - 3, - ], - preferred_format: ArrayOfBytes( - Hexadecimal, - ), - }, - doc: None, - location: 0..8, - name: "foo", - public: false, - return_annotation: None, - return_type: (), - end_position: 35, - can_error: true, - }, - ), - ], - kind: Validator, -} diff --git a/crates/aiken-lang/src/tests/snapshots/parsing_numeric_underscore.snap b/crates/aiken-lang/src/tests/snapshots/parsing_numeric_underscore.snap deleted file mode 100644 index a2c4b26e..00000000 --- a/crates/aiken-lang/src/tests/snapshots/parsing_numeric_underscore.snap +++ /dev/null @@ -1,82 +0,0 @@ ---- -source: crates/aiken-lang/src/tests/parser.rs -description: "Code:\n\nfn foo() {\n let i = 1_234_567\n let j = 1_000_000\n let k = -10_000\n}\n" ---- -Module { - name: "", - docs: [], - type_info: (), - definitions: [ - Fn( - Function { - arguments: [], - body: Sequence { - location: 13..68, - expressions: [ - Assignment { - location: 13..30, - value: Int { - location: 21..30, - value: "1234567", - base: Decimal { - numeric_underscore: true, - }, - }, - pattern: Var { - location: 17..18, - name: "i", - }, - kind: Let, - annotation: None, - }, - Assignment { - location: 33..50, - value: Int { - location: 41..50, - value: "1000000", - base: Decimal { - numeric_underscore: true, - }, - }, - pattern: Var { - location: 37..38, - name: "j", - }, - kind: Let, - annotation: None, - }, - Assignment { - location: 53..68, - value: UnOp { - op: Negate, - location: 61..68, - value: Int { - location: 62..68, - value: "10000", - base: Decimal { - numeric_underscore: true, - }, - }, - }, - pattern: Var { - location: 57..58, - name: "k", - }, - kind: Let, - annotation: None, - }, - ], - }, - doc: None, - location: 0..8, - name: "foo", - public: false, - return_annotation: None, - return_type: (), - end_position: 69, - can_error: true, - }, - ), - ], - kind: Validator, -} diff --git a/crates/aiken-lang/src/tests/snapshots/unqualified_imports.snap b/crates/aiken-lang/src/tests/snapshots/unqualified_imports.snap deleted file mode 100644 index b8d080d8..00000000 --- a/crates/aiken-lang/src/tests/snapshots/unqualified_imports.snap +++ /dev/null @@ -1,41 +0,0 @@ ---- -source: crates/aiken-lang/src/tests/parser.rs -description: "Code:\n\nuse std/address.{Address as A, thing as w}\n" ---- -Module { - name: "", - docs: [], - type_info: (), - definitions: [ - Use( - Use { - as_name: None, - location: 0..42, - module: [ - "std", - "address", - ], - package: (), - unqualified: [ - UnqualifiedImport { - location: 17..29, - name: "Address", - as_name: Some( - "A", - ), - layer: Value, - }, - UnqualifiedImport { - location: 31..41, - name: "thing", - as_name: Some( - "w", - ), - layer: Value, - }, - ], - }, - ), - ], - kind: Validator, -}