diff --git a/libflux/flux-core/src/ast/mod.rs b/libflux/flux-core/src/ast/mod.rs index f1a7525456..f4e1c150dd 100644 --- a/libflux/flux-core/src/ast/mod.rs +++ b/libflux/flux-core/src/ast/mod.rs @@ -74,7 +74,7 @@ impl From for lsp_types::Position { } /// Represents the location of a node in the AST. -#[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize)] +#[derive(Default, PartialEq, Clone, Serialize, Deserialize)] pub struct SourceLocation { /// File is the optional file name. #[serde(skip_serializing_if = "skip_string_option")] @@ -88,6 +88,33 @@ pub struct SourceLocation { pub source: Option, } +// Custom debug implentation which reduces the size of `Debug` printing `AST`s +impl fmt::Debug for SourceLocation { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut f = f.debug_struct("SourceLocation"); + + if let Some(file) = &self.file { + f.field("file", file); + } + + // Render the positions on a single line so that `Debug` printing `AST`s are less verbose + f.field( + "start", + &format!("line: {}, column: {}", self.start.line, self.start.column), + ); + f.field( + "end", + &format!("line: {}, column: {}", self.end.line, self.end.column), + ); + + if let Some(source) = &self.source { + f.field("source", source); + } + + f.finish() + } +} + impl SourceLocation { #[allow(missing_docs)] pub fn is_valid(&self) -> bool { @@ -391,7 +418,7 @@ pub struct Comment { } /// BaseNode holds the attributes every expression or statement must have. -#[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize)] +#[derive(Default, PartialEq, Clone, Serialize, Deserialize)] #[allow(missing_docs)] pub struct BaseNode { #[serde(default)] @@ -409,6 +436,24 @@ pub struct BaseNode { pub errors: Vec, } +// Custom debug implentation which reduces the size of `Debug` printing `AST`s +impl fmt::Debug for BaseNode { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut f = f.debug_struct("BaseNode"); + f.field("location", &self.location); + + if !self.comments.is_empty() { + f.field("comments", &self.comments); + } + + if !self.errors.is_empty() { + f.field("errors", &self.errors); + } + + f.finish() + } +} + impl BaseNode { #[allow(missing_docs)] pub fn is_empty(&self) -> bool { diff --git a/libflux/flux-core/src/parser/tests.rs b/libflux/flux-core/src/parser/tests.rs index 3422b7ebf8..e62375ecb6 100644 --- a/libflux/flux-core/src/parser/tests.rs +++ b/libflux/flux-core/src/parser/tests.rs @@ -1,11 +1,9 @@ -use chrono; use pretty_assertions::assert_eq; use super::*; -use crate::{ - ast, - ast::{tests::Locator, Statement::Variable}, -}; +use crate::ast; + +use expect_test::expect; mod arrow_function; mod errors; @@ -13,9 +11,17 @@ mod from; mod literals; mod objects; mod operator_precedence; +mod property_list; mod strings; mod types; +fn test_file(source: &str, expect: expect_test::Expect) { + let mut parser = Parser::new(source); + let parsed = parser.parse_file("".to_string()); + + expect.assert_debug_eq(&parsed); +} + /// Parsed ast roundtrips across the serde boundary and generates the same ast. #[test] fn parse_ast_roundtrip() { @@ -64,844 +70,1269 @@ sort(columns: ["_time"], desc: true)|> limit(n: [object Object]) #[test] fn parse_invalid_unicode_bare() { - let mut p = Parser::new(r#"®some string®"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"®some string®"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 16), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 16", + source: "®some string®", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![ - Statement::Bad(Box::new(BadStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 3), - ..BaseNode::default() + imports: [], + body: [ + Bad( + BadStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 3", + source: "®", + }, + }, + text: "®", }, - text: "®".to_string(), - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 3, 1, 7), - ..BaseNode::default() + ), + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 3", + end: "line: 1, column: 7", + source: "some", + }, + }, + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 3", + end: "line: 1, column: 7", + source: "some", + }, + }, + name: "some", + }, + ), }, - expression: Expression::Identifier(Identifier { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 3, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 14", + source: "string", + }, }, - name: "some".to_string(), - }) - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 8, 1, 14), - ..BaseNode::default() + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 14", + source: "string", + }, + }, + name: "string", + }, + ), }, - expression: Expression::Identifier(Identifier { + ), + Bad( + BadStmt { base: BaseNode { - location: loc.get(1, 8, 1, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 16", + source: "®", + }, }, - name: "string".to_string(), - }) - })), - Statement::Bad(Box::new(BadStmt { - base: BaseNode { - location: loc.get(1, 14, 1, 16), - ..BaseNode::default() + text: "®", }, - text: "®".to_string(), - })), + ), ], - eof: vec![], - }, - ) + eof: [], + } + "#]], + ); } #[test] fn parse_invalid_unicode_paren_wrapped() { - let mut p = Parser::new(r#"(‛some string‛)"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"(‛some string‛)"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 20), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 20", + source: "(‛some string‛)", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 20), - ..BaseNode::default() - }, - expression: Expression::Paren(Box::new(ParenExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 20), - errors: vec!["invalid expression @1:16-1:19: ‛".to_string()], - ..BaseNode::default() - }, - lparen: vec![], - expression: Expression::Binary(Box::new(BinaryExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 5, 1, 16), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 20", + source: "(‛some string‛)", + }, }, - operator: Operator::InvalidOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 5, 1, 9), - errors: vec!["invalid expression @1:2-1:5: ‛".to_string()], - ..BaseNode::default() + expression: Paren( + ParenExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 20", + source: "(‛some string‛)", + }, + errors: [ + "invalid expression @1:16-1:19: ‛", + ], + }, + lparen: [], + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 16", + source: "some string", + }, + }, + operator: InvalidOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 9", + source: "some", + }, + errors: [ + "invalid expression @1:2-1:5: ‛", + ], + }, + name: "some", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 16", + source: "string", + }, + }, + name: "string", + }, + ), + }, + ), + rparen: [], }, - name: "some".to_string(), - }), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 10, 1, 16), - ..BaseNode::default() - }, - name: "string".to_string(), - }) - })), - rparen: vec![], - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn parse_invalid_unicode_interspersed() { - let mut p = Parser::new(r#"®s®t®r®i®n®g"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"®s®t®r®i®n®g"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 19), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 19", + source: "®s®t®r®i®n®g", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![ - Statement::Bad(Box::new(BadStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 3), - ..BaseNode::default() - }, - text: "®".to_string(), - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 3, 1, 4), - ..BaseNode::default() + imports: [], + body: [ + Bad( + BadStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 3", + source: "®", + }, + }, + text: "®", }, - expression: Expression::Identifier(Identifier { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 3, 1, 4), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 3", + end: "line: 1, column: 4", + source: "s", + }, }, - name: "s".to_string(), - }) - })), - Statement::Bad(Box::new(BadStmt { - base: BaseNode { - location: loc.get(1, 4, 1, 6), - ..BaseNode::default() + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 3", + end: "line: 1, column: 4", + source: "s", + }, + }, + name: "s", + }, + ), }, - text: "®".to_string(), - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() + ), + Bad( + BadStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 6", + source: "®", + }, + }, + text: "®", }, - expression: Expression::Identifier(Identifier { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "t", + }, }, - name: "t".to_string(), - }) - })), - Statement::Bad(Box::new(BadStmt { - base: BaseNode { - location: loc.get(1, 7, 1, 9), - ..BaseNode::default() + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "t", + }, + }, + name: "t", + }, + ), }, - text: "®".to_string(), - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 9, 1, 10), - ..BaseNode::default() + ), + Bad( + BadStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 9", + source: "®", + }, + }, + text: "®", }, - expression: Expression::Identifier(Identifier { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 9, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 10", + source: "r", + }, }, - name: "r".to_string(), - }) - })), - Statement::Bad(Box::new(BadStmt { - base: BaseNode { - location: loc.get(1, 10, 1, 12), - ..BaseNode::default() + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 10", + source: "r", + }, + }, + name: "r", + }, + ), }, - text: "®".to_string(), - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 12, 1, 13), - ..BaseNode::default() + ), + Bad( + BadStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 12", + source: "®", + }, + }, + text: "®", }, - expression: Expression::Identifier(Identifier { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 12, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 13", + source: "i", + }, }, - name: "i".to_string(), - }) - })), - Statement::Bad(Box::new(BadStmt { - base: BaseNode { - location: loc.get(1, 13, 1, 15), - ..BaseNode::default() + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 13", + source: "i", + }, + }, + name: "i", + }, + ), }, - text: "®".to_string(), - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 15, 1, 16), - ..BaseNode::default() + ), + Bad( + BadStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 13", + end: "line: 1, column: 15", + source: "®", + }, + }, + text: "®", }, - expression: Expression::Identifier(Identifier { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 15, 1, 16), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 16", + source: "n", + }, }, - name: "n".to_string(), - }) - })), - Statement::Bad(Box::new(BadStmt { - base: BaseNode { - location: loc.get(1, 16, 1, 18), - ..BaseNode::default() + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 16", + source: "n", + }, + }, + name: "n", + }, + ), }, - text: "®".to_string(), - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 18, 1, 19), - ..BaseNode::default() + ), + Bad( + BadStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 16", + end: "line: 1, column: 18", + source: "®", + }, + }, + text: "®", }, - expression: Expression::Identifier(Identifier { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 18, 1, 19), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 18", + end: "line: 1, column: 19", + source: "g", + }, }, - name: "g".to_string(), - }) - })), + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 18", + end: "line: 1, column: 19", + source: "g", + }, + }, + name: "g", + }, + ), + }, + ), ], - eof: vec![], - }, - ) + eof: [], + } + "#]], + ); } #[test] fn parse_greedy_quotes_paren_wrapped() { - let mut p = Parser::new(r#"(“some string”)"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"(“some string”)"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 20), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 20", + source: "(“some string”)", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 20), - ..BaseNode::default() - }, - expression: Expression::Paren(Box::new(ParenExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 20), - errors: vec!["invalid expression @1:16-1:19: ”".to_string()], - ..BaseNode::default() - }, - lparen: vec![], - expression: Expression::Binary(Box::new(BinaryExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 5, 1, 16), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 20", + source: "(“some string”)", + }, }, - operator: Operator::InvalidOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 5, 1, 9), - errors: vec!["invalid expression @1:2-1:5: “".to_string()], - ..BaseNode::default() + expression: Paren( + ParenExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 20", + source: "(“some string”)", + }, + errors: [ + "invalid expression @1:16-1:19: ”", + ], + }, + lparen: [], + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 16", + source: "some string", + }, + }, + operator: InvalidOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 9", + source: "some", + }, + errors: [ + "invalid expression @1:2-1:5: “", + ], + }, + name: "some", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 16", + source: "string", + }, + }, + name: "string", + }, + ), + }, + ), + rparen: [], }, - name: "some".to_string(), - }), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 10, 1, 16), - ..BaseNode::default() - }, - name: "string".to_string(), - }) - })), - rparen: vec![], - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn parse_greedy_quotes_bare() { - let mut p = Parser::new(r#"“some string”"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"“some string”"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "“some string”", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![ - Statement::Bad(Box::new(BadStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() + imports: [], + body: [ + Bad( + BadStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "“", + }, + }, + text: "“", }, - text: "“".to_string(), - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 4, 1, 8), - ..BaseNode::default() + ), + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 8", + source: "some", + }, + }, + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 8", + source: "some", + }, + }, + name: "some", + }, + ), }, - expression: Expression::Identifier(Identifier { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 4, 1, 8), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 15", + source: "string", + }, }, - name: "some".to_string(), - }) - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 9, 1, 15), - ..BaseNode::default() + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 15", + source: "string", + }, + }, + name: "string", + }, + ), }, - expression: Expression::Identifier(Identifier { + ), + Bad( + BadStmt { base: BaseNode { - location: loc.get(1, 9, 1, 15), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 18", + source: "”", + }, }, - name: "string".to_string(), - }) - })), - Statement::Bad(Box::new(BadStmt { - base: BaseNode { - location: loc.get(1, 15, 1, 18), - ..BaseNode::default() + text: "”", }, - text: "”".to_string(), - })), + ), ], - eof: vec![], - }, - ) + eof: [], + } + "#]], + ); } #[test] fn parse_greedy_quotes_interspersed() { - let mut p = Parser::new(r#"“s”t“r”i“n”g"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"“s”t“r”i“n”g"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 25), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 25", + source: "“s”t“r”i“n”g", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![ - Statement::Bad(Box::new(BadStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() - }, - text: "“".to_string(), - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 4, 1, 5), - ..BaseNode::default() + imports: [], + body: [ + Bad( + BadStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "“", + }, + }, + text: "“", }, - expression: Expression::Identifier(Identifier { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 4, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 5", + source: "s", + }, }, - name: "s".to_string(), - }) - })), - Statement::Bad(Box::new(BadStmt { - base: BaseNode { - location: loc.get(1, 5, 1, 8), - ..BaseNode::default() + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 5", + source: "s", + }, + }, + name: "s", + }, + ), }, - text: "”".to_string(), - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 8, 1, 9), - ..BaseNode::default() + ), + Bad( + BadStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 8", + source: "”", + }, + }, + text: "”", }, - expression: Expression::Identifier(Identifier { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 8, 1, 9), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 9", + source: "t", + }, }, - name: "t".to_string(), - }) - })), - Statement::Bad(Box::new(BadStmt { - base: BaseNode { - location: loc.get(1, 9, 1, 12), - ..BaseNode::default() + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 9", + source: "t", + }, + }, + name: "t", + }, + ), }, - text: "“".to_string(), - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 12, 1, 13), - ..BaseNode::default() + ), + Bad( + BadStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 12", + source: "“", + }, + }, + text: "“", }, - expression: Expression::Identifier(Identifier { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 12, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 13", + source: "r", + }, }, - name: "r".to_string(), - }) - })), - Statement::Bad(Box::new(BadStmt { - base: BaseNode { - location: loc.get(1, 13, 1, 16), - ..BaseNode::default() + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 13", + source: "r", + }, + }, + name: "r", + }, + ), }, - text: "”".to_string(), - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 16, 1, 17), - ..BaseNode::default() + ), + Bad( + BadStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 13", + end: "line: 1, column: 16", + source: "”", + }, + }, + text: "”", }, - expression: Expression::Identifier(Identifier { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 16, 1, 17), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 16", + end: "line: 1, column: 17", + source: "i", + }, }, - name: "i".to_string(), - }) - })), - Statement::Bad(Box::new(BadStmt { - base: BaseNode { - location: loc.get(1, 17, 1, 20), - ..BaseNode::default() + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 16", + end: "line: 1, column: 17", + source: "i", + }, + }, + name: "i", + }, + ), }, - text: "“".to_string(), - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 20, 1, 21), - ..BaseNode::default() + ), + Bad( + BadStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 17", + end: "line: 1, column: 20", + source: "“", + }, + }, + text: "“", }, - expression: Expression::Identifier(Identifier { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 20, 1, 21), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 20", + end: "line: 1, column: 21", + source: "n", + }, }, - name: "n".to_string(), - }) - })), - Statement::Bad(Box::new(BadStmt { - base: BaseNode { - location: loc.get(1, 21, 1, 24), - ..BaseNode::default() + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 20", + end: "line: 1, column: 21", + source: "n", + }, + }, + name: "n", + }, + ), }, - text: "”".to_string(), - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 24, 1, 25), - ..BaseNode::default() + ), + Bad( + BadStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 21", + end: "line: 1, column: 24", + source: "”", + }, + }, + text: "”", }, - expression: Expression::Identifier(Identifier { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 24, 1, 25), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 24", + end: "line: 1, column: 25", + source: "g", + }, }, - name: "g".to_string(), - }) - })), + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 24", + end: "line: 1, column: 25", + source: "g", + }, + }, + name: "g", + }, + ), + }, + ), ], - eof: vec![], - }, - ) + eof: [], + } + "#]], + ); } #[test] fn package_clause() { - let mut p = Parser::new(r#"package foo"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"package foo"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), - package: Some(PackageClause { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "package foo", }, - name: Identifier { + }, + name: "", + metadata: "parser-type=rust", + package: Some( + PackageClause { base: BaseNode { - location: loc.get(1, 9, 1, 12), - ..BaseNode::default() - }, - name: "foo".to_string() - } - }), - imports: vec![], - body: vec![], - eof: vec![], - }, - ) + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "package foo", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 12", + source: "foo", + }, + }, + name: "foo", + }, + }, + ), + imports: [], + body: [], + eof: [], + } + "#]], + ); } #[test] fn string_interpolation_trailing_dollar() { - let mut p = Parser::new(r#""a + b = ${a + b}$""#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#""a + b = ${a + b}$""#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 20), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 20", + source: "\"a + b = ${a + b}$\"", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 20), - ..BaseNode::default() - }, - expression: Expression::StringExpr(Box::new(StringExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 20), - ..BaseNode::default() - }, - parts: vec![ - StringExprPart::Text(TextPart { - base: BaseNode { - location: loc.get(1, 2, 1, 10), - ..BaseNode::default() - }, - value: "a + b = ".to_string(), - }), - StringExprPart::Interpolated(InterpolatedPart { - base: BaseNode { - location: loc.get(1, 10, 1, 18), - ..BaseNode::default() + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 20", + source: "\"a + b = ${a + b}$\"", }, - expression: Expression::Binary(Box::new(BinaryExpr { + }, + expression: StringExpr( + StringExpr { base: BaseNode { - location: loc.get(1, 12, 1, 17), - ..BaseNode::default() - }, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 12, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 20", + source: "\"a + b = ${a + b}$\"", }, - name: "a".to_string(), - }), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 16, 1, 17), - ..BaseNode::default() - }, - name: "b".to_string(), - }), - operator: Operator::AdditionOperator, - })), - }), - StringExprPart::Text(TextPart { - base: BaseNode { - location: loc.get(1, 18, 1, 19), - ..BaseNode::default() - }, - value: "$".to_string(), - }), - ], - })), - })),], - eof: vec![], - }, - ) -} + }, + parts: [ + Text( + TextPart { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 10", + source: "a + b = ", + }, + }, + value: "a + b = ", + }, + ), + Interpolated( + InterpolatedPart { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 18", + source: "${a + b}", + }, + }, + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 17", + source: "a + b", + }, + }, + operator: AdditionOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 13", + source: "a", + }, + }, + name: "a", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 16", + end: "line: 1, column: 17", + source: "b", + }, + }, + name: "b", + }, + ), + }, + ), + }, + ), + Text( + TextPart { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 18", + end: "line: 1, column: 19", + source: "$", + }, + }, + value: "$", + }, + ), + ], + }, + ), + }, + ), + ], + eof: [], + } + "#]], + ); +} #[test] fn import() { - let mut p = Parser::new(r#"import "path/foo""#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"import "path/foo""#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "import \"path/foo\"", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![ImportDeclaration { - base: BaseNode { - location: loc.get(1, 1, 1, 18), - ..BaseNode::default() - }, - alias: None, - path: StringLit { + imports: [ + ImportDeclaration { base: BaseNode { - location: loc.get(1, 8, 1, 18), - ..BaseNode::default() - }, - value: "path/foo".to_string() - } - }], - body: vec![], - eof: vec![], - }, - ) + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "import \"path/foo\"", + }, + }, + alias: None, + path: StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 18", + source: "\"path/foo\"", + }, + }, + value: "path/foo", + }, + }, + ], + body: [], + eof: [], + } + "#]], + ); } #[test] fn import_as() { - let mut p = Parser::new(r#"import bar "path/foo""#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"import bar "path/foo""#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 22), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 22", + source: "import bar \"path/foo\"", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![ImportDeclaration { - base: BaseNode { - location: loc.get(1, 1, 1, 22), - ..BaseNode::default() - }, - alias: Some(Identifier { + imports: [ + ImportDeclaration { base: BaseNode { - location: loc.get(1, 8, 1, 11), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 22", + source: "import bar \"path/foo\"", + }, }, - name: "bar".to_string() - }), - path: StringLit { - base: BaseNode { - location: loc.get(1, 12, 1, 22), - ..BaseNode::default() - }, - value: "path/foo".to_string() - } - }], - body: vec![], - eof: vec![], + alias: Some( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 11", + source: "bar", + }, + }, + name: "bar", + }, + ), + path: StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 22", + source: "\"path/foo\"", + }, + }, + value: "path/foo", + }, + }, + ], + body: [], + eof: [], } - ) + "#]], + ); } #[test] fn imports() { - let mut p = Parser::new( + test_file( r#"import "path/foo" import "path/bar""#, - ); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - File { - base: BaseNode { - location: loc.get(1, 1, 2, 18), - ..BaseNode::default() - }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), - package: None, - imports: vec![ - ImportDeclaration { - base: BaseNode { - location: loc.get(1, 1, 1, 18), - ..BaseNode::default() + expect![[r#" + File { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 2, column: 18", + source: "import \"path/foo\"\nimport \"path/bar\"", }, - alias: None, - path: StringLit { + }, + name: "", + metadata: "parser-type=rust", + package: None, + imports: [ + ImportDeclaration { base: BaseNode { - location: loc.get(1, 8, 1, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "import \"path/foo\"", + }, + }, + alias: None, + path: StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 18", + source: "\"path/foo\"", + }, + }, + value: "path/foo", }, - value: "path/foo".to_string() - } - }, - ImportDeclaration { - base: BaseNode { - location: loc.get(2, 1, 2, 18), - ..BaseNode::default() }, - alias: None, - path: StringLit { + ImportDeclaration { base: BaseNode { - location: loc.get(2, 8, 2, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 1", + end: "line: 2, column: 18", + source: "import \"path/bar\"", + }, }, - value: "path/bar".to_string() - } - } - ], - body: vec![], - eof: vec![], - } - ) + alias: None, + path: StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 8", + end: "line: 2, column: 18", + source: "\"path/bar\"", + }, + }, + value: "path/bar", + }, + }, + ], + body: [], + eof: [], + } + "#]], + ); } #[test] fn package_and_imports() { - let mut p = Parser::new( + test_file( r#" package baz import "path/foo" import "path/bar""#, - ); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - File { - base: BaseNode { - location: loc.get(2, 1, 5, 18), - ..BaseNode::default() - }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), - package: Some(PackageClause { + expect![[r#" + File { base: BaseNode { - location: loc.get(2, 1, 2, 12), - ..BaseNode::default() - }, - name: Identifier { - base: BaseNode { - location: loc.get(2, 9, 2, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 1", + end: "line: 5, column: 18", + source: "package baz\n\nimport \"path/foo\"\nimport \"path/bar\"", }, - name: "baz".to_string() - } - }), - imports: vec![ - ImportDeclaration { - base: BaseNode { - location: loc.get(4, 1, 4, 18), - ..BaseNode::default() + }, + name: "", + metadata: "parser-type=rust", + package: Some( + PackageClause { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 1", + end: "line: 2, column: 12", + source: "package baz", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 9", + end: "line: 2, column: 12", + source: "baz", + }, + }, + name: "baz", + }, }, - alias: None, - path: StringLit { + ), + imports: [ + ImportDeclaration { base: BaseNode { - location: loc.get(4, 8, 4, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 4, column: 1", + end: "line: 4, column: 18", + source: "import \"path/foo\"", + }, + }, + alias: None, + path: StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 8", + end: "line: 4, column: 18", + source: "\"path/foo\"", + }, + }, + value: "path/foo", }, - value: "path/foo".to_string() - } - }, - ImportDeclaration { - base: BaseNode { - location: loc.get(5, 1, 5, 18), - ..BaseNode::default() }, - alias: None, - path: StringLit { + ImportDeclaration { base: BaseNode { - location: loc.get(5, 8, 5, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 5, column: 1", + end: "line: 5, column: 18", + source: "import \"path/bar\"", + }, }, - value: "path/bar".to_string() - } - } - ], - body: vec![], - eof: vec![], - }, - ) + alias: None, + path: StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 5, column: 8", + end: "line: 5, column: 18", + source: "\"path/bar\"", + }, + }, + value: "path/bar", + }, + }, + ], + body: [], + eof: [], + } + "#]], + ); } #[test] fn package_and_imports_and_body() { - let mut p = Parser::new( + test_file( r#" package baz @@ -909,96 +1340,138 @@ import "path/foo" import "path/bar" 1 + 1"#, - ); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - File { - base: BaseNode { - location: loc.get(2, 1, 7, 6), - ..BaseNode::default() - }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), - package: Some(PackageClause { + expect![[r#" + File { base: BaseNode { - location: loc.get(2, 1, 2, 12), - ..BaseNode::default() - }, - name: Identifier { - base: BaseNode { - location: loc.get(2, 9, 2, 12), - ..BaseNode::default() - }, - name: "baz".to_string() - } - }), - imports: vec![ - ImportDeclaration { - base: BaseNode { - location: loc.get(4, 1, 4, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 1", + end: "line: 7, column: 6", + source: "package baz\n\nimport \"path/foo\"\nimport \"path/bar\"\n\n1 + 1", }, - alias: None, - path: StringLit { + }, + name: "", + metadata: "parser-type=rust", + package: Some( + PackageClause { base: BaseNode { - location: loc.get(4, 8, 4, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 1", + end: "line: 2, column: 12", + source: "package baz", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 9", + end: "line: 2, column: 12", + source: "baz", + }, + }, + name: "baz", }, - value: "path/foo".to_string() - } - }, - ImportDeclaration { - base: BaseNode { - location: loc.get(5, 1, 5, 18), - ..BaseNode::default() }, - alias: None, - path: StringLit { + ), + imports: [ + ImportDeclaration { base: BaseNode { - location: loc.get(5, 8, 5, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 4, column: 1", + end: "line: 4, column: 18", + source: "import \"path/foo\"", + }, + }, + alias: None, + path: StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 8", + end: "line: 4, column: 18", + source: "\"path/foo\"", + }, + }, + value: "path/foo", }, - value: "path/bar".to_string() - } - } - ], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(7, 1, 7, 6), - ..BaseNode::default() - }, - expression: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(7, 1, 7, 6), - ..BaseNode::default() }, - operator: Operator::AdditionOperator, - left: Expression::Integer(IntegerLit { + ImportDeclaration { base: BaseNode { - location: loc.get(7, 1, 7, 2), - ..BaseNode::default() + location: SourceLocation { + start: "line: 5, column: 1", + end: "line: 5, column: 18", + source: "import \"path/bar\"", + }, }, - value: 1 - }), - right: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(7, 5, 7, 6), - ..BaseNode::default() + alias: None, + path: StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 5, column: 8", + end: "line: 5, column: 18", + source: "\"path/bar\"", + }, + }, + value: "path/bar", + }, + }, + ], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 7, column: 1", + end: "line: 7, column: 6", + source: "1 + 1", + }, + }, + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 7, column: 1", + end: "line: 7, column: 6", + source: "1 + 1", + }, + }, + operator: AdditionOperator, + left: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 7, column: 1", + end: "line: 7, column: 2", + source: "1", + }, + }, + value: 1, + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 7, column: 5", + end: "line: 7, column: 6", + source: "1", + }, + }, + value: 1, + }, + ), + }, + ), }, - value: 1 - }) - })) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]], + ); } #[test] fn optional_query_metadata() { - let mut p = Parser::new( + test_file( r#"option task = { name: "foo", every: 1h, @@ -1006,2937 +1479,4392 @@ fn optional_query_metadata() { cron: "0 2 * * *", retry: 5, }"#, - ); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - File { - base: BaseNode { - location: loc.get(1, 1, 7, 7), - ..BaseNode::default() - }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), - package: None, - imports: vec![], - body: vec![Statement::Option(Box::new(OptionStmt { + expect![[r#" + File { base: BaseNode { - location: loc.get(1, 1, 7, 7), - ..BaseNode::default() - }, - assignment: Assignment::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 8, 7, 7), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 8, 1, 12), - ..BaseNode::default() - }, - name: "task".to_string() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 7, column: 7", + source: "option task = {\n\t\t\t\tname: \"foo\",\n\t\t\t\tevery: 1h,\n\t\t\t\tdelay: 10m,\n\t\t\t\tcron: \"0 2 * * *\",\n\t\t\t\tretry: 5,\n\t\t\t }", }, - init: Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 15, 7, 7), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![ - Property { - base: BaseNode { - location: loc.get(2, 5, 2, 16), - ..BaseNode::default() + }, + name: "", + metadata: "parser-type=rust", + package: None, + imports: [], + body: [ + Option( + OptionStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 7, column: 7", + source: "option task = {\n\t\t\t\tname: \"foo\",\n\t\t\t\tevery: 1h,\n\t\t\t\tdelay: 10m,\n\t\t\t\tcron: \"0 2 * * *\",\n\t\t\t\tretry: 5,\n\t\t\t }", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 5, 2, 9), - ..BaseNode::default() - }, - name: "name".to_string() - }), - separator: vec![], - value: Some(Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(2, 11, 2, 16), - ..BaseNode::default() - }, - value: "foo".to_string() - })), - comma: vec![], }, - Property { - base: BaseNode { - location: loc.get(3, 5, 3, 14), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { + assignment: Variable( + VariableAssgn { base: BaseNode { - location: loc.get(3, 5, 3, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 7, column: 7", + source: "task = {\n\t\t\t\tname: \"foo\",\n\t\t\t\tevery: 1h,\n\t\t\t\tdelay: 10m,\n\t\t\t\tcron: \"0 2 * * *\",\n\t\t\t\tretry: 5,\n\t\t\t }", + }, }, - name: "every".to_string() - }), - separator: vec![], - value: Some(Expression::Duration(DurationLit { - base: BaseNode { - location: loc.get(3, 12, 3, 14), - ..BaseNode::default() + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 12", + source: "task", + }, + }, + name: "task", }, - values: vec![Duration { - magnitude: 1, - unit: "h".to_string() - }] - })), - comma: vec![], - }, - Property { - base: BaseNode { - location: loc.get(4, 5, 4, 15), - ..BaseNode::default() + init: Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 7, column: 7", + source: "{\n\t\t\t\tname: \"foo\",\n\t\t\t\tevery: 1h,\n\t\t\t\tdelay: 10m,\n\t\t\t\tcron: \"0 2 * * *\",\n\t\t\t\tretry: 5,\n\t\t\t }", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 5", + end: "line: 2, column: 16", + source: "name: \"foo\"", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 5", + end: "line: 2, column: 9", + source: "name", + }, + }, + name: "name", + }, + ), + separator: [], + value: Some( + StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 11", + end: "line: 2, column: 16", + source: "\"foo\"", + }, + }, + value: "foo", + }, + ), + ), + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 5", + end: "line: 3, column: 14", + source: "every: 1h", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 5", + end: "line: 3, column: 10", + source: "every", + }, + }, + name: "every", + }, + ), + separator: [], + value: Some( + Duration( + DurationLit { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 12", + end: "line: 3, column: 14", + source: "1h", + }, + }, + values: [ + Duration { + magnitude: 1, + unit: "h", + }, + ], + }, + ), + ), + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 5", + end: "line: 4, column: 15", + source: "delay: 10m", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 5", + end: "line: 4, column: 10", + source: "delay", + }, + }, + name: "delay", + }, + ), + separator: [], + value: Some( + Duration( + DurationLit { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 12", + end: "line: 4, column: 15", + source: "10m", + }, + }, + values: [ + Duration { + magnitude: 10, + unit: "m", + }, + ], + }, + ), + ), + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 5, column: 5", + end: "line: 5, column: 22", + source: "cron: \"0 2 * * *\"", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 5, column: 5", + end: "line: 5, column: 9", + source: "cron", + }, + }, + name: "cron", + }, + ), + separator: [], + value: Some( + StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 5, column: 11", + end: "line: 5, column: 22", + source: "\"0 2 * * *\"", + }, + }, + value: "0 2 * * *", + }, + ), + ), + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 6, column: 5", + end: "line: 6, column: 13", + source: "retry: 5", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 6, column: 5", + end: "line: 6, column: 10", + source: "retry", + }, + }, + name: "retry", + }, + ), + separator: [], + value: Some( + Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 6, column: 12", + end: "line: 6, column: 13", + source: "5", + }, + }, + value: 5, + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(4, 5, 4, 10), - ..BaseNode::default() - }, - name: "delay".to_string() - }), - separator: vec![], - value: Some(Expression::Duration(DurationLit { - base: BaseNode { - location: loc.get(4, 12, 4, 15), - ..BaseNode::default() - }, - values: vec![Duration { - magnitude: 10, - unit: "m".to_string() - }] - })), - comma: vec![], + ), + }, + ), + ], + eof: [], + } + "#]], + ); +} + +#[test] +fn qualified_option() { + test_file( + r#"option alert.state = "Warning""#, + expect![[r#" + File { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 31", + source: "option alert.state = \"Warning\"", + }, + }, + name: "", + metadata: "parser-type=rust", + package: None, + imports: [], + body: [ + Option( + OptionStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 31", + source: "option alert.state = \"Warning\"", }, - Property { + }, + assignment: Member( + MemberAssgn { base: BaseNode { - location: loc.get(5, 5, 5, 22), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(5, 5, 5, 9), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 31", + source: "alert.state = \"Warning\"", }, - name: "cron".to_string() - }), - separator: vec![], - value: Some(Expression::StringLit(StringLit { + }, + member: MemberExpr { base: BaseNode { - location: loc.get(5, 11, 5, 22), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 19", + source: "alert.state", + }, }, - value: "0 2 * * *".to_string() - })), - comma: vec![], - }, - Property { - base: BaseNode { - location: loc.get(6, 5, 6, 13), - ..BaseNode::default() + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 13", + source: "alert", + }, + }, + name: "alert", + }, + ), + lbrack: [], + property: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 19", + source: "state", + }, + }, + name: "state", + }, + ), + rbrack: [], }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(6, 5, 6, 10), - ..BaseNode::default() + init: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 22", + end: "line: 1, column: 31", + source: "\"Warning\"", + }, + }, + value: "Warning", }, - name: "retry".to_string() - }), - separator: vec![], - value: Some(Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(6, 12, 6, 13), - ..BaseNode::default() - }, - value: 5 - })), - comma: vec![], - } - ], - rbrace: vec![], - })) - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] -fn optional_query_metadata_preceding_query_text() { - let mut p = Parser::new( - r#"option task = { - name: "foo", // Name of task - every: 1h, // Execution frequency of task - } - - // Task will execute the following query - from() |> count()"#, - ); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, +fn builtin() { + test_file( + r#"builtin from : int"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 7, 22), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 19", + source: "builtin from : int", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![ - Statement::Option(Box::new(OptionStmt { - base: BaseNode { - location: loc.get(1, 1, 4, 6), - ..BaseNode::default() - }, - assignment: Assignment::Variable(Box::new(VariableAssgn { + imports: [], + body: [ + Builtin( + BuiltinStmt { base: BaseNode { - location: loc.get(1, 8, 4, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 19", + source: "builtin from : int", + }, }, + colon: [], id: Identifier { base: BaseNode { - location: loc.get(1, 8, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 13", + source: "from", + }, }, - name: "task".to_string() + name: "from", }, - init: Expression::Object(Box::new(ObjectExpr { + ty: TypeExpression { base: BaseNode { - location: loc.get(1, 15, 4, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 16", + end: "line: 1, column: 19", + source: "int", + }, }, - lbrace: vec![], - with: None, - properties: vec![ - Property { + monotype: Basic( + NamedType { base: BaseNode { - location: loc.get(2, 6, 2, 17), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 6, 2, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 16", + end: "line: 1, column: 19", + source: "int", }, - name: "name".to_string() - }), - separator: vec![], - value: Some(Expression::StringLit(StringLit { + }, + name: Identifier { base: BaseNode { - location: loc.get(2, 12, 2, 17), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 16", + end: "line: 1, column: 19", + source: "int", + }, }, - value: "foo".to_string() - })), - comma: vec![], - }, - Property { - base: BaseNode { - location: loc.get(3, 6, 3, 15), - ..BaseNode::default() + name: "int", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(3, 6, 3, 11), - comments: vec![ast::Comment { - text: String::from("// Name of task\n"), - }], - ..BaseNode::default() - }, - name: "every".to_string() - }), - separator: vec![], - value: Some(Expression::Duration(DurationLit { - base: BaseNode { - location: loc.get(3, 13, 3, 15), - ..BaseNode::default() - }, - values: vec![Duration { - magnitude: 1, - unit: "h".to_string() - }] - })), - comma: vec![], - } - ], - rbrace: vec![ast::Comment { - text: String::from("// Execution frequency of task\n"), - }], - })) - })) - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(7, 5, 7, 22), - ..BaseNode::default() - }, - expression: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(7, 5, 7, 22), - ..BaseNode::default() + }, + ), + constraints: [], }, - argument: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(7, 5, 7, 11), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(7, 5, 7, 9), - comments: vec![ast::Comment { - text: String::from( - "// Task will execute the following query\n" - ), - }], - ..BaseNode::default() - }, - name: "from".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })), - call: CallExpr { - base: BaseNode { - location: loc.get(7, 15, 7, 22), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(7, 15, 7, 20), - ..BaseNode::default() - }, - name: "count".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - } - })), - })) - ], - eof: vec![], - }, - ) -} - -#[test] -fn qualified_option() { - let mut p = Parser::new(r#"option alert.state = "Warning""#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - File { - base: BaseNode { - location: loc.get(1, 1, 1, 31), - ..BaseNode::default() - }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), - package: None, - imports: vec![], - body: vec![Statement::Option(Box::new(OptionStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 31), - ..BaseNode::default() - }, - assignment: Assignment::Member(Box::new(MemberAssgn { - base: BaseNode { - location: loc.get(1, 8, 1, 31), - ..BaseNode::default() - }, - member: MemberExpr { - base: BaseNode { - location: loc.get(1, 8, 1, 19), - ..BaseNode::default() - }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 8, 1, 13), - ..BaseNode::default() - }, - name: "alert".to_string() - }), - lbrack: vec![], - property: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 14, 1, 19), - ..BaseNode::default() - }, - name: "state".to_string() - }), - rbrack: vec![], }, - init: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 22, 1, 31), - ..BaseNode::default() - }, - value: "Warning".to_string() - }) - })) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]], + ); } #[test] -fn builtin() { - let mut p = Parser::new(r#"builtin from : int"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - File { - base: BaseNode { - location: loc.get(1, 1, 1, 19), - ..BaseNode::default() - }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), - package: None, - imports: vec![], - body: vec![Statement::Builtin(Box::new(BuiltinStmt { +fn comment() { + test_file( + r#"// Comment + from()"#, + expect![[r#" + File { base: BaseNode { - location: loc.get(1, 1, 1, 19), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 9, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 10", + source: "from()", }, - name: "from".to_string() }, - colon: vec![], - ty: TypeExpression { - base: BaseNode { - location: loc.get(1, 16, 1, 19), - ..BaseNode::default() - }, - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 16, 1, 19), - ..BaseNode::default() - }, - name: Identifier { + name: "", + metadata: "parser-type=rust", + package: None, + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 16, 1, 19), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 10", + source: "from()", + }, }, - name: "int".to_string() + expression: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 10", + source: "from()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 8", + source: "from", + }, + comments: [ + Comment { + text: "// Comment\n", + }, + ], + }, + name: "from", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), }, - }), - constraints: vec![] - }, - }))], - eof: vec![], - }, - ) -} - -#[test] -fn comment() { - let mut p = Parser::new( - r#"// Comment - from()"#, + ), + ], + eof: [], + } + "#]], ); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - File { - base: BaseNode { - location: loc.get(2, 4, 2, 10), - ..BaseNode::default() - }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), - package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(2, 4, 2, 10), - ..BaseNode::default() - }, - expression: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(2, 4, 2, 10), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 4, 2, 8), - comments: vec![ast::Comment { - text: String::from("// Comment\n"), - }], - ..BaseNode::default() - }, - name: "from".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })), - }))], - eof: vec![], - }, - ) } #[test] fn comment_builtin() { - let mut p = Parser::new( + test_file( r#"// Comment builtin foo // colon comment : int"#, - ); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - File { - base: BaseNode { - location: loc.get(2, 1, 4, 6), - ..BaseNode::default() - }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), - package: None, - imports: vec![], - body: vec![Statement::Builtin(Box::new(BuiltinStmt { + expect![[r#" + File { base: BaseNode { - location: loc.get(2, 1, 4, 6), - comments: vec![ast::Comment { - text: String::from("// Comment\n"), - }], - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(2, 9, 2, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 1", + end: "line: 4, column: 6", + source: "builtin foo\n// colon comment\n: int", }, - name: "foo".to_string() }, - colon: vec![ast::Comment { - text: String::from("// colon comment\n"), - }], - ty: TypeExpression { - base: BaseNode { - location: loc.get(4, 3, 4, 6), - ..BaseNode::default() - }, - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(4, 3, 4, 6), - ..BaseNode::default() - }, - name: Identifier { + name: "", + metadata: "parser-type=rust", + package: None, + imports: [], + body: [ + Builtin( + BuiltinStmt { base: BaseNode { - location: loc.get(4, 3, 4, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 1", + end: "line: 4, column: 6", + source: "builtin foo\n// colon comment\n: int", + }, + comments: [ + Comment { + text: "// Comment\n", + }, + ], + }, + colon: [ + Comment { + text: "// colon comment\n", + }, + ], + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 9", + end: "line: 2, column: 12", + source: "foo", + }, + }, + name: "foo", + }, + ty: TypeExpression { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 3", + end: "line: 4, column: 6", + source: "int", + }, + }, + monotype: Basic( + NamedType { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 3", + end: "line: 4, column: 6", + source: "int", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 3", + end: "line: 4, column: 6", + source: "int", + }, + }, + name: "int", + }, + }, + ), + constraints: [], }, - name: "int".to_string() }, - }), - constraints: vec![] - }, - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]], + ); } #[test] fn comment_function_body() { - let mut p = Parser::new( + test_file( r#"fn = (tables=<-) => // comment (tables)"#, - ); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - File { - base: BaseNode { - location: loc.get(1, 1, 3, 9), - ..BaseNode::default() - }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), - package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { + expect![[r#" + File { base: BaseNode { - location: loc.get(1, 1, 3, 9), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 3), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 3, column: 9", + source: "fn = (tables=<-) =>\n// comment\n(tables)", }, - name: "fn".to_string() }, - init: Expression::Function(Box::new(FunctionExpr { - base: BaseNode { - location: loc.get(1, 6, 3, 9), - ..BaseNode::default() - }, - lparen: vec![], - params: vec![Property { - base: BaseNode { - location: loc.get(1, 7, 1, 16), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { + name: "", + metadata: "parser-type=rust", + package: None, + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(1, 7, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 3, column: 9", + source: "fn = (tables=<-) =>\n// comment\n(tables)", + }, }, - name: "tables".to_string() - }), - separator: vec![], - value: Some(Expression::PipeLit(PipeLit { - base: BaseNode { - location: loc.get(1, 14, 1, 16), - ..BaseNode::default() - }, - })), - comma: vec![], - }], - rparen: vec![], - arrow: vec![], - body: FunctionBody::Expr(Expression::Paren(Box::new(ParenExpr { - base: BaseNode { - location: loc.get(3, 1, 3, 9), - ..BaseNode::default() - }, - lparen: vec![ast::Comment { - text: String::from("// comment\n"), - }], - expression: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(3, 2, 3, 8), - ..BaseNode::default() - }, - name: "tables".to_string(), - }), - rparen: vec![], - }))) - })) - }))], - eof: vec![], - }, - ) + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 3", + source: "fn", + }, + }, + name: "fn", + }, + init: Function( + FunctionExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 3, column: 9", + source: "(tables=<-) =>\n// comment\n(tables)", + }, + }, + lparen: [], + params: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 16", + source: "tables=<-", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 13", + source: "tables", + }, + }, + name: "tables", + }, + ), + separator: [], + value: Some( + PipeLit( + PipeLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 16", + source: "<-", + }, + }, + }, + ), + ), + comma: [], + }, + ], + rparen: [], + arrow: [], + body: Expr( + Paren( + ParenExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 1", + end: "line: 3, column: 9", + source: "(tables)", + }, + }, + lparen: [ + Comment { + text: "// comment\n", + }, + ], + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 2", + end: "line: 3, column: 8", + source: "tables", + }, + }, + name: "tables", + }, + ), + rparen: [], + }, + ), + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn identifier_with_number() { - let mut p = Parser::new(r#"tan2()"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"tan2()"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "tan2()", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() - }, - expression: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() - }, - name: "tan2".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })) - }))], - eof: vec![], - }, - ) + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "tan2()", + }, + }, + expression: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "tan2()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "tan2", + }, + }, + name: "tan2", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn regex_match_operators() { - let mut p = Parser::new(r#""a" =~ /.*/ and "b" !~ /c$/"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#""a" =~ /.*/ and "b" !~ /c$/"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 28), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 28", + source: "\"a\" =~ /.*/ and \"b\" !~ /c$/", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 28), - ..BaseNode::default() - }, - expression: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 28), - ..BaseNode::default() - }, - operator: LogicalOperator::AndOperator, - left: Expression::Binary(Box::new(BinaryExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - operator: Operator::RegexpMatchOperator, - left: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() - }, - value: "a".to_string() - }), - right: Expression::Regexp(RegexpLit { - base: BaseNode { - location: loc.get(1, 8, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 28", + source: "\"a\" =~ /.*/ and \"b\" !~ /c$/", }, - value: ".*".to_string() - }) - })), - right: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 17, 1, 28), - ..BaseNode::default() }, - operator: Operator::NotRegexpMatchOperator, - left: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 17, 1, 20), - ..BaseNode::default() + expression: Logical( + LogicalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 28", + source: "\"a\" =~ /.*/ and \"b\" !~ /c$/", + }, + }, + operator: AndOperator, + left: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "\"a\" =~ /.*/", + }, + }, + operator: RegexpMatchOperator, + left: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "\"a\"", + }, + }, + value: "a", + }, + ), + right: Regexp( + RegexpLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 12", + source: "/.*/", + }, + }, + value: ".*", + }, + ), + }, + ), + right: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 17", + end: "line: 1, column: 28", + source: "\"b\" !~ /c$/", + }, + }, + operator: NotRegexpMatchOperator, + left: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 17", + end: "line: 1, column: 20", + source: "\"b\"", + }, + }, + value: "b", + }, + ), + right: Regexp( + RegexpLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 24", + end: "line: 1, column: 28", + source: "/c$/", + }, + }, + value: "c$", + }, + ), + }, + ), }, - value: "b".to_string() - }), - right: Expression::Regexp(RegexpLit { - base: BaseNode { - location: loc.get(1, 24, 1, 28), - ..BaseNode::default() - }, - value: "c$".to_string() - }) - })) - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn declare_variable_as_an_int() { - let mut p = Parser::new(r#"howdy = 1"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"howdy = 1"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 10", + source: "howdy = 1", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 10), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 10", + source: "howdy = 1", + }, + }, + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "howdy", + }, + }, + name: "howdy", + }, + init: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 10", + source: "1", + }, + }, + value: 1, + }, + ), }, - name: "howdy".to_string() - }, - init: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 9, 1, 10), - ..BaseNode::default() - }, - value: 1 - }) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]], + ); } #[test] fn declare_variable_as_a_float() { - let mut p = Parser::new(r#"howdy = 1.1"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"howdy = 1.1"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "howdy = 1.1", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "howdy = 1.1", + }, + }, + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "howdy", + }, + }, + name: "howdy", + }, + init: Float( + FloatLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 12", + source: "1.1", + }, + }, + value: 1.1, + }, + ), }, - name: "howdy".to_string() - }, - init: Expression::Float(FloatLit { - base: BaseNode { - location: loc.get(1, 9, 1, 12), - ..BaseNode::default() - }, - value: 1.1 - }) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]], + ); } #[test] fn declare_variable_as_an_array() { - let mut p = Parser::new(r#"howdy = [1, 2, 3, 4]"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"howdy = [1, 2, 3, 4]"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 21), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 21", + source: "howdy = [1, 2, 3, 4]", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 21), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - name: "howdy".to_string() - }, - init: Expression::Array(Box::new(ArrayExpr { - base: BaseNode { - location: loc.get(1, 9, 1, 21), - ..BaseNode::default() - }, - lbrack: vec![], - elements: vec![ - ArrayItem { - expression: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 10, 1, 11), - ..BaseNode::default() - }, - value: 1 - }), - comma: vec![], + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 21", + source: "howdy = [1, 2, 3, 4]", + }, }, - ArrayItem { - expression: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 13, 1, 14), - ..BaseNode::default() + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "howdy", }, - value: 2 - }), - comma: vec![], + }, + name: "howdy", }, - ArrayItem { - expression: Expression::Integer(IntegerLit { + init: Array( + ArrayExpr { base: BaseNode { - location: loc.get(1, 16, 1, 17), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 21", + source: "[1, 2, 3, 4]", + }, }, - value: 3 - }), - comma: vec![], - }, - ArrayItem { - expression: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 19, 1, 20), - ..BaseNode::default() - }, - value: 4 - }), - comma: vec![], - } - ], - rbrack: vec![], - })) - }))], - eof: vec![], - }, - ) + lbrack: [], + elements: [ + ArrayItem { + expression: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 11", + source: "1", + }, + }, + value: 1, + }, + ), + comma: [], + }, + ArrayItem { + expression: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 13", + end: "line: 1, column: 14", + source: "2", + }, + }, + value: 2, + }, + ), + comma: [], + }, + ArrayItem { + expression: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 16", + end: "line: 1, column: 17", + source: "3", + }, + }, + value: 3, + }, + ), + comma: [], + }, + ArrayItem { + expression: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 19", + end: "line: 1, column: 20", + source: "4", + }, + }, + value: 4, + }, + ), + comma: [], + }, + ], + rbrack: [], + }, + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn declare_variable_as_an_empty_array() { - let mut p = Parser::new(r#"howdy = []"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"howdy = []"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 11), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 11", + source: "howdy = []", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 11), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 11", + source: "howdy = []", + }, + }, + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "howdy", + }, + }, + name: "howdy", + }, + init: Array( + ArrayExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 11", + source: "[]", + }, + }, + lbrack: [], + elements: [], + rbrack: [], + }, + ), }, - name: "howdy".to_string() - }, - init: Expression::Array(Box::new(ArrayExpr { - base: BaseNode { - location: loc.get(1, 9, 1, 11), - ..BaseNode::default() - }, - lbrack: vec![], - elements: vec![], - rbrack: vec![], - })) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]], + ); } #[test] fn parse_empty_dict() { - let mut p = Parser::new(r#"[:]"#); - let parsed = p.parse_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - Expression::Dict(Box::new(DictExpr { + test_file( + r#"[:]"#, + expect![[r#" + File { base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "[:]", + }, }, - elements: vec![], - lbrack: vec![], - rbrack: vec![], - })) - ) + name: "", + metadata: "parser-type=rust", + package: None, + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "[:]", + }, + }, + expression: Dict( + DictExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "[:]", + }, + }, + lbrack: [], + elements: [], + rbrack: [], + }, + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn parse_single_element_dict() { - let mut p = Parser::new(r#"["a": 0]"#); - let parsed = p.parse_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - Expression::Dict(Box::new(DictExpr { + test_file( + r#"["a": 0]"#, + expect![[r#" + File { base: BaseNode { - location: loc.get(1, 1, 1, 9), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 9", + source: "[\"a\": 0]", + }, }, - elements: vec![DictItem { - key: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 2, 1, 5), - ..BaseNode::default() + name: "", + metadata: "parser-type=rust", + package: None, + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 9", + source: "[\"a\": 0]", + }, + }, + expression: Dict( + DictExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 9", + source: "[\"a\": 0]", + }, + }, + lbrack: [], + elements: [ + DictItem { + key: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 5", + source: "\"a\"", + }, + }, + value: "a", + }, + ), + val: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 8", + source: "0", + }, + }, + value: 0, + }, + ), + comma: [], + }, + ], + rbrack: [], + }, + ), }, - value: "a".to_string(), - }), - val: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 7, 1, 8), - ..BaseNode::default() - }, - value: 0, - }), - comma: vec![], - }], - lbrack: vec![], - rbrack: vec![], - })) - ) + ), + ], + eof: [], + } + "#]], + ); } #[test] fn parse_multi_element_dict() { - let mut p = Parser::new(r#"["a": 0, "b": 1]"#); - let parsed = p.parse_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - Expression::Dict(Box::new(DictExpr { + test_file( + r#"["a": 0, "b": 1]"#, + expect![[r#" + File { base: BaseNode { - location: loc.get(1, 1, 1, 17), - ..BaseNode::default() - }, - elements: vec![ - DictItem { - key: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 2, 1, 5), - ..BaseNode::default() - }, - value: "a".to_string(), - }), - val: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 7, 1, 8), - ..BaseNode::default() - }, - value: 0, - }), - comma: vec![], + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 17", + source: "[\"a\": 0, \"b\": 1]", }, - DictItem { - key: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 10, 1, 13), - ..BaseNode::default() - }, - value: "b".to_string(), - }), - val: Expression::Integer(IntegerLit { + }, + name: "", + metadata: "parser-type=rust", + package: None, + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 15, 1, 16), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 17", + source: "[\"a\": 0, \"b\": 1]", + }, }, - value: 1, - }), - comma: vec![], - }, + expression: Dict( + DictExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 17", + source: "[\"a\": 0, \"b\": 1]", + }, + }, + lbrack: [], + elements: [ + DictItem { + key: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 5", + source: "\"a\"", + }, + }, + value: "a", + }, + ), + val: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 8", + source: "0", + }, + }, + value: 0, + }, + ), + comma: [], + }, + DictItem { + key: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 13", + source: "\"b\"", + }, + }, + value: "b", + }, + ), + val: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 16", + source: "1", + }, + }, + value: 1, + }, + ), + comma: [], + }, + ], + rbrack: [], + }, + ), + }, + ), ], - lbrack: vec![], - rbrack: vec![], - })) - ) + eof: [], + } + "#]], + ); } #[test] fn parse_dict_trailing_comma0() { - let mut p = Parser::new(r#"["a": 0, ]"#); - let parsed = p.parse_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - Expression::Dict(Box::new(DictExpr { + test_file( + r#"["a": 0, ]"#, + expect![[r#" + File { base: BaseNode { - location: loc.get(1, 1, 1, 11), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 11", + source: "[\"a\": 0, ]", + }, }, - elements: vec![DictItem { - key: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 2, 1, 5), - ..BaseNode::default() + name: "", + metadata: "parser-type=rust", + package: None, + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 11", + source: "[\"a\": 0, ]", + }, + }, + expression: Dict( + DictExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 11", + source: "[\"a\": 0, ]", + }, + }, + lbrack: [], + elements: [ + DictItem { + key: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 5", + source: "\"a\"", + }, + }, + value: "a", + }, + ), + val: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 8", + source: "0", + }, + }, + value: 0, + }, + ), + comma: [], + }, + ], + rbrack: [], + }, + ), }, - value: "a".to_string(), - }), - val: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 7, 1, 8), - ..BaseNode::default() - }, - value: 0, - }), - comma: vec![], - }], - lbrack: vec![], - rbrack: vec![], - })) - ) + ), + ], + eof: [], + } + "#]], + ); } #[test] fn parse_dict_trailing_comma1() { - let mut p = Parser::new(r#"["a": 0, "b": 1, ]"#); - let parsed = p.parse_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - Expression::Dict(Box::new(DictExpr { + test_file( + r#"["a": 0, "b": 1, ]"#, + expect![[r#" + File { base: BaseNode { - location: loc.get(1, 1, 1, 19), - ..BaseNode::default() - }, - elements: vec![ - DictItem { - key: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 2, 1, 5), - ..BaseNode::default() - }, - value: "a".to_string(), - }), - val: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 7, 1, 8), - ..BaseNode::default() - }, - value: 0, - }), - comma: vec![], + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 19", + source: "[\"a\": 0, \"b\": 1, ]", }, - DictItem { - key: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 10, 1, 13), - ..BaseNode::default() - }, - value: "b".to_string(), - }), - val: Expression::Integer(IntegerLit { + }, + name: "", + metadata: "parser-type=rust", + package: None, + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 15, 1, 16), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 19", + source: "[\"a\": 0, \"b\": 1, ]", + }, }, - value: 1, - }), - comma: vec![], - }, + expression: Dict( + DictExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 19", + source: "[\"a\": 0, \"b\": 1, ]", + }, + }, + lbrack: [], + elements: [ + DictItem { + key: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 5", + source: "\"a\"", + }, + }, + value: "a", + }, + ), + val: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 8", + source: "0", + }, + }, + value: 0, + }, + ), + comma: [], + }, + DictItem { + key: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 13", + source: "\"b\"", + }, + }, + value: "b", + }, + ), + val: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 16", + source: "1", + }, + }, + value: 1, + }, + ), + comma: [], + }, + ], + rbrack: [], + }, + ), + }, + ), ], - lbrack: vec![], - rbrack: vec![], - })) - ) + eof: [], + } + "#]], + ); } #[test] fn parse_dict_arbitrary_keys() { - let mut p = Parser::new(r#"[1-1: 0, 1+1: 1]"#); - let parsed = p.parse_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - Expression::Dict(Box::new(DictExpr { + test_file( + r#"[1-1: 0, 1+1: 1]"#, + expect![[r#" + File { base: BaseNode { - location: loc.get(1, 1, 1, 17), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 17", + source: "[1-1: 0, 1+1: 1]", + }, }, - elements: vec![ - DictItem { - key: Expression::Binary(Box::new(BinaryExpr { + name: "", + metadata: "parser-type=rust", + package: None, + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 2, 1, 5), - ..BaseNode::default() - }, - operator: Operator::SubtractionOperator, - left: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 2, 1, 3), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 17", + source: "[1-1: 0, 1+1: 1]", }, - value: 1, - }), - right: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 4, 1, 5), - ..BaseNode::default() - }, - value: 1, - }), - })), - val: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 7, 1, 8), - ..BaseNode::default() }, - value: 0, - }), - comma: vec![], - }, - DictItem { - key: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 10, 1, 13), - ..BaseNode::default() - }, - operator: Operator::AdditionOperator, - left: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 10, 1, 11), - ..BaseNode::default() - }, - value: 1, - }), - right: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 12, 1, 13), - ..BaseNode::default() + expression: Dict( + DictExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 17", + source: "[1-1: 0, 1+1: 1]", + }, + }, + lbrack: [], + elements: [ + DictItem { + key: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 5", + source: "1-1", + }, + }, + operator: SubtractionOperator, + left: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 3", + source: "1", + }, + }, + value: 1, + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 5", + source: "1", + }, + }, + value: 1, + }, + ), + }, + ), + val: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 8", + source: "0", + }, + }, + value: 0, + }, + ), + comma: [], + }, + DictItem { + key: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 13", + source: "1+1", + }, + }, + operator: AdditionOperator, + left: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 11", + source: "1", + }, + }, + value: 1, + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 13", + source: "1", + }, + }, + value: 1, + }, + ), + }, + ), + val: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 16", + source: "1", + }, + }, + value: 1, + }, + ), + comma: [], + }, + ], + rbrack: [], }, - value: 1, - }), - })), - val: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 15, 1, 16), - ..BaseNode::default() - }, - value: 1, - }), - comma: vec![], - }, + ), + }, + ), ], - lbrack: vec![], - rbrack: vec![], - })) - ) + eof: [], + } + "#]], + ); } #[test] fn use_variable_to_declare_something() { - let mut p = Parser::new( + test_file( r#"howdy = 1 from()"#, - ); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - File { - base: BaseNode { - location: loc.get(1, 1, 2, 10), - ..BaseNode::default() - }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), - package: None, - imports: vec![], - body: vec![ - Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 10), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - name: "howdy".to_string() - }, - init: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 9, 1, 10), - ..BaseNode::default() - }, - value: 1 - }) - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(2, 4, 2, 10), - ..BaseNode::default() + expect![[r#" + File { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 2, column: 10", + source: "howdy = 1\n\t\t\tfrom()", }, - expression: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(2, 4, 2, 10), - ..BaseNode::default() + }, + name: "", + metadata: "parser-type=rust", + package: None, + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 10", + source: "howdy = 1", + }, + }, + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "howdy", + }, + }, + name: "howdy", + }, + init: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 10", + source: "1", + }, + }, + value: 1, + }, + ), }, - callee: Expression::Identifier(Identifier { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(2, 4, 2, 8), - ..BaseNode::default() - }, - name: "from".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })), - })) - ], - eof: vec![], - }, - ) + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 10", + source: "from()", + }, + }, + expression: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 10", + source: "from()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 8", + source: "from", + }, + }, + name: "from", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn variable_is_from_statement() { - let mut p = Parser::new( + test_file( r#"howdy = from() howdy.count()"#, - ); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - File { - base: BaseNode { - location: loc.get(1, 1, 2, 17), - ..BaseNode::default() - }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), - package: None, - imports: vec![], - body: vec![ - Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 15), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - name: "howdy".to_string() + expect![[r#" + File { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 2, column: 17", + source: "howdy = from()\n\t\t\thowdy.count()", }, - init: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(1, 9, 1, 15), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { + }, + name: "", + metadata: "parser-type=rust", + package: None, + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(1, 9, 1, 13), - ..BaseNode::default() - }, - name: "from".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })), - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(2, 4, 2, 17), - ..BaseNode::default() - }, - expression: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(2, 4, 2, 17), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 15", + source: "howdy = from()", + }, + }, + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "howdy", + }, + }, + name: "howdy", + }, + init: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 15", + source: "from()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 13", + source: "from", + }, + }, + name: "from", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), }, - callee: Expression::Member(Box::new(MemberExpr { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(2, 4, 2, 15), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 17", + source: "howdy.count()", + }, }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 4, 2, 9), - ..BaseNode::default() + expression: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 17", + source: "howdy.count()", + }, + }, + callee: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 15", + source: "howdy.count", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 9", + source: "howdy", + }, + }, + name: "howdy", + }, + ), + lbrack: [], + property: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 10", + end: "line: 2, column: 15", + source: "count", + }, + }, + name: "count", + }, + ), + rbrack: [], + }, + ), + lparen: [], + arguments: [], + rparen: [], }, - name: "howdy".to_string() - }), - lbrack: vec![], - property: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 10, 2, 15), - ..BaseNode::default() - }, - name: "count".to_string() - }), - rbrack: vec![], - })), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })) - })) - ], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn pipe_expression() { - let mut p = Parser::new(r#"from() |> count()"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"from() |> count()"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "from() |> count()", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 18), - ..BaseNode::default() - }, - expression: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 18), - ..BaseNode::default() - }, - argument: Expression::Call(Box::new(CallExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "from() |> count()", }, - name: "from".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })), - call: CallExpr { - base: BaseNode { - location: loc.get(1, 11, 1, 18), - ..BaseNode::default() }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 11, 1, 16), - ..BaseNode::default() - }, - name: "count".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - } - })) - }))], - eof: vec![], - }, - ) + expression: PipeExpr( + PipeExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "from() |> count()", + }, + }, + argument: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "from()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "from", + }, + }, + name: "from", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), + call: CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 18", + source: "count()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 16", + source: "count", + }, + }, + name: "count", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + }, + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn pipe_expression_to_member_expression_function() { - let mut p = Parser::new(r#"a |> b.c(d:e)"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"a |> b.c(d:e)"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 14", + source: "a |> b.c(d:e)", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 14), - ..BaseNode::default() - }, - expression: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 14), - ..BaseNode::default() - }, - argument: Expression::Identifier(Identifier { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "a".to_string() - }), - call: CallExpr { - base: BaseNode { - location: loc.get(1, 6, 1, 14), - ..BaseNode::default() - }, - callee: Expression::Member(Box::new(MemberExpr { - base: BaseNode { - location: loc.get(1, 6, 1, 9), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 14", + source: "a |> b.c(d:e)", }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() - }, - name: "b".to_string() - }), - lbrack: vec![], - property: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 8, 1, 9), - ..BaseNode::default() - }, - name: "c".to_string() - }), - rbrack: vec![], - })), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 10, 1, 13), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![Property { + }, + expression: PipeExpr( + PipeExpr { base: BaseNode { - location: loc.get(1, 10, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 14", + source: "a |> b.c(d:e)", + }, }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 10, 1, 11), - ..BaseNode::default() + argument: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, + }, + name: "a", }, - name: "d".to_string() - }), - separator: vec![], - value: Some(Expression::Identifier(Identifier { + ), + call: CallExpr { base: BaseNode { - location: loc.get(1, 12, 1, 13), - ..BaseNode::default() - }, - name: "e".to_string() - })), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - } - })) - }))], - eof: vec![], - }, - ) + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 14", + source: "b.c(d:e)", + }, + }, + callee: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 9", + source: "b.c", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "b", + }, + }, + name: "b", + }, + ), + lbrack: [], + property: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 9", + source: "c", + }, + }, + name: "c", + }, + ), + rbrack: [], + }, + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 13", + source: "d:e", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 13", + source: "d:e", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 11", + source: "d", + }, + }, + name: "d", + }, + ), + separator: [], + value: Some( + Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 13", + source: "e", + }, + }, + name: "e", + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], + }, + }, + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn literal_pipe_expression() { - let mut p = Parser::new(r#"5 |> pow2()"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"5 |> pow2()"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "5 |> pow2()", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - expression: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - argument: Expression::Integer(IntegerLit { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - value: 5, - }), - call: CallExpr { - base: BaseNode { - location: loc.get(1, 6, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "5 |> pow2()", + }, }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 6, 1, 10), - ..BaseNode::default() - }, - name: "pow2".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - } - })), - }))], - eof: vec![], - }, - ) + expression: PipeExpr( + PipeExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "5 |> pow2()", + }, + }, + argument: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "5", + }, + }, + value: 5, + }, + ), + call: CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 12", + source: "pow2()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 10", + source: "pow2", + }, + }, + name: "pow2", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + }, + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn member_expression_pipe_expression() { - let mut p = Parser::new(r#"foo.bar |> baz()"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"foo.bar |> baz()"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 17), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 17", + source: "foo.bar |> baz()", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 17), - ..BaseNode::default() - }, - expression: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 17), - ..BaseNode::default() - }, - argument: Expression::Member(Box::new(MemberExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 8), - ..BaseNode::default() - }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 17", + source: "foo.bar |> baz()", }, - name: "foo".to_string() - }), - lbrack: vec![], - property: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 5, 1, 8), - ..BaseNode::default() - }, - name: "bar".to_string() - }), - rbrack: vec![], - })), - call: CallExpr { - base: BaseNode { - location: loc.get(1, 12, 1, 17), - ..BaseNode::default() }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 12, 1, 15), - ..BaseNode::default() - }, - name: "baz".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - } - })) - }))], - eof: vec![], - }, - ) + expression: PipeExpr( + PipeExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 17", + source: "foo.bar |> baz()", + }, + }, + argument: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 8", + source: "foo.bar", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "foo", + }, + }, + name: "foo", + }, + ), + lbrack: [], + property: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 8", + source: "bar", + }, + }, + name: "bar", + }, + ), + rbrack: [], + }, + ), + call: CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 17", + source: "baz()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 15", + source: "baz", + }, + }, + name: "baz", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + }, + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn multiple_pipe_expressions() { - let mut p = Parser::new(r#"from() |> range() |> filter() |> count()"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"from() |> range() |> filter() |> count()"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 41), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 41", + source: "from() |> range() |> filter() |> count()", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 41), - ..BaseNode::default() - }, - expression: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 41), - ..BaseNode::default() - }, - argument: Expression::PipeExpr(Box::new(PipeExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 30), - ..BaseNode::default() - }, - argument: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 41", + source: "from() |> range() |> filter() |> count()", }, - argument: Expression::Call(Box::new(CallExpr { + }, + expression: PipeExpr( + PipeExpr { base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 41", + source: "from() |> range() |> filter() |> count()", + }, }, - callee: Expression::Identifier(Identifier { + argument: PipeExpr( + PipeExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 30", + source: "from() |> range() |> filter()", + }, + }, + argument: PipeExpr( + PipeExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "from() |> range()", + }, + }, + argument: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "from()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "from", + }, + }, + name: "from", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), + call: CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 18", + source: "range()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 16", + source: "range", + }, + }, + name: "range", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + }, + ), + call: CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 22", + end: "line: 1, column: 30", + source: "filter()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 22", + end: "line: 1, column: 28", + source: "filter", + }, + }, + name: "filter", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + }, + ), + call: CallExpr { base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() - }, - name: "from".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })), - call: CallExpr { - base: BaseNode { - location: loc.get(1, 11, 1, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 34", + end: "line: 1, column: 41", + source: "count()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 34", + end: "line: 1, column: 39", + source: "count", + }, + }, + name: "count", + }, + ), + lparen: [], + arguments: [], + rparen: [], }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 11, 1, 16), - ..BaseNode::default() - }, - name: "range".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - } - })), - call: CallExpr { - base: BaseNode { - location: loc.get(1, 22, 1, 30), - ..BaseNode::default() }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 22, 1, 28), - ..BaseNode::default() - }, - name: "filter".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - } - })), - call: CallExpr { - base: BaseNode { - location: loc.get(1, 34, 1, 41), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 34, 1, 39), - ..BaseNode::default() - }, - name: "count".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - } - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn pipe_expression_into_non_call_expression() { - let mut p = Parser::new(r#"foo() |> bar"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"foo() |> bar"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "foo() |> bar", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 13), - ..BaseNode::default() - }, - expression: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 13), - ..BaseNode::default() - }, - argument: Expression::Call(Box::new(CallExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "foo() |> bar", + }, }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() - }, - name: "foo".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })), - call: CallExpr { - base: BaseNode { - location: loc.get(1, 10, 1, 13), - errors: vec!["pipe destination must be a function call".to_string()], - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 10, 1, 13), - ..BaseNode::default() - }, - name: "bar".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - } - })), - }))], - eof: vec![], - }, - ) + expression: PipeExpr( + PipeExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "foo() |> bar", + }, + }, + argument: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "foo()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "foo", + }, + }, + name: "foo", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), + call: CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 13", + source: "bar", + }, + errors: [ + "pipe destination must be a function call", + ], + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 13", + source: "bar", + }, + }, + name: "bar", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + }, + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn two_variables_for_two_froms() { - let mut p = Parser::new( + test_file( r#"howdy = from() doody = from() howdy|>count() doody|>sum()"#, - ); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - File { - base: BaseNode { - location: loc.get(1, 1, 4, 16), - ..BaseNode::default() - }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), - package: None, - imports: vec![], - body: vec![ - Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 15), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - name: "howdy".to_string() - }, - init: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(1, 9, 1, 15), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 9, 1, 13), - ..BaseNode::default() - }, - name: "from".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })), - })), - Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(2, 4, 2, 18), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(2, 4, 2, 9), - ..BaseNode::default() - }, - name: "doody".to_string() - }, - init: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(2, 12, 2, 18), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 12, 2, 16), - ..BaseNode::default() - }, - name: "from".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })), - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(3, 4, 3, 18), - ..BaseNode::default() + expect![[r#" + File { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 4, column: 16", + source: "howdy = from()\n\t\t\tdoody = from()\n\t\t\thowdy|>count()\n\t\t\tdoody|>sum()", }, - expression: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(3, 4, 3, 18), - ..BaseNode::default() - }, - argument: Expression::Identifier(Identifier { + }, + name: "", + metadata: "parser-type=rust", + package: None, + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(3, 4, 3, 9), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 15", + source: "howdy = from()", + }, }, - name: "howdy".to_string() - }), - call: CallExpr { + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "howdy", + }, + }, + name: "howdy", + }, + init: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 15", + source: "from()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 13", + source: "from", + }, + }, + name: "from", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), + }, + ), + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(3, 11, 3, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 18", + source: "doody = from()", + }, }, - callee: Expression::Identifier(Identifier { + id: Identifier { base: BaseNode { - location: loc.get(3, 11, 3, 16), - ..BaseNode::default() - }, - name: "count".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - } - })) - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(4, 4, 4, 16), - ..BaseNode::default() - }, - expression: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(4, 4, 4, 16), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 9", + source: "doody", + }, + }, + name: "doody", + }, + init: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 12", + end: "line: 2, column: 18", + source: "from()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 12", + end: "line: 2, column: 16", + source: "from", + }, + }, + name: "from", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), }, - argument: Expression::Identifier(Identifier { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(4, 4, 4, 9), - ..BaseNode::default() + location: SourceLocation { + start: "line: 3, column: 4", + end: "line: 3, column: 18", + source: "howdy|>count()", + }, }, - name: "doody".to_string() - }), - call: CallExpr { + expression: PipeExpr( + PipeExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 4", + end: "line: 3, column: 18", + source: "howdy|>count()", + }, + }, + argument: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 4", + end: "line: 3, column: 9", + source: "howdy", + }, + }, + name: "howdy", + }, + ), + call: CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 11", + end: "line: 3, column: 18", + source: "count()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 11", + end: "line: 3, column: 16", + source: "count", + }, + }, + name: "count", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + }, + ), + }, + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(4, 11, 4, 16), - ..BaseNode::default() + location: SourceLocation { + start: "line: 4, column: 4", + end: "line: 4, column: 16", + source: "doody|>sum()", + }, }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(4, 11, 4, 14), - ..BaseNode::default() - }, - name: "sum".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - } - })) - })) - ], - eof: vec![], - }, - ) + expression: PipeExpr( + PipeExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 4", + end: "line: 4, column: 16", + source: "doody|>sum()", + }, + }, + argument: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 4", + end: "line: 4, column: 9", + source: "doody", + }, + }, + name: "doody", + }, + ), + call: CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 11", + end: "line: 4, column: 16", + source: "sum()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 11", + end: "line: 4, column: 14", + source: "sum", + }, + }, + name: "sum", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + }, + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn index_expression() { - let mut p = Parser::new(r#"a[3]"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"a[3]"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "a[3]", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() - }, - expression: Expression::Index(Box::new(IndexExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() - }, - array: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "a".to_string() - }), - lbrack: vec![], - index: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 3, 1, 4), - ..BaseNode::default() - }, - value: 3 - }), - rbrack: vec![], - })) - }))], - eof: vec![], - }, - ) + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "a[3]", + }, + }, + expression: Index( + IndexExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "a[3]", + }, + }, + array: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, + }, + name: "a", + }, + ), + lbrack: [], + index: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 3", + end: "line: 1, column: 4", + source: "3", + }, + }, + value: 3, + }, + ), + rbrack: [], + }, + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn nested_index_expression() { - let mut p = Parser::new(r#"a[3][5]"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"a[3][5]"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 8), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 8", + source: "a[3][5]", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 8), - ..BaseNode::default() - }, - expression: Expression::Index(Box::new(IndexExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 8), - ..BaseNode::default() - }, - array: Expression::Index(Box::new(IndexExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 8", + source: "a[3][5]", + }, }, - array: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() + expression: Index( + IndexExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 8", + source: "a[3][5]", + }, + }, + array: Index( + IndexExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "a[3]", + }, + }, + array: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, + }, + name: "a", + }, + ), + lbrack: [], + index: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 3", + end: "line: 1, column: 4", + source: "3", + }, + }, + value: 3, + }, + ), + rbrack: [], + }, + ), + lbrack: [], + index: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "5", + }, + }, + value: 5, + }, + ), + rbrack: [], }, - name: "a".to_string() - }), - lbrack: vec![], - index: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 3, 1, 4), - ..BaseNode::default() - }, - value: 3 - }), - rbrack: vec![], - })), - lbrack: vec![], - index: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() - }, - value: 5 - }), - rbrack: vec![], - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn access_indexed_object_returned_from_function_call() { - let mut p = Parser::new(r#"f()[3]"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"f()[3]"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "f()[3]", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() - }, - expression: Expression::Index(Box::new(IndexExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() - }, - array: Expression::Call(Box::new(CallExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "f()[3]", + }, }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "f".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })), - lbrack: vec![], - index: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 5, 1, 6), - ..BaseNode::default() - }, - value: 3 - }), - rbrack: vec![], - })) - }))], - eof: vec![], - }, - ) + expression: Index( + IndexExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "f()[3]", + }, + }, + array: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "f()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "f", + }, + }, + name: "f", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), + lbrack: [], + index: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 6", + source: "3", + }, + }, + value: 3, + }, + ), + rbrack: [], + }, + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn index_with_member_expressions() { - let mut p = Parser::new(r#"a.b["c"]"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"a.b["c"]"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 9), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 9", + source: "a.b[\"c\"]", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 9), - ..BaseNode::default() - }, - expression: Expression::Member(Box::new(MemberExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 9), - ..BaseNode::default() - }, - object: Expression::Member(Box::new(MemberExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 9", + source: "a.b[\"c\"]", + }, }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() + expression: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 9", + source: "a.b[\"c\"]", + }, + }, + object: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "a.b", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, + }, + name: "a", + }, + ), + lbrack: [], + property: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 3", + end: "line: 1, column: 4", + source: "b", + }, + }, + name: "b", + }, + ), + rbrack: [], + }, + ), + lbrack: [], + property: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 8", + source: "\"c\"", + }, + }, + value: "c", + }, + ), + rbrack: [], }, - name: "a".to_string() - }), - lbrack: vec![], - property: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 3, 1, 4), - ..BaseNode::default() - }, - name: "b".to_string() - }), - rbrack: vec![], - })), - lbrack: vec![], - property: PropertyKey::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 5, 1, 8), - ..BaseNode::default() - }, - value: "c".to_string() - }), - rbrack: vec![], - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn index_with_member_with_call_expression() { - let mut p = Parser::new(r#"a.b()["c"]"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"a.b()["c"]"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 11), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 11", + source: "a.b()[\"c\"]", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 11), - ..BaseNode::default() - }, - expression: Expression::Member(Box::new(MemberExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 11), - ..BaseNode::default() - }, - object: Expression::Call(Box::new(CallExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - callee: Expression::Member(Box::new(MemberExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 11", + source: "a.b()[\"c\"]", }, - object: Expression::Identifier(Identifier { + }, + expression: Member( + MemberExpr { base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 11", + source: "a.b()[\"c\"]", + }, }, - name: "a".to_string() - }), - lbrack: vec![], - property: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 3, 1, 4), - ..BaseNode::default() - }, - name: "b".to_string() - }), - rbrack: vec![], - })), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })), - lbrack: vec![], - property: PropertyKey::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 7, 1, 10), - ..BaseNode::default() - }, - value: "c".to_string() - }), - rbrack: vec![], - })) - }))], - eof: vec![], - }, - ) + object: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "a.b()", + }, + }, + callee: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "a.b", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, + }, + name: "a", + }, + ), + lbrack: [], + property: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 3", + end: "line: 1, column: 4", + source: "b", + }, + }, + name: "b", + }, + ), + rbrack: [], + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), + lbrack: [], + property: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 10", + source: "\"c\"", + }, + }, + value: "c", + }, + ), + rbrack: [], + }, + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn expressions_with_function_calls() { - let mut p = Parser::new(r#"a = foo() == 10"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"a = foo() == 10"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 16), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 16", + source: "a = foo() == 10", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 16), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "a".to_string() - }, - init: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 5, 1, 16), - ..BaseNode::default() - }, - operator: Operator::EqualOperator, - left: Expression::Call(Box::new(CallExpr { + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(1, 5, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 16", + source: "a = foo() == 10", + }, }, - callee: Expression::Identifier(Identifier { + id: Identifier { base: BaseNode { - location: loc.get(1, 5, 1, 8), - ..BaseNode::default() - }, - name: "foo".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })), - right: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 14, 1, 16), - ..BaseNode::default() - }, - value: 10 - }) - })) - }))], - eof: vec![], - }, - ) + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, + }, + name: "a", + }, + init: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 16", + source: "foo() == 10", + }, + }, + operator: EqualOperator, + left: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 10", + source: "foo()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 8", + source: "foo", + }, + }, + name: "foo", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 16", + source: "10", + }, + }, + value: 10, + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn conditional() { - let mut p = Parser::new(r#"a = if true then 0 else 1"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_file( + r#"a = if true then 0 else 1"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 26), - ..BaseNode::default() - }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), - package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 26), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 26", + source: "a = if true then 0 else 1", }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "a".to_string() - }, - init: Expression::Conditional(Box::new(ConditionalExpr { - base: BaseNode { - location: loc.get(1, 5, 1, 26), - ..BaseNode::default() - }, - test: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 8, 1, 12), - ..BaseNode::default() - }, - name: "true".to_string() - }), - consequent: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 18, 1, 19), - ..BaseNode::default() - }, - value: 0 - }), - alternate: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 25, 1, 26), - ..BaseNode::default() - }, - value: 1 - }), - tk_if: vec![], - tk_then: vec![], - tk_else: vec![], - })) - }))], - eof: vec![], - }, - ) -} - -#[test] -fn conditional_with_unary_logical_operators() { - let mut p = Parser::new( - r#"a = if exists b or c < d and not e == f then not exists (g - h) else exists exists i"#, - ); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - File { - base: BaseNode { - location: loc.get(1, 1, 1, 85), - ..BaseNode::default() }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 85), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "a".to_string() - }, - init: Expression::Conditional(Box::new(ConditionalExpr { - base: BaseNode { - location: loc.get(1, 5, 1, 85), - ..BaseNode::default() - }, - test: Expression::Logical(Box::new(LogicalExpr { + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(1, 8, 1, 40), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 26", + source: "a = if true then 0 else 1", + }, }, - operator: LogicalOperator::OrOperator, - left: Expression::Unary(Box::new(UnaryExpr { + id: Identifier { base: BaseNode { - location: loc.get(1, 8, 1, 16), - ..BaseNode::default() - }, - operator: Operator::ExistsOperator, - argument: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 15, 1, 16), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", }, - name: "b".to_string() - }) - })), - right: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(1, 20, 1, 40), - ..BaseNode::default() }, - operator: LogicalOperator::AndOperator, - left: Expression::Binary(Box::new(BinaryExpr { + name: "a", + }, + init: Conditional( + ConditionalExpr { base: BaseNode { - location: loc.get(1, 20, 1, 25), - ..BaseNode::default() - }, - operator: Operator::LessThanOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 20, 1, 21), - ..BaseNode::default() - }, - name: "c".to_string() - }), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 24, 1, 25), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 26", + source: "if true then 0 else 1", }, - name: "d".to_string() - }) - })), - right: Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(1, 30, 1, 40), - ..BaseNode::default() }, - operator: Operator::NotOperator, - argument: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 34, 1, 40), - ..BaseNode::default() + tk_if: [], + test: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 12", + source: "true", + }, + }, + name: "true", }, - operator: Operator::EqualOperator, - left: Expression::Identifier(Identifier { + ), + tk_then: [], + consequent: Integer( + IntegerLit { base: BaseNode { - location: loc.get(1, 34, 1, 35), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 18", + end: "line: 1, column: 19", + source: "0", + }, }, - name: "e".to_string() - }), - right: Expression::Identifier(Identifier { + value: 0, + }, + ), + tk_else: [], + alternate: Integer( + IntegerLit { base: BaseNode { - location: loc.get(1, 39, 1, 40), - ..BaseNode::default() - }, - name: "f".to_string() - }) - })) - })) - })) - })), - consequent: Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(1, 46, 1, 64), - ..BaseNode::default() - }, - operator: Operator::NotOperator, - argument: Expression::Unary(Box::new(UnaryExpr { + location: SourceLocation { + start: "line: 1, column: 25", + end: "line: 1, column: 26", + source: "1", + }, + }, + value: 1, + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]], + ); +} + +#[test] +fn conditional_with_unary_logical_operators() { + test_file( + r#"a = if exists b or c < d and not e == f then not exists (g - h) else exists exists i"#, + expect![[r#" + File { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 85", + source: "a = if exists b or c < d and not e == f then not exists (g - h) else exists exists i", + }, + }, + name: "", + metadata: "parser-type=rust", + package: None, + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(1, 50, 1, 64), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 85", + source: "a = if exists b or c < d and not e == f then not exists (g - h) else exists exists i", + }, }, - operator: Operator::ExistsOperator, - argument: Expression::Paren(Box::new(ParenExpr { + id: Identifier { base: BaseNode { - location: loc.get(1, 57, 1, 64), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, }, - lparen: vec![], - expression: Expression::Binary(Box::new(BinaryExpr { + name: "a", + }, + init: Conditional( + ConditionalExpr { base: BaseNode { - location: loc.get(1, 58, 1, 63), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 85", + source: "if exists b or c < d and not e == f then not exists (g - h) else exists exists i", + }, }, - operator: Operator::SubtractionOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 58, 1, 59), - ..BaseNode::default() + tk_if: [], + test: Logical( + LogicalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 40", + source: "exists b or c < d and not e == f", + }, + }, + operator: OrOperator, + left: Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 16", + source: "exists b", + }, + }, + operator: ExistsOperator, + argument: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 16", + source: "b", + }, + }, + name: "b", + }, + ), + }, + ), + right: Logical( + LogicalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 20", + end: "line: 1, column: 40", + source: "c < d and not e == f", + }, + }, + operator: AndOperator, + left: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 20", + end: "line: 1, column: 25", + source: "c < d", + }, + }, + operator: LessThanOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 20", + end: "line: 1, column: 21", + source: "c", + }, + }, + name: "c", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 24", + end: "line: 1, column: 25", + source: "d", + }, + }, + name: "d", + }, + ), + }, + ), + right: Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 30", + end: "line: 1, column: 40", + source: "not e == f", + }, + }, + operator: NotOperator, + argument: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 34", + end: "line: 1, column: 40", + source: "e == f", + }, + }, + operator: EqualOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 34", + end: "line: 1, column: 35", + source: "e", + }, + }, + name: "e", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 39", + end: "line: 1, column: 40", + source: "f", + }, + }, + name: "f", + }, + ), + }, + ), + }, + ), + }, + ), }, - name: "g".to_string() - }), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 62, 1, 63), - ..BaseNode::default() - }, - name: "h".to_string() - }) - })), - rparen: vec![], - })) - })) - })), - alternate: Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(1, 70, 1, 85), - ..BaseNode::default() - }, - operator: Operator::ExistsOperator, - argument: Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(1, 77, 1, 85), - ..BaseNode::default() - }, - operator: Operator::ExistsOperator, - argument: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 84, 1, 85), - ..BaseNode::default() - }, - name: "i".to_string() - }) - })) - })), - tk_if: vec![], - tk_then: vec![], - tk_else: vec![], - })) - }))], - eof: vec![], - }, - ) + ), + tk_then: [], + consequent: Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 46", + end: "line: 1, column: 64", + source: "not exists (g - h)", + }, + }, + operator: NotOperator, + argument: Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 50", + end: "line: 1, column: 64", + source: "exists (g - h)", + }, + }, + operator: ExistsOperator, + argument: Paren( + ParenExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 57", + end: "line: 1, column: 64", + source: "(g - h)", + }, + }, + lparen: [], + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 58", + end: "line: 1, column: 63", + source: "g - h", + }, + }, + operator: SubtractionOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 58", + end: "line: 1, column: 59", + source: "g", + }, + }, + name: "g", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 62", + end: "line: 1, column: 63", + source: "h", + }, + }, + name: "h", + }, + ), + }, + ), + rparen: [], + }, + ), + }, + ), + }, + ), + tk_else: [], + alternate: Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 70", + end: "line: 1, column: 85", + source: "exists exists i", + }, + }, + operator: ExistsOperator, + argument: Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 77", + end: "line: 1, column: 85", + source: "exists i", + }, + }, + operator: ExistsOperator, + argument: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 84", + end: "line: 1, column: 85", + source: "i", + }, + }, + name: "i", + }, + ), + }, + ), + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]], + ); } #[test] fn nested_conditionals() { - let mut p = Parser::new( + test_file( r#"if if b < 0 then true else false then if c > 0 then 30 else 60 else if d == 0 then 90 else 120"#, + expect![[r#" + File { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 3, column: 50", + source: "if if b < 0 then true else false\n then if c > 0 then 30 else 60\n else if d == 0 then 90 else 120", + }, + }, + name: "", + metadata: "parser-type=rust", + package: None, + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 3, column: 50", + source: "if if b < 0 then true else false\n then if c > 0 then 30 else 60\n else if d == 0 then 90 else 120", + }, + }, + expression: Conditional( + ConditionalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 3, column: 50", + source: "if if b < 0 then true else false\n then if c > 0 then 30 else 60\n else if d == 0 then 90 else 120", + }, + }, + tk_if: [], + test: Conditional( + ConditionalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 33", + source: "if b < 0 then true else false", + }, + }, + tk_if: [], + test: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 12", + source: "b < 0", + }, + }, + operator: LessThanOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 8", + source: "b", + }, + }, + name: "b", + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 12", + source: "0", + }, + }, + value: 0, + }, + ), + }, + ), + tk_then: [], + consequent: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 18", + end: "line: 1, column: 22", + source: "true", + }, + }, + name: "true", + }, + ), + tk_else: [], + alternate: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 28", + end: "line: 1, column: 33", + source: "false", + }, + }, + name: "false", + }, + ), + }, + ), + tk_then: [], + consequent: Conditional( + ConditionalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 24", + end: "line: 2, column: 48", + source: "if c > 0 then 30 else 60", + }, + }, + tk_if: [], + test: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 27", + end: "line: 2, column: 32", + source: "c > 0", + }, + }, + operator: GreaterThanOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 27", + end: "line: 2, column: 28", + source: "c", + }, + }, + name: "c", + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 31", + end: "line: 2, column: 32", + source: "0", + }, + }, + value: 0, + }, + ), + }, + ), + tk_then: [], + consequent: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 38", + end: "line: 2, column: 40", + source: "30", + }, + }, + value: 30, + }, + ), + tk_else: [], + alternate: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 46", + end: "line: 2, column: 48", + source: "60", + }, + }, + value: 60, + }, + ), + }, + ), + tk_else: [], + alternate: Conditional( + ConditionalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 24", + end: "line: 3, column: 50", + source: "if d == 0 then 90 else 120", + }, + }, + tk_if: [], + test: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 27", + end: "line: 3, column: 33", + source: "d == 0", + }, + }, + operator: EqualOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 27", + end: "line: 3, column: 28", + source: "d", + }, + }, + name: "d", + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 32", + end: "line: 3, column: 33", + source: "0", + }, + }, + value: 0, + }, + ), + }, + ), + tk_then: [], + consequent: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 39", + end: "line: 3, column: 41", + source: "90", + }, + }, + value: 90, + }, + ), + tk_else: [], + alternate: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 47", + end: "line: 3, column: 50", + source: "120", + }, + }, + value: 120, + }, + ), + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]], ); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, +} + +#[test] +fn parse_testcase() { + test_file( + r#"testcase my_test { a = 1 }"#, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 3, 50), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 27", + source: "testcase my_test { a = 1 }", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 3, 50), - ..BaseNode::default() - }, - expression: Expression::Conditional(Box::new(ConditionalExpr { - base: BaseNode { - location: loc.get(1, 1, 3, 50), - ..BaseNode::default() - }, - test: Expression::Conditional(Box::new(ConditionalExpr { + imports: [], + body: [ + TestCase( + TestCaseStmt { base: BaseNode { - location: loc.get(1, 4, 1, 33), - ..BaseNode::default() - }, - test: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 7, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 27", + source: "testcase my_test { a = 1 }", }, - operator: Operator::LessThanOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 7, 1, 8), - ..BaseNode::default() - }, - name: "b".to_string() - }), - right: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 11, 1, 12), - ..BaseNode::default() - }, - value: 0 - }) - })), - consequent: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 18, 1, 22), - ..BaseNode::default() - }, - name: "true".to_string() - }), - alternate: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 28, 1, 33), - ..BaseNode::default() - }, - name: "false".to_string() - }), - tk_if: vec![], - tk_then: vec![], - tk_else: vec![], - })), - consequent: Expression::Conditional(Box::new(ConditionalExpr { - base: BaseNode { - location: loc.get(2, 24, 2, 48), - ..BaseNode::default() }, - test: Expression::Binary(Box::new(BinaryExpr { + id: Identifier { base: BaseNode { - location: loc.get(2, 27, 2, 32), - ..BaseNode::default() - }, - operator: Operator::GreaterThanOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 27, 2, 28), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 17", + source: "my_test", }, - name: "c".to_string() - }), - right: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(2, 31, 2, 32), - ..BaseNode::default() - }, - value: 0 - }) - })), - consequent: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(2, 38, 2, 40), - ..BaseNode::default() - }, - value: 30 - }), - alternate: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(2, 46, 2, 48), - ..BaseNode::default() }, - value: 60 - }), - tk_if: vec![], - tk_then: vec![], - tk_else: vec![], - })), - alternate: Expression::Conditional(Box::new(ConditionalExpr { - base: BaseNode { - location: loc.get(3, 24, 3, 50), - ..BaseNode::default() + name: "my_test", }, - test: Expression::Binary(Box::new(BinaryExpr { + extends: None, + block: Block { base: BaseNode { - location: loc.get(3, 27, 3, 33), - ..BaseNode::default() - }, - operator: Operator::EqualOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(3, 27, 3, 28), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 18", + end: "line: 1, column: 27", + source: "{ a = 1 }", }, - name: "d".to_string() - }), - right: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(3, 32, 3, 33), - ..BaseNode::default() - }, - value: 0 - }) - })), - consequent: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(3, 39, 3, 41), - ..BaseNode::default() }, - value: 90 - }), - alternate: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(3, 47, 3, 50), - ..BaseNode::default() - }, - value: 120 - }), - tk_if: vec![], - tk_then: vec![], - tk_else: vec![], - })), - tk_if: vec![], - tk_then: vec![], - tk_else: vec![], - })) - }))], - eof: vec![], - }, - ) -} - -#[test] -fn parse_testcase() { - let mut parser = Parser::new(r#"testcase my_test { a = 1 }"#); - let parsed = parser.parse_file("".to_string()); - let loc = Locator::new(parser.source); - let expected = vec![Statement::TestCase(Box::new(TestCaseStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 27), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 10, 1, 17), - ..BaseNode::default() - }, - name: "my_test".to_string(), - }, - extends: None, - block: Block { - base: BaseNode { - location: loc.get(1, 18, 1, 27), - ..BaseNode::default() - }, - lbrace: vec![], - body: vec![Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 20, 1, 25), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 20, 1, 21), - ..BaseNode::default() - }, - name: "a".to_string(), - }, - init: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 24, 1, 25), - ..BaseNode::default() + lbrace: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 20", + end: "line: 1, column: 25", + source: "a = 1", + }, + }, + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 20", + end: "line: 1, column: 21", + source: "a", + }, + }, + name: "a", + }, + init: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 24", + end: "line: 1, column: 25", + source: "1", + }, + }, + value: 1, + }, + ), + }, + ), + ], + rbrace: [], + }, }, - value: 1, - }), - }))], - rbrace: vec![], - }, - }))]; - - assert_eq!(expected, parsed.body); + ), + ], + eof: [], + } + "#]], + ); } #[test] fn parse_testcase_extends() { - let mut parser = Parser::new(r#"testcase my_test extends "other_test" { a = 1 }"#); - let parsed = parser.parse_file("".to_string()); - let loc = Locator::new(parser.source); - let expected = vec![Statement::TestCase(Box::new(TestCaseStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 48), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 10, 1, 17), - ..BaseNode::default() - }, - name: "my_test".to_string(), - }, - extends: Some(StringLit { - base: BaseNode { - location: loc.get(1, 26, 1, 38), - ..BaseNode::default() - }, - value: "other_test".to_string(), - }), - block: Block { - base: BaseNode { - location: loc.get(1, 39, 1, 48), - ..BaseNode::default() - }, - lbrace: vec![], - body: vec![Variable(Box::new(VariableAssgn { + test_file( + r#"testcase my_test extends "other_test" { a = 1 }"#, + expect![[r#" + File { base: BaseNode { - location: loc.get(1, 41, 1, 46), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 41, 1, 42), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 48", + source: "testcase my_test extends \"other_test\" { a = 1 }", }, - name: "a".to_string(), }, - init: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 45, 1, 46), - ..BaseNode::default() - }, - value: 1, - }), - }))], - rbrace: vec![], - }, - }))]; - - assert_eq!(expected, parsed.body); + name: "", + metadata: "parser-type=rust", + package: None, + imports: [], + body: [ + TestCase( + TestCaseStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 48", + source: "testcase my_test extends \"other_test\" { a = 1 }", + }, + }, + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 17", + source: "my_test", + }, + }, + name: "my_test", + }, + extends: Some( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 26", + end: "line: 1, column: 38", + source: "\"other_test\"", + }, + }, + value: "other_test", + }, + ), + block: Block { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 39", + end: "line: 1, column: 48", + source: "{ a = 1 }", + }, + }, + lbrace: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 41", + end: "line: 1, column: 46", + source: "a = 1", + }, + }, + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 41", + end: "line: 1, column: 42", + source: "a", + }, + }, + name: "a", + }, + init: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 45", + end: "line: 1, column: 46", + source: "1", + }, + }, + value: 1, + }, + ), + }, + ), + ], + rbrace: [], + }, + }, + ), + ], + eof: [], + } + "#]], + ); } diff --git a/libflux/flux-core/src/parser/tests/arrow_function.rs b/libflux/flux-core/src/parser/tests/arrow_function.rs index 71cac01927..56f44e2c2a 100644 --- a/libflux/flux-core/src/parser/tests/arrow_function.rs +++ b/libflux/flux-core/src/parser/tests/arrow_function.rs @@ -1,7 +1,4 @@ -use pretty_assertions::assert_eq; - use super::*; -use crate::ast::tests::Locator; #[test] fn arrow_function_called() { @@ -10,427 +7,666 @@ fn arrow_function_called() { plusOne(r:5)"#, ); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 2, 16), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 2, column: 16", + source: "plusOne = (r) => r + 1\n plusOne(r:5)", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![ - Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 23), - ..BaseNode::default() - }, - id: Identifier { + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(1, 1, 1, 8), - ..BaseNode::default() - }, - name: "plusOne".to_string() - }, - init: Expression::Function(Box::new(FunctionExpr { - base: BaseNode { - location: loc.get(1, 11, 1, 23), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 23", + source: "plusOne = (r) => r + 1", + }, }, - lparen: vec![], - params: vec![Property { + id: Identifier { base: BaseNode { - location: loc.get(1, 12, 1, 13), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 12, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 8", + source: "plusOne", }, - name: "r".to_string() - }), - separator: vec![], - value: None, - comma: vec![], - }], - rparen: vec![], - arrow: vec![], - body: FunctionBody::Expr(Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 18, 1, 23), - ..BaseNode::default() }, - operator: Operator::AdditionOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 18, 1, 19), - ..BaseNode::default() - }, - name: "r".to_string() - }), - right: Expression::Integer(IntegerLit { + name: "plusOne", + }, + init: Function( + FunctionExpr { base: BaseNode { - location: loc.get(1, 22, 1, 23), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 23", + source: "(r) => r + 1", + }, }, - value: 1 - }) - }))), - })) - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(2, 4, 2, 16), - ..BaseNode::default() + lparen: [], + params: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 13", + source: "r", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 13", + source: "r", + }, + }, + name: "r", + }, + ), + separator: [], + value: None, + comma: [], + }, + ], + rparen: [], + arrow: [], + body: Expr( + Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 18", + end: "line: 1, column: 23", + source: "r + 1", + }, + }, + operator: AdditionOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 18", + end: "line: 1, column: 19", + source: "r", + }, + }, + name: "r", + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 22", + end: "line: 1, column: 23", + source: "1", + }, + }, + value: 1, + }, + ), + }, + ), + ), + }, + ), }, - expression: Expression::Call(Box::new(CallExpr { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(2, 4, 2, 16), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 4, 2, 11), - ..BaseNode::default() - }, - name: "plusOne".to_string() - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(2, 12, 2, 15), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 16", + source: "plusOne(r:5)", }, - lbrace: vec![], - with: None, - properties: vec![Property { + }, + expression: Call( + CallExpr { base: BaseNode { - location: loc.get(2, 12, 2, 15), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 12, 2, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 16", + source: "plusOne(r:5)", }, - name: "r".to_string() - }), - separator: vec![], - value: Some(Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(2, 14, 2, 15), - ..BaseNode::default() + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 11", + source: "plusOne", + }, + }, + name: "plusOne", }, - value: 5 - })), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - })) - })) + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 12", + end: "line: 2, column: 15", + source: "r:5", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 12", + end: "line: 2, column: 15", + source: "r:5", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 12", + end: "line: 2, column: 13", + source: "r", + }, + }, + name: "r", + }, + ), + separator: [], + value: Some( + Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 14", + end: "line: 2, column: 15", + source: "5", + }, + }, + value: 5, + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], + }, + ), + }, + ), ], - eof: vec![], - }, - ) + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] fn arrow_function_return_map() { let mut p = Parser::new(r#"toMap = (r) =>({r:r})"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 22), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 22", + source: "toMap = (r) =>({r:r})", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 22), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - name: "toMap".to_string() - }, - init: Expression::Function(Box::new(FunctionExpr { - base: BaseNode { - location: loc.get(1, 9, 1, 22), - ..BaseNode::default() - }, - lparen: vec![], - params: vec![Property { + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(1, 10, 1, 11), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 10, 1, 11), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 22", + source: "toMap = (r) =>({r:r})", }, - name: "r".to_string() - }), - separator: vec![], - value: None, - comma: vec![], - }], - rparen: vec![], - arrow: vec![], - body: FunctionBody::Expr(Expression::Paren(Box::new(ParenExpr { - base: BaseNode { - location: loc.get(1, 15, 1, 22), - ..BaseNode::default() }, - lparen: vec![], - expression: Expression::Object(Box::new(ObjectExpr { + id: Identifier { base: BaseNode { - location: loc.get(1, 16, 1, 21), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "toMap", + }, }, - lbrace: vec![], - with: None, - properties: vec![Property { + name: "toMap", + }, + init: Function( + FunctionExpr { base: BaseNode { - location: loc.get(1, 17, 1, 20), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 17, 1, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 22", + source: "(r) =>({r:r})", }, - name: "r".to_string() - }), - separator: vec![], - value: Some(Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 19, 1, 20), - ..BaseNode::default() + }, + lparen: [], + params: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 11", + source: "r", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 11", + source: "r", + }, + }, + name: "r", + }, + ), + separator: [], + value: None, + comma: [], }, - name: "r".to_string() - })), - comma: vec![], - }], - rbrace: vec![], - })), - rparen: vec![], - }))), - })) - }))], - eof: vec![], - }, - ) + ], + rparen: [], + arrow: [], + body: Expr( + Paren( + ParenExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 22", + source: "({r:r})", + }, + }, + lparen: [], + expression: Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 16", + end: "line: 1, column: 21", + source: "{r:r}", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 17", + end: "line: 1, column: 20", + source: "r:r", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 17", + end: "line: 1, column: 18", + source: "r", + }, + }, + name: "r", + }, + ), + separator: [], + value: Some( + Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 19", + end: "line: 1, column: 20", + source: "r", + }, + }, + name: "r", + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + rparen: [], + }, + ), + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] fn arrow_function() { let mut p = Parser::new(r#"(x,y) => x == y"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 16), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 16", + source: "(x,y) => x == y", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 16), - ..BaseNode::default() - }, - expression: Expression::Function(Box::new(FunctionExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 16), - ..BaseNode::default() - }, - lparen: vec![], - params: vec![ - Property { - base: BaseNode { - location: loc.get(1, 2, 1, 3), - ..BaseNode::default() + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 16", + source: "(x,y) => x == y", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 2, 1, 3), - ..BaseNode::default() - }, - name: "x".to_string() - }), - separator: vec![], - value: None, - comma: vec![], }, - Property { - base: BaseNode { - location: loc.get(1, 4, 1, 5), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { + expression: Function( + FunctionExpr { base: BaseNode { - location: loc.get(1, 4, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 16", + source: "(x,y) => x == y", + }, }, - name: "y".to_string() - }), - separator: vec![], - value: None, - comma: vec![], - } - ], - rparen: vec![], - arrow: vec![], - body: FunctionBody::Expr(Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 10, 1, 16), - ..BaseNode::default() - }, - operator: Operator::EqualOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 10, 1, 11), - ..BaseNode::default() - }, - name: "x".to_string(), - }), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 15, 1, 16), - ..BaseNode::default() + lparen: [], + params: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 3", + source: "x", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 3", + source: "x", + }, + }, + name: "x", + }, + ), + separator: [], + value: None, + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 5", + source: "y", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 5", + source: "y", + }, + }, + name: "y", + }, + ), + separator: [], + value: None, + comma: [], + }, + ], + rparen: [], + arrow: [], + body: Expr( + Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 16", + source: "x == y", + }, + }, + operator: EqualOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 11", + source: "x", + }, + }, + name: "x", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 16", + source: "y", + }, + }, + name: "y", + }, + ), + }, + ), + ), }, - name: "y".to_string(), - }), - }))), - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn arrow_function_with_default_arg() { let mut p = Parser::new(r#"addN = (r, n=5) => r + n"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 25), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 25", + source: "addN = (r, n=5) => r + n", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 25), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() - }, - name: "addN".to_string() - }, - init: Expression::Function(Box::new(FunctionExpr { - base: BaseNode { - location: loc.get(1, 8, 1, 25), - ..BaseNode::default() - }, - lparen: vec![], - params: vec![ - Property { - base: BaseNode { - location: loc.get(1, 9, 1, 10), - ..BaseNode::default() + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 25", + source: "addN = (r, n=5) => r + n", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 9, 1, 10), - ..BaseNode::default() - }, - name: "r".to_string() - }), - separator: vec![], - value: None, - comma: vec![], }, - Property { + id: Identifier { base: BaseNode { - location: loc.get(1, 12, 1, 15), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 12, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "addN", }, - name: "n".to_string() - }), - separator: vec![], - value: Some(Expression::Integer(IntegerLit { + }, + name: "addN", + }, + init: Function( + FunctionExpr { base: BaseNode { - location: loc.get(1, 14, 1, 15), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 25", + source: "(r, n=5) => r + n", + }, }, - value: 5 - })), - comma: vec![], - } - ], - rparen: vec![], - arrow: vec![], - body: FunctionBody::Expr(Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 20, 1, 25), - ..BaseNode::default() - }, - operator: Operator::AdditionOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 20, 1, 21), - ..BaseNode::default() - }, - name: "r".to_string() - }), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 24, 1, 25), - ..BaseNode::default() + lparen: [], + params: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 10", + source: "r", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 10", + source: "r", + }, + }, + name: "r", + }, + ), + separator: [], + value: None, + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 15", + source: "n=5", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 13", + source: "n", + }, + }, + name: "n", + }, + ), + separator: [], + value: Some( + Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 15", + source: "5", + }, + }, + value: 5, + }, + ), + ), + comma: [], + }, + ], + rparen: [], + arrow: [], + body: Expr( + Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 20", + end: "line: 1, column: 25", + source: "r + n", + }, + }, + operator: AdditionOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 20", + end: "line: 1, column: 21", + source: "r", + }, + }, + name: "r", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 24", + end: "line: 1, column: 25", + source: "n", + }, + }, + name: "n", + }, + ), + }, + ), + ), }, - name: "n".to_string() - }) - }))), - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] @@ -441,266 +677,425 @@ fn arrow_function_called_in_binary_expression() { plusOne(r:5) == 6 or die()"#, ); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(2, 13, 3, 39), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 3, column: 39", + source: "plusOne = (r) => r + 1\n plusOne(r:5) == 6 or die()", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![ - Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(2, 13, 2, 35), - ..BaseNode::default() - }, - id: Identifier { + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(2, 13, 2, 20), - ..BaseNode::default() - }, - name: "plusOne".to_string() - }, - init: Expression::Function(Box::new(FunctionExpr { - base: BaseNode { - location: loc.get(2, 23, 2, 35), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 35", + source: "plusOne = (r) => r + 1", + }, }, - lparen: vec![], - params: vec![Property { + id: Identifier { base: BaseNode { - location: loc.get(2, 24, 2, 25), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 24, 2, 25), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 20", + source: "plusOne", }, - name: "r".to_string() - }), - separator: vec![], - value: None, - comma: vec![], - }], - rparen: vec![], - arrow: vec![], - body: FunctionBody::Expr(Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(2, 30, 2, 35), - ..BaseNode::default() }, - operator: Operator::AdditionOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 30, 2, 31), - ..BaseNode::default() - }, - name: "r".to_string() - }), - right: Expression::Integer(IntegerLit { + name: "plusOne", + }, + init: Function( + FunctionExpr { base: BaseNode { - location: loc.get(2, 34, 2, 35), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 23", + end: "line: 2, column: 35", + source: "(r) => r + 1", + }, }, - value: 1 - }) - }))), - })) - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(3, 13, 3, 39), - ..BaseNode::default() + lparen: [], + params: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 24", + end: "line: 2, column: 25", + source: "r", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 24", + end: "line: 2, column: 25", + source: "r", + }, + }, + name: "r", + }, + ), + separator: [], + value: None, + comma: [], + }, + ], + rparen: [], + arrow: [], + body: Expr( + Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 30", + end: "line: 2, column: 35", + source: "r + 1", + }, + }, + operator: AdditionOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 30", + end: "line: 2, column: 31", + source: "r", + }, + }, + name: "r", + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 34", + end: "line: 2, column: 35", + source: "1", + }, + }, + value: 1, + }, + ), + }, + ), + ), + }, + ), }, - expression: Expression::Logical(Box::new(LogicalExpr { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(3, 13, 3, 39), - ..BaseNode::default() - }, - operator: LogicalOperator::OrOperator, - left: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(3, 13, 3, 30), - ..BaseNode::default() + location: SourceLocation { + start: "line: 3, column: 13", + end: "line: 3, column: 39", + source: "plusOne(r:5) == 6 or die()", }, - operator: Operator::EqualOperator, - left: Expression::Call(Box::new(CallExpr { + }, + expression: Logical( + LogicalExpr { base: BaseNode { - location: loc.get(3, 13, 3, 25), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(3, 13, 3, 20), - ..BaseNode::default() + location: SourceLocation { + start: "line: 3, column: 13", + end: "line: 3, column: 39", + source: "plusOne(r:5) == 6 or die()", }, - name: "plusOne".to_string() - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(3, 21, 3, 24), - ..BaseNode::default() + }, + operator: OrOperator, + left: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 13", + end: "line: 3, column: 30", + source: "plusOne(r:5) == 6", + }, + }, + operator: EqualOperator, + left: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 13", + end: "line: 3, column: 25", + source: "plusOne(r:5)", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 13", + end: "line: 3, column: 20", + source: "plusOne", + }, + }, + name: "plusOne", + }, + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 21", + end: "line: 3, column: 24", + source: "r:5", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 21", + end: "line: 3, column: 24", + source: "r:5", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 21", + end: "line: 3, column: 22", + source: "r", + }, + }, + name: "r", + }, + ), + separator: [], + value: Some( + Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 23", + end: "line: 3, column: 24", + source: "5", + }, + }, + value: 5, + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 29", + end: "line: 3, column: 30", + source: "6", + }, + }, + value: 6, + }, + ), }, - lbrace: vec![], - with: None, - properties: vec![Property { + ), + right: Call( + CallExpr { base: BaseNode { - location: loc.get(3, 21, 3, 24), - ..BaseNode::default() + location: SourceLocation { + start: "line: 3, column: 34", + end: "line: 3, column: 39", + source: "die()", + }, }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(3, 21, 3, 22), - ..BaseNode::default() + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 34", + end: "line: 3, column: 37", + source: "die", + }, + }, + name: "die", }, - name: "r".to_string() - }), - separator: vec![], - value: Some(Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(3, 23, 3, 24), - ..BaseNode::default() - }, - value: 5 - })), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - })), - right: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(3, 29, 3, 30), - ..BaseNode::default() - }, - value: 6 - }) - })), - right: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(3, 34, 3, 39), - ..BaseNode::default() + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(3, 34, 3, 37), - ..BaseNode::default() - }, - name: "die".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })) - })) - })) + ), + }, + ), ], - eof: vec![], - }, - ) + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] fn arrow_function_as_single_expression() { let mut p = Parser::new(r#"f = (r) => r["_measurement"] == "cpu""#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 38), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 38", + source: "f = (r) => r[\"_measurement\"] == \"cpu\"", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 38), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "f".to_string() - }, - init: Expression::Function(Box::new(FunctionExpr { - base: BaseNode { - location: loc.get(1, 5, 1, 38), - ..BaseNode::default() - }, - lparen: vec![], - params: vec![Property { + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 38", + source: "f = (r) => r[\"_measurement\"] == \"cpu\"", }, - name: "r".to_string() - }), - separator: vec![], - value: None, - comma: vec![], - }], - rparen: vec![], - arrow: vec![], - body: FunctionBody::Expr(Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 12, 1, 38), - ..BaseNode::default() }, - operator: Operator::EqualOperator, - left: Expression::Member(Box::new(MemberExpr { + id: Identifier { base: BaseNode { - location: loc.get(1, 12, 1, 29), - ..BaseNode::default() - }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 12, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "f", }, - name: "r".to_string() - }), - lbrack: vec![], - property: PropertyKey::StringLit(StringLit { + }, + name: "f", + }, + init: Function( + FunctionExpr { base: BaseNode { - location: loc.get(1, 14, 1, 28), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 38", + source: "(r) => r[\"_measurement\"] == \"cpu\"", + }, }, - value: "_measurement".to_string() - }), - rbrack: vec![], - })), - right: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 33, 1, 38), - ..BaseNode::default() + lparen: [], + params: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "r", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "r", + }, + }, + name: "r", + }, + ), + separator: [], + value: None, + comma: [], + }, + ], + rparen: [], + arrow: [], + body: Expr( + Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 38", + source: "r[\"_measurement\"] == \"cpu\"", + }, + }, + operator: EqualOperator, + left: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 29", + source: "r[\"_measurement\"]", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 13", + source: "r", + }, + }, + name: "r", + }, + ), + lbrack: [], + property: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 28", + source: "\"_measurement\"", + }, + }, + value: "_measurement", + }, + ), + rbrack: [], + }, + ), + right: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 33", + end: "line: 1, column: 38", + source: "\"cpu\"", + }, + }, + value: "cpu", + }, + ), + }, + ), + ), }, - value: "cpu".to_string() - }) - }))), - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] @@ -712,129 +1107,203 @@ fn arrow_function_as_block() { }"#, ); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 4, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 4, column: 14", + source: "f = (r) => {\n m = r[\"_measurement\"]\n return m == \"cpu\"\n }", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 4, 14), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "f".to_string() - }, - init: Expression::Function(Box::new(FunctionExpr { - base: BaseNode { - location: loc.get(1, 5, 4, 14), - ..BaseNode::default() - }, - lparen: vec![], - params: vec![Property { + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 4, column: 14", + source: "f = (r) => {\n m = r[\"_measurement\"]\n return m == \"cpu\"\n }", + }, }, - key: PropertyKey::Identifier(Identifier { + id: Identifier { base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "f", + }, }, - name: "r".to_string() - }), - separator: vec![], - value: None, - comma: vec![], - }], - rparen: vec![], - arrow: vec![], - body: FunctionBody::Block(Block { - base: BaseNode { - location: loc.get(1, 12, 4, 14), - ..BaseNode::default() + name: "f", }, - lbrace: vec![], - body: vec![ - Statement::Variable(Box::new(VariableAssgn { + init: Function( + FunctionExpr { base: BaseNode { - location: loc.get(2, 17, 2, 38), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(2, 17, 2, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 4, column: 14", + source: "(r) => {\n m = r[\"_measurement\"]\n return m == \"cpu\"\n }", }, - name: "m".to_string() }, - init: Expression::Member(Box::new(MemberExpr { - base: BaseNode { - location: loc.get(2, 21, 2, 38), - ..BaseNode::default() - }, - object: Expression::Identifier(Identifier { + lparen: [], + params: [ + Property { base: BaseNode { - location: loc.get(2, 21, 2, 22), - ..BaseNode::default() - }, - name: "r".to_string() - }), - lbrack: vec![], - property: PropertyKey::StringLit(StringLit { - base: BaseNode { - location: loc.get(2, 23, 2, 37), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "r", + }, }, - value: "_measurement".to_string() - }), - rbrack: vec![], - })) - })), - Statement::Return(Box::new(ReturnStmt { - base: BaseNode { - location: loc.get(3, 17, 3, 34), - ..BaseNode::default() - }, - argument: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(3, 24, 3, 34), - ..BaseNode::default() + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "r", + }, + }, + name: "r", + }, + ), + separator: [], + value: None, + comma: [], }, - operator: Operator::EqualOperator, - left: Expression::Identifier(Identifier { + ], + rparen: [], + arrow: [], + body: Block( + Block { base: BaseNode { - location: loc.get(3, 24, 3, 25), - ..BaseNode::default() - }, - name: "m".to_string() - }), - right: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(3, 29, 3, 34), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 4, column: 14", + source: "{\n m = r[\"_measurement\"]\n return m == \"cpu\"\n }", + }, }, - value: "cpu".to_string() - }) - })) - })) - ], - rbrace: vec![], - }), - })) - }))], - eof: vec![], - }, - ) + lbrace: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 17", + end: "line: 2, column: 38", + source: "m = r[\"_measurement\"]", + }, + }, + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 17", + end: "line: 2, column: 18", + source: "m", + }, + }, + name: "m", + }, + init: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 21", + end: "line: 2, column: 38", + source: "r[\"_measurement\"]", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 21", + end: "line: 2, column: 22", + source: "r", + }, + }, + name: "r", + }, + ), + lbrack: [], + property: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 23", + end: "line: 2, column: 37", + source: "\"_measurement\"", + }, + }, + value: "_measurement", + }, + ), + rbrack: [], + }, + ), + }, + ), + Return( + ReturnStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 17", + end: "line: 3, column: 34", + source: "return m == \"cpu\"", + }, + }, + argument: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 24", + end: "line: 3, column: 34", + source: "m == \"cpu\"", + }, + }, + operator: EqualOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 24", + end: "line: 3, column: 25", + source: "m", + }, + }, + name: "m", + }, + ), + right: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 29", + end: "line: 3, column: 34", + source: "\"cpu\"", + }, + }, + value: "cpu", + }, + ), + }, + ), + }, + ), + ], + rbrace: [], + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } diff --git a/libflux/flux-core/src/parser/tests/errors.rs b/libflux/flux-core/src/parser/tests/errors.rs index 5a0cc034ca..ae468d0e30 100644 --- a/libflux/flux-core/src/parser/tests/errors.rs +++ b/libflux/flux-core/src/parser/tests/errors.rs @@ -1,178 +1,284 @@ use pretty_assertions::assert_eq; use super::*; -use crate::ast::tests::Locator; #[test] fn function_call_with_unbalanced_braces() { let mut p = Parser::new(r#"from() |> range() |> map(fn: (r) => { return r._value )"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 56), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 56", + source: "from() |> range() |> map(fn: (r) => { return r._value )", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 56), - ..BaseNode::default() - }, - expression: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 56), - ..BaseNode::default() - }, - argument: Expression::PipeExpr(Box::new(PipeExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 18), - ..BaseNode::default() - }, - argument: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() - }, - name: "from".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })), - call: CallExpr { - base: BaseNode { - location: loc.get(1, 11, 1, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 56", + source: "from() |> range() |> map(fn: (r) => { return r._value )", }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 11, 1, 16), - ..BaseNode::default() - }, - name: "range".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - } - })), - call: CallExpr { - base: BaseNode { - location: loc.get(1, 22, 1, 56), - ..BaseNode::default() }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 22, 1, 25), - ..BaseNode::default() - }, - name: "map".to_string() - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 26, 1, 56), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![Property { + expression: PipeExpr( + PipeExpr { base: BaseNode { - location: loc.get(1, 26, 1, 56), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 26, 1, 28), - ..BaseNode::default() - }, - name: "fn".to_string() - }), - separator: vec![], - value: Some(Expression::Function(Box::new(FunctionExpr { - base: BaseNode { - location: loc.get(1, 30, 1, 56), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 56", + source: "from() |> range() |> map(fn: (r) => { return r._value )", }, - lparen: vec![], - params: vec![Property { + }, + argument: PipeExpr( + PipeExpr { base: BaseNode { - location: loc.get(1, 31, 1, 32), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "from() |> range()", + }, }, - key: PropertyKey::Identifier(Identifier { + argument: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "from()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "from", + }, + }, + name: "from", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), + call: CallExpr { base: BaseNode { - location: loc.get(1, 31, 1, 32), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 18", + source: "range()", + }, }, - name: "r".to_string() - }), - separator: vec![], - value: None, - comma: vec![], - }], - rparen: vec![], - arrow: vec![], - body: FunctionBody::Block(Block { - base: BaseNode { - location: loc.get(1, 37, 1, 56), - errors: vec!["expected RBRACE, got RPAREN".to_string()], - ..BaseNode::default() + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 16", + source: "range", + }, + }, + name: "range", + }, + ), + lparen: [], + arguments: [], + rparen: [], }, - lbrace: vec![], - body: vec![Statement::Return(Box::new(ReturnStmt { + }, + ), + call: CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 22", + end: "line: 1, column: 56", + source: "map(fn: (r) => { return r._value )", + }, + }, + callee: Identifier( + Identifier { base: BaseNode { - location: loc.get(1, 39, 1, 54), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 22", + end: "line: 1, column: 25", + source: "map", + }, }, - argument: Expression::Member(Box::new(MemberExpr { + name: "map", + }, + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { base: BaseNode { - location: loc.get(1, 46, 1, 54), - ..BaseNode::default() - }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 46, 1, 47), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 26", + end: "line: 1, column: 56", + source: "fn: (r) => { return r._value )", }, - name: "r".to_string() - }), - lbrack: vec![], - property: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 48, 1, 54), - ..BaseNode::default() + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 26", + end: "line: 1, column: 56", + source: "fn: (r) => { return r._value )", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 26", + end: "line: 1, column: 28", + source: "fn", + }, + }, + name: "fn", + }, + ), + separator: [], + value: Some( + Function( + FunctionExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 30", + end: "line: 1, column: 56", + source: "(r) => { return r._value )", + }, + }, + lparen: [], + params: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 31", + end: "line: 1, column: 32", + source: "r", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 31", + end: "line: 1, column: 32", + source: "r", + }, + }, + name: "r", + }, + ), + separator: [], + value: None, + comma: [], + }, + ], + rparen: [], + arrow: [], + body: Block( + Block { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 37", + end: "line: 1, column: 56", + source: "{ return r._value )", + }, + errors: [ + "expected RBRACE, got RPAREN", + ], + }, + lbrace: [], + body: [ + Return( + ReturnStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 39", + end: "line: 1, column: 54", + source: "return r._value", + }, + }, + argument: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 46", + end: "line: 1, column: 54", + source: "r._value", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 46", + end: "line: 1, column: 47", + source: "r", + }, + }, + name: "r", + }, + ), + lbrack: [], + property: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 48", + end: "line: 1, column: 54", + source: "_value", + }, + }, + name: "_value", + }, + ), + rbrack: [], + }, + ), + }, + ), + ], + rbrace: [], + }, + ), + }, + ), + ), + comma: [], }, - name: "_value".to_string() - }), - rbrack: vec![], - })) - }))], - rbrace: vec![], - }), - }))), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - } - })) - }))], - eof: vec![], - }, - ) + ], + rbrace: [], + }, + ), + ], + rparen: [], + }, + }, + ), + }, + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } // TODO(affo): that error is injected by ast.Check(). @@ -180,44 +286,60 @@ fn function_call_with_unbalanced_braces() { fn illegal_statement_token() { let mut p = Parser::new(r#"@ ident"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 8), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 8", + source: "@ ident", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![ - Statement::Bad(Box::new(BadStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - // errors: vec!["invalid statement @1:1-1:2: @".to_string()] - ..BaseNode::default() - }, - text: "@".to_string() - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 3, 1, 8), - ..BaseNode::default() + imports: [], + body: [ + Bad( + BadStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "@", + }, + }, + text: "@", }, - expression: Expression::Identifier(Identifier { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 3, 1, 8), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 3", + end: "line: 1, column: 8", + source: "ident", + }, }, - name: "ident".to_string() - }) - })) + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 3", + end: "line: 1, column: 8", + source: "ident", + }, + }, + name: "ident", + }, + ), + }, + ), ], - eof: vec![], - }, - ) + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } // TODO(affo): that error is injected by ast.Check(). @@ -225,57 +347,85 @@ fn illegal_statement_token() { fn multiple_idents_in_parens() { let mut p = Parser::new(r#"(a b)"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "(a b)", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - expression: Expression::Paren(Box::new(ParenExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - lparen: vec![], - expression: Expression::Binary(Box::new(BinaryExpr { - // TODO(affo): ast.Check would add the error "expected an operator between two expressions". + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 2, 1, 5), - ..BaseNode::default() - }, - operator: Operator::InvalidOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 2, 1, 3), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "(a b)", }, - name: "a".to_string() - }), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 4, 1, 5), - ..BaseNode::default() + }, + expression: Paren( + ParenExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "(a b)", + }, + }, + lparen: [], + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 5", + source: "a b", + }, + }, + operator: InvalidOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 3", + source: "a", + }, + }, + name: "a", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 5", + source: "b", + }, + }, + name: "b", + }, + ), + }, + ), + rparen: [], }, - name: "b".to_string() - }) - })), - rparen: vec![], - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } // TODO(affo): that error is injected by ast.Check(). @@ -284,59 +434,86 @@ fn multiple_idents_in_parens() { fn missing_left_hand_side() { let mut p = Parser::new(r#"(*b)"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "(*b)", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() - }, - expression: Expression::Paren(Box::new(ParenExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() - }, - lparen: vec![], - expression: Expression::Binary(Box::new(BinaryExpr { - // TODO(affo): this should be like this: - // base: BaseNode {location: ..., errors: vec!["missing left hand side of expression".to_string()] }, + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 2, 1, 4), - ..BaseNode::default() - }, - operator: Operator::MultiplicationOperator, - left: Expression::Bad(Box::new(BadExpr { - base: BaseNode { - location: loc.get(1, 2, 1, 3), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "(*b)", }, - text: "invalid token for primary expression: MUL".to_string(), - expression: None - })), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 3, 1, 4), - ..BaseNode::default() + }, + expression: Paren( + ParenExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "(*b)", + }, + }, + lparen: [], + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 4", + source: "*b", + }, + }, + operator: MultiplicationOperator, + left: Bad( + BadExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 3", + source: "*", + }, + }, + text: "invalid token for primary expression: MUL", + expression: None, + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 3", + end: "line: 1, column: 4", + source: "b", + }, + }, + name: "b", + }, + ), + }, + ), + rparen: [], }, - name: "b".to_string() - }) - })), - rparen: vec![], - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } // TODO(affo): that error is injected by ast.Check(). @@ -345,103 +522,150 @@ fn missing_left_hand_side() { fn missing_right_hand_side() { let mut p = Parser::new(r#"(a*)"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "(a*)", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() - }, - expression: Expression::Paren(Box::new(ParenExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() - }, - lparen: vec![], - expression: Expression::Binary(Box::new(BinaryExpr { - // TODO(affo): this should be like this: - // base: BaseNode {location: ..., errors: vec!["missing right hand side of expression".to_string()] }, + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 2, 1, 5), - ..BaseNode::default() - }, - operator: Operator::MultiplicationOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 2, 1, 3), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "(a*)", }, - name: "a".to_string() - }), - right: Expression::Bad(Box::new(BadExpr { - base: BaseNode { - location: loc.get(1, 4, 1, 5), - ..BaseNode::default() + }, + expression: Paren( + ParenExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "(a*)", + }, + }, + lparen: [], + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 5", + source: "a*)", + }, + }, + operator: MultiplicationOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 3", + source: "a", + }, + }, + name: "a", + }, + ), + right: Bad( + BadExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 5", + source: ")", + }, + }, + text: "invalid token for primary expression: RPAREN", + expression: None, + }, + ), + }, + ), + rparen: [], }, - text: "invalid token for primary expression: RPAREN".to_string(), - expression: None - })), - })), - rparen: vec![], - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] fn illegal_expression() { let mut p = Parser::new(r#"(@)"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "(@)", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() - }, - expression: Expression::Paren(Box::new(ParenExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 4), - errors: vec!["invalid expression @1:2-1:3: @".to_string()], - ..BaseNode::default() - }, - lparen: vec![], - expression: Expression::Bad(Box::new(BadExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 2, 1, 3), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "(@)", + }, }, - text: "@".to_string(), - expression: None - })), - rparen: vec![], - })) - }))], - eof: vec![], - }, - ) + expression: Paren( + ParenExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "(@)", + }, + errors: [ + "invalid expression @1:2-1:3: @", + ], + }, + lparen: [], + expression: Bad( + BadExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 3", + source: "@", + }, + }, + text: "@", + expression: None, + }, + ), + rparen: [], + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } // NOTE(affo): this is slightly different from Go. We have a BadExpr in the body. @@ -453,21 +677,10 @@ fn missing_arrow_in_function_expression() { File { base: BaseNode { location: SourceLocation { - file: None, - start: Position { - line: 1, - column: 1, - }, - end: Position { - line: 1, - column: 13, - }, - source: Some( - "(a, b) a + b", - ), + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "(a, b) a + b", }, - comments: [], - errors: [], }, name: "", metadata: "parser-type=rust", @@ -478,82 +691,38 @@ fn missing_arrow_in_function_expression() { ExprStmt { base: BaseNode { location: SourceLocation { - file: None, - start: Position { - line: 1, - column: 1, - }, - end: Position { - line: 1, - column: 13, - }, - source: Some( - "(a, b) a + b", - ), + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "(a, b) a + b", }, - comments: [], - errors: [], }, expression: Function( FunctionExpr { base: BaseNode { location: SourceLocation { - file: None, - start: Position { - line: 1, - column: 1, - }, - end: Position { - line: 1, - column: 13, - }, - source: Some( - "(a, b) a + b", - ), + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "(a, b) a + b", }, - comments: [], - errors: [], }, lparen: [], params: [ Property { base: BaseNode { location: SourceLocation { - file: None, - start: Position { - line: 1, - column: 2, - }, - end: Position { - line: 1, - column: 3, - }, - source: Some( - "a", - ), + start: "line: 1, column: 2", + end: "line: 1, column: 3", + source: "a", }, - comments: [], - errors: [], }, key: Identifier( Identifier { base: BaseNode { location: SourceLocation { - file: None, - start: Position { - line: 1, - column: 2, - }, - end: Position { - line: 1, - column: 3, - }, - source: Some( - "a", - ), + start: "line: 1, column: 2", + end: "line: 1, column: 3", + source: "a", }, - comments: [], - errors: [], }, name: "a", }, @@ -565,41 +734,19 @@ fn missing_arrow_in_function_expression() { Property { base: BaseNode { location: SourceLocation { - file: None, - start: Position { - line: 1, - column: 5, - }, - end: Position { - line: 1, - column: 6, - }, - source: Some( - "b", - ), + start: "line: 1, column: 5", + end: "line: 1, column: 6", + source: "b", }, - comments: [], - errors: [], }, key: Identifier( Identifier { base: BaseNode { location: SourceLocation { - file: None, - start: Position { - line: 1, - column: 5, - }, - end: Position { - line: 1, - column: 6, - }, - source: Some( - "b", - ), + start: "line: 1, column: 5", + end: "line: 1, column: 6", + source: "b", }, - comments: [], - errors: [], }, name: "b", }, @@ -616,41 +763,20 @@ fn missing_arrow_in_function_expression() { BinaryExpr { base: BaseNode { location: SourceLocation { - file: None, - start: Position { - line: 1, - column: 8, - }, - end: Position { - line: 1, - column: 13, - }, - source: Some( - "a + b", - ), + start: "line: 1, column: 8", + end: "line: 1, column: 13", + source: "a + b", }, - comments: [], - errors: [], }, operator: AdditionOperator, left: Identifier( Identifier { base: BaseNode { location: SourceLocation { - file: None, - start: Position { - line: 1, - column: 8, - }, - end: Position { - line: 1, - column: 9, - }, - source: Some( - "a", - ), + start: "line: 1, column: 8", + end: "line: 1, column: 9", + source: "a", }, - comments: [], errors: [ "expected ARROW, got IDENT (a) at 1:8", ], @@ -662,21 +788,10 @@ fn missing_arrow_in_function_expression() { Identifier { base: BaseNode { location: SourceLocation { - file: None, - start: Position { - line: 1, - column: 12, - }, - end: Position { - line: 1, - column: 13, - }, - source: Some( - "b", - ), + start: "line: 1, column: 12", + end: "line: 1, column: 13", + source: "b", }, - comments: [], - errors: [], }, name: "b", }, @@ -699,206 +814,306 @@ fn missing_arrow_in_function_expression() { fn index_with_unclosed_bracket() { let mut p = Parser::new(r#"a[b()"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "a[b()", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - expression: Expression::Index(Box::new(IndexExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - errors: vec!["expected RBRACK, got EOF".to_string()], - ..BaseNode::default() - }, - array: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "a".to_string() - }), - lbrack: vec![], - index: Expression::Call(Box::new(CallExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 3, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "a[b()", + }, }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 3, 1, 4), - ..BaseNode::default() + expression: Index( + IndexExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "a[b()", + }, + errors: [ + "expected RBRACK, got EOF", + ], + }, + array: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, + }, + name: "a", + }, + ), + lbrack: [], + index: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 3", + end: "line: 1, column: 6", + source: "b()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 3", + end: "line: 1, column: 4", + source: "b", + }, + }, + name: "b", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), + rbrack: [], }, - name: "b".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })), - rbrack: vec![], - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn index_with_unbalanced_parenthesis() { let mut p = Parser::new(r#"a[b(]"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "a[b(]", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - expression: Expression::Index(Box::new(IndexExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - array: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "a".to_string() - }), - lbrack: vec![], - index: Expression::Call(Box::new(CallExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 3, 1, 6), - errors: vec!["expected RPAREN, got RBRACK".to_string()], - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "a[b(]", + }, }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 3, 1, 4), - ..BaseNode::default() + expression: Index( + IndexExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "a[b(]", + }, + }, + array: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, + }, + name: "a", + }, + ), + lbrack: [], + index: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 3", + end: "line: 1, column: 6", + source: "b(]", + }, + errors: [ + "expected RPAREN, got RBRACK", + ], + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 3", + end: "line: 1, column: 4", + source: "b", + }, + }, + name: "b", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), + rbrack: [], }, - name: "b".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })), - rbrack: vec![], - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn index_with_unexpected_rparen() { let mut p = Parser::new(r#"a[b)]"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "a[b)]", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - expression: Expression::Index(Box::new(IndexExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - errors: vec!["invalid expression @1:4-1:5: )".to_string()], - ..BaseNode::default() - }, - array: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "a".to_string() - }), - lbrack: vec![], - index: Expression::Identifier(Identifier { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 3, 1, 4), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "a[b)]", + }, }, - name: "b".to_string() - }), - rbrack: vec![], - })) - }))], - eof: vec![], - }, - ) + expression: Index( + IndexExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "a[b)]", + }, + errors: [ + "invalid expression @1:4-1:5: )", + ], + }, + array: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, + }, + name: "a", + }, + ), + lbrack: [], + index: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 3", + end: "line: 1, column: 4", + source: "b", + }, + }, + name: "b", + }, + ), + rbrack: [], + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn int_literal_zero_prefix() { let mut p = Parser::new(r#"0123"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "0123", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() - }, - expression: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - errors: vec![ - "invalid integer literal \"0123\": nonzero value cannot start with 0" - .to_string() - ], - ..BaseNode::default() + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "0123", + }, + }, + expression: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "0123", + }, + errors: [ + "invalid integer literal \"0123\": nonzero value cannot start with 0", + ], + }, + value: 0, + }, + ), }, - value: 0, - }) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } fn test_error_msg(src: &str, expect: expect_test::Expect) { diff --git a/libflux/flux-core/src/parser/tests/from.rs b/libflux/flux-core/src/parser/tests/from.rs index 30f2659dbe..2dfaf6dce3 100644 --- a/libflux/flux-core/src/parser/tests/from.rs +++ b/libflux/flux-core/src/parser/tests/from.rs @@ -1,122 +1,180 @@ -use pretty_assertions::assert_eq; - use super::*; -use crate::ast::tests::Locator; #[test] fn from() { let mut p = Parser::new(r#"from()"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "from()", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() - }, - expression: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "from()", + }, }, - name: "from".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })), - }))], - eof: vec![], - }, - ) + expression: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "from()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "from", + }, + }, + name: "from", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn from_with_database() { let mut p = Parser::new(r#"from(bucket:"telegraf/autogen")"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 32), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 32", + source: "from(bucket:\"telegraf/autogen\")", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 32), - ..BaseNode::default() - }, - expression: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 32), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() - }, - name: "from".to_string() - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 6, 1, 31), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![Property { - base: BaseNode { - location: loc.get(1, 6, 1, 31), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 32", + source: "from(bucket:\"telegraf/autogen\")", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 6, 1, 12), - ..BaseNode::default() - }, - name: "bucket".to_string() - }), - separator: vec![], - value: Some(Expression::StringLit(StringLit { + }, + expression: Call( + CallExpr { base: BaseNode { - location: loc.get(1, 13, 1, 31), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 32", + source: "from(bucket:\"telegraf/autogen\")", + }, }, - value: "telegraf/autogen".to_string() - })), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - })) - }))], - eof: vec![], - }, - ) + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "from", + }, + }, + name: "from", + }, + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 31", + source: "bucket:\"telegraf/autogen\"", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 31", + source: "bucket:\"telegraf/autogen\"", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 12", + source: "bucket", + }, + }, + name: "bucket", + }, + ), + separator: [], + value: Some( + StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 13", + end: "line: 1, column: 31", + source: "\"telegraf/autogen\"", + }, + }, + value: "telegraf/autogen", + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], + }, + ), + }, + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] @@ -125,580 +183,949 @@ fn from_with_filter_with_no_parens() { r#"from(bucket:"telegraf/autogen").filter(fn: (r) => r["other"]=="mem" and r["this"]=="that" or r["these"]!="those")"#, ); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 114), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 114", + source: "from(bucket:\"telegraf/autogen\").filter(fn: (r) => r[\"other\"]==\"mem\" and r[\"this\"]==\"that\" or r[\"these\"]!=\"those\")", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 114), - ..BaseNode::default() - }, - expression: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 114), - ..BaseNode::default() - }, - callee: Expression::Member(Box::new(MemberExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 39), - ..BaseNode::default() - }, - property: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 33, 1, 39), - ..BaseNode::default() - }, - name: "filter".to_string() - }), - lbrack: vec![], - object: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 32), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 114", + source: "from(bucket:\"telegraf/autogen\").filter(fn: (r) => r[\"other\"]==\"mem\" and r[\"this\"]==\"that\" or r[\"these\"]!=\"those\")", }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() - }, - name: "from".to_string() - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 6, 1, 31), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![Property { - base: BaseNode { - location: loc.get(1, 6, 1, 31), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 6, 1, 12), - ..BaseNode::default() - }, - name: "bucket".to_string() - }), - separator: vec![], - value: Some(Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 13, 1, 31), - ..BaseNode::default() - }, - value: "telegraf/autogen".to_string() - })), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - })), - rbrack: vec![], - })), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 40, 1, 113), - ..BaseNode::default() }, - lbrace: vec![], - with: None, - properties: vec![Property { - base: BaseNode { - location: loc.get(1, 40, 1, 113), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 40, 1, 42), - ..BaseNode::default() - }, - name: "fn".to_string() - }), - separator: vec![], - value: Some(Expression::Function(Box::new(FunctionExpr { + expression: Call( + CallExpr { base: BaseNode { - location: loc.get(1, 44, 1, 113), - ..BaseNode::default() - }, - lparen: vec![], - params: vec![Property { - base: BaseNode { - location: loc.get(1, 45, 1, 46), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 114", + source: "from(bucket:\"telegraf/autogen\").filter(fn: (r) => r[\"other\"]==\"mem\" and r[\"this\"]==\"that\" or r[\"these\"]!=\"those\")", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 45, 1, 46), - ..BaseNode::default() - }, - name: "r".to_string() - }), - separator: vec![], - value: None, - comma: vec![], - }], - rparen: vec![], - arrow: vec![], - body: FunctionBody::Expr(Expression::Logical(Box::new( - LogicalExpr { + }, + callee: Member( + MemberExpr { base: BaseNode { - location: loc.get(1, 51, 1, 113), - ..BaseNode::default() - }, - operator: LogicalOperator::OrOperator, - left: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(1, 51, 1, 90), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 39", + source: "from(bucket:\"telegraf/autogen\").filter", }, - operator: LogicalOperator::AndOperator, - left: Expression::Binary(Box::new(BinaryExpr { + }, + object: Call( + CallExpr { base: BaseNode { - location: loc.get(1, 51, 1, 68), - ..BaseNode::default() - }, - operator: Operator::EqualOperator, - left: Expression::Member(Box::new(MemberExpr { - base: BaseNode { - location: loc.get(1, 51, 1, 61), - ..BaseNode::default() - }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 51, 1, 52), - ..BaseNode::default() - }, - name: "r".to_string() - }), - lbrack: vec![], - property: PropertyKey::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 53, 1, 60), - ..BaseNode::default() - }, - value: "other".to_string() - }), - rbrack: vec![], - })), - right: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 63, 1, 68), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 32", + source: "from(bucket:\"telegraf/autogen\")", }, - value: "mem".to_string() - }) - })), - right: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 73, 1, 90), - ..BaseNode::default() }, - operator: Operator::EqualOperator, - left: Expression::Member(Box::new(MemberExpr { - base: BaseNode { - location: loc.get(1, 73, 1, 82), - ..BaseNode::default() - }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 73, 1, 74), - ..BaseNode::default() - }, - name: "r".to_string() - }), - lbrack: vec![], - property: PropertyKey::StringLit(StringLit { + callee: Identifier( + Identifier { base: BaseNode { - location: loc.get(1, 75, 1, 81), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "from", + }, }, - value: "this".to_string() - }), - rbrack: vec![], - })), - right: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 84, 1, 90), - ..BaseNode::default() + name: "from", }, - value: "that".to_string() - }) - })) - })), - right: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 94, 1, 113), - ..BaseNode::default() + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 31", + source: "bucket:\"telegraf/autogen\"", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 31", + source: "bucket:\"telegraf/autogen\"", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 12", + source: "bucket", + }, + }, + name: "bucket", + }, + ), + separator: [], + value: Some( + StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 13", + end: "line: 1, column: 31", + source: "\"telegraf/autogen\"", + }, + }, + value: "telegraf/autogen", + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], }, - operator: Operator::NotEqualOperator, - left: Expression::Member(Box::new(MemberExpr { + ), + lbrack: [], + property: Identifier( + Identifier { base: BaseNode { - location: loc.get(1, 94, 1, 104), - ..BaseNode::default() - }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 94, 1, 95), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 33", + end: "line: 1, column: 39", + source: "filter", }, - name: "r".to_string() - }), - lbrack: vec![], - property: PropertyKey::StringLit(StringLit { + }, + name: "filter", + }, + ), + rbrack: [], + }, + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 40", + end: "line: 1, column: 113", + source: "fn: (r) => r[\"other\"]==\"mem\" and r[\"this\"]==\"that\" or r[\"these\"]!=\"those\"", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { base: BaseNode { - location: loc.get(1, 96, 1, 103), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 40", + end: "line: 1, column: 113", + source: "fn: (r) => r[\"other\"]==\"mem\" and r[\"this\"]==\"that\" or r[\"these\"]!=\"those\"", + }, }, - value: "these".to_string() - }), - rbrack: vec![], - })), - right: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 106, 1, 113), - ..BaseNode::default() + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 40", + end: "line: 1, column: 42", + source: "fn", + }, + }, + name: "fn", + }, + ), + separator: [], + value: Some( + Function( + FunctionExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 44", + end: "line: 1, column: 113", + source: "(r) => r[\"other\"]==\"mem\" and r[\"this\"]==\"that\" or r[\"these\"]!=\"those\"", + }, + }, + lparen: [], + params: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 45", + end: "line: 1, column: 46", + source: "r", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 45", + end: "line: 1, column: 46", + source: "r", + }, + }, + name: "r", + }, + ), + separator: [], + value: None, + comma: [], + }, + ], + rparen: [], + arrow: [], + body: Expr( + Logical( + LogicalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 51", + end: "line: 1, column: 113", + source: "r[\"other\"]==\"mem\" and r[\"this\"]==\"that\" or r[\"these\"]!=\"those\"", + }, + }, + operator: OrOperator, + left: Logical( + LogicalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 51", + end: "line: 1, column: 90", + source: "r[\"other\"]==\"mem\" and r[\"this\"]==\"that\"", + }, + }, + operator: AndOperator, + left: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 51", + end: "line: 1, column: 68", + source: "r[\"other\"]==\"mem\"", + }, + }, + operator: EqualOperator, + left: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 51", + end: "line: 1, column: 61", + source: "r[\"other\"]", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 51", + end: "line: 1, column: 52", + source: "r", + }, + }, + name: "r", + }, + ), + lbrack: [], + property: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 53", + end: "line: 1, column: 60", + source: "\"other\"", + }, + }, + value: "other", + }, + ), + rbrack: [], + }, + ), + right: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 63", + end: "line: 1, column: 68", + source: "\"mem\"", + }, + }, + value: "mem", + }, + ), + }, + ), + right: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 73", + end: "line: 1, column: 90", + source: "r[\"this\"]==\"that\"", + }, + }, + operator: EqualOperator, + left: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 73", + end: "line: 1, column: 82", + source: "r[\"this\"]", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 73", + end: "line: 1, column: 74", + source: "r", + }, + }, + name: "r", + }, + ), + lbrack: [], + property: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 75", + end: "line: 1, column: 81", + source: "\"this\"", + }, + }, + value: "this", + }, + ), + rbrack: [], + }, + ), + right: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 84", + end: "line: 1, column: 90", + source: "\"that\"", + }, + }, + value: "that", + }, + ), + }, + ), + }, + ), + right: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 94", + end: "line: 1, column: 113", + source: "r[\"these\"]!=\"those\"", + }, + }, + operator: NotEqualOperator, + left: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 94", + end: "line: 1, column: 104", + source: "r[\"these\"]", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 94", + end: "line: 1, column: 95", + source: "r", + }, + }, + name: "r", + }, + ), + lbrack: [], + property: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 96", + end: "line: 1, column: 103", + source: "\"these\"", + }, + }, + value: "these", + }, + ), + rbrack: [], + }, + ), + right: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 106", + end: "line: 1, column: 113", + source: "\"those\"", + }, + }, + value: "those", + }, + ), + }, + ), + }, + ), + ), + }, + ), + ), + comma: [], }, - value: "those".to_string() - }) - })) - } - ))), - }))), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - })) - }))], - eof: vec![], - }, - ) + ], + rbrace: [], + }, + ), + ], + rparen: [], + }, + ), + }, + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] fn from_with_range() { let mut p = Parser::new(r#"from(bucket:"telegraf/autogen")|>range(start:-1h, end:10m)"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 59), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 59", + source: "from(bucket:\"telegraf/autogen\")|>range(start:-1h, end:10m)", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 59), - ..BaseNode::default() - }, - expression: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 59), - ..BaseNode::default() - }, - argument: Expression::Call(Box::new(CallExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 32), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() - }, - name: "from".to_string() - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 6, 1, 31), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 59", + source: "from(bucket:\"telegraf/autogen\")|>range(start:-1h, end:10m)", }, - lbrace: vec![], - with: None, - properties: vec![Property { - base: BaseNode { - location: loc.get(1, 6, 1, 31), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 6, 1, 12), - ..BaseNode::default() - }, - name: "bucket".to_string() - }), - separator: vec![], - value: Some(Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 13, 1, 31), - ..BaseNode::default() - }, - value: "telegraf/autogen".to_string() - })), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - })), - call: CallExpr { - base: BaseNode { - location: loc.get(1, 34, 1, 59), - ..BaseNode::default() }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 34, 1, 39), - ..BaseNode::default() - }, - name: "range".to_string() - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 40, 1, 58), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![ - Property { - base: BaseNode { - location: loc.get(1, 40, 1, 49), - ..BaseNode::default() + expression: PipeExpr( + PipeExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 59", + source: "from(bucket:\"telegraf/autogen\")|>range(start:-1h, end:10m)", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 40, 1, 45), - ..BaseNode::default() - }, - name: "start".to_string() - }), - separator: vec![], - value: Some(Expression::Unary(Box::new(UnaryExpr { + }, + argument: Call( + CallExpr { base: BaseNode { - location: loc.get(1, 46, 1, 49), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 32", + source: "from(bucket:\"telegraf/autogen\")", + }, }, - operator: Operator::SubtractionOperator, - argument: Expression::Duration(DurationLit { - base: BaseNode { - location: loc.get(1, 47, 1, 49), - ..BaseNode::default() + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "from", + }, + }, + name: "from", }, - values: vec![Duration { - magnitude: 1, - unit: "h".to_string() - }] - }) - }))), - comma: vec![], - }, - Property { - base: BaseNode { - location: loc.get(1, 51, 1, 58), - ..BaseNode::default() + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 31", + source: "bucket:\"telegraf/autogen\"", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 31", + source: "bucket:\"telegraf/autogen\"", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 12", + source: "bucket", + }, + }, + name: "bucket", + }, + ), + separator: [], + value: Some( + StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 13", + end: "line: 1, column: 31", + source: "\"telegraf/autogen\"", + }, + }, + value: "telegraf/autogen", + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 51, 1, 54), - ..BaseNode::default() + ), + call: CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 34", + end: "line: 1, column: 59", + source: "range(start:-1h, end:10m)", }, - name: "end".to_string() - }), - separator: vec![], - value: Some(Expression::Duration(DurationLit { - base: BaseNode { - location: loc.get(1, 55, 1, 58), - ..BaseNode::default() + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 34", + end: "line: 1, column: 39", + source: "range", + }, + }, + name: "range", }, - values: vec![Duration { - magnitude: 10, - unit: "m".to_string() - }] - })), - comma: vec![], - } - ], - rbrace: vec![], - }))], - rparen: vec![], - } - })) - }))], - eof: vec![], - }, - ) + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 40", + end: "line: 1, column: 58", + source: "start:-1h, end:10m", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 40", + end: "line: 1, column: 49", + source: "start:-1h", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 40", + end: "line: 1, column: 45", + source: "start", + }, + }, + name: "start", + }, + ), + separator: [], + value: Some( + Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 46", + end: "line: 1, column: 49", + source: "-1h", + }, + }, + operator: SubtractionOperator, + argument: Duration( + DurationLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 47", + end: "line: 1, column: 49", + source: "1h", + }, + }, + values: [ + Duration { + magnitude: 1, + unit: "h", + }, + ], + }, + ), + }, + ), + ), + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 51", + end: "line: 1, column: 58", + source: "end:10m", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 51", + end: "line: 1, column: 54", + source: "end", + }, + }, + name: "end", + }, + ), + separator: [], + value: Some( + Duration( + DurationLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 55", + end: "line: 1, column: 58", + source: "10m", + }, + }, + values: [ + Duration { + magnitude: 10, + unit: "m", + }, + ], + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], + }, + }, + ), + }, + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] fn from_with_limit() { let mut p = Parser::new(r#"from(bucket:"telegraf/autogen")|>limit(limit:100, offset:10)"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 61), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 61", + source: "from(bucket:\"telegraf/autogen\")|>limit(limit:100, offset:10)", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 61), - ..BaseNode::default() - }, - expression: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 61), - ..BaseNode::default() - }, - argument: Expression::Call(Box::new(CallExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 32), - ..BaseNode::default() - }, - lparen: vec![], - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 61", + source: "from(bucket:\"telegraf/autogen\")|>limit(limit:100, offset:10)", }, - name: "from".to_string() - }), - rparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 6, 1, 31), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![Property { - base: BaseNode { - location: loc.get(1, 6, 1, 31), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 6, 1, 12), - ..BaseNode::default() - }, - name: "bucket".to_string() - }), - separator: vec![], - value: Some(Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 13, 1, 31), - ..BaseNode::default() - }, - value: "telegraf/autogen".to_string() - })), - comma: vec![], - }], - rbrace: vec![], - }))] - })), - call: CallExpr { - base: BaseNode { - location: loc.get(1, 34, 1, 61), - ..BaseNode::default() }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 34, 1, 39), - ..BaseNode::default() - }, - name: "limit".to_string() - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 40, 1, 60), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![ - Property { - base: BaseNode { - location: loc.get(1, 40, 1, 49), - ..BaseNode::default() + expression: PipeExpr( + PipeExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 61", + source: "from(bucket:\"telegraf/autogen\")|>limit(limit:100, offset:10)", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 40, 1, 45), - ..BaseNode::default() - }, - name: "limit".to_string() - }), - separator: vec![], - value: Some(Expression::Integer(IntegerLit { + }, + argument: Call( + CallExpr { base: BaseNode { - location: loc.get(1, 46, 1, 49), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 32", + source: "from(bucket:\"telegraf/autogen\")", + }, }, - value: 100 - })), - comma: vec![], - }, - Property { - base: BaseNode { - location: loc.get(1, 51, 1, 60), - ..BaseNode::default() + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "from", + }, + }, + name: "from", + }, + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 31", + source: "bucket:\"telegraf/autogen\"", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 31", + source: "bucket:\"telegraf/autogen\"", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 12", + source: "bucket", + }, + }, + name: "bucket", + }, + ), + separator: [], + value: Some( + StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 13", + end: "line: 1, column: 31", + source: "\"telegraf/autogen\"", + }, + }, + value: "telegraf/autogen", + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 51, 1, 57), - ..BaseNode::default() + ), + call: CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 34", + end: "line: 1, column: 61", + source: "limit(limit:100, offset:10)", }, - name: "offset".to_string() - }), - separator: vec![], - value: Some(Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 58, 1, 60), - ..BaseNode::default() + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 34", + end: "line: 1, column: 39", + source: "limit", + }, + }, + name: "limit", }, - value: 10 - })), - comma: vec![], - } - ], - rbrace: vec![], - }))], - rparen: vec![], - } - })) - }))], - eof: vec![], - }, - ) + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 40", + end: "line: 1, column: 60", + source: "limit:100, offset:10", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 40", + end: "line: 1, column: 49", + source: "limit:100", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 40", + end: "line: 1, column: 45", + source: "limit", + }, + }, + name: "limit", + }, + ), + separator: [], + value: Some( + Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 46", + end: "line: 1, column: 49", + source: "100", + }, + }, + value: 100, + }, + ), + ), + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 51", + end: "line: 1, column: 60", + source: "offset:10", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 51", + end: "line: 1, column: 57", + source: "offset", + }, + }, + name: "offset", + }, + ), + separator: [], + value: Some( + Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 58", + end: "line: 1, column: 60", + source: "10", + }, + }, + value: 10, + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], + }, + }, + ), + }, + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] @@ -709,191 +1136,310 @@ fn from_with_range_and_count() { |> count()"#, ); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 3, 17), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 3, column: 17", + source: "from(bucket:\"mydb/autogen\")\n\t\t\t\t\t\t|> range(start:-4h, stop:-2h)\n\t\t\t\t\t\t|> count()", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 3, 17), - ..BaseNode::default() - }, - expression: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(1, 1, 3, 17), - ..BaseNode::default() - }, - argument: Expression::PipeExpr(Box::new(PipeExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 2, 36), - ..BaseNode::default() - }, - argument: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 28), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 3, column: 17", + source: "from(bucket:\"mydb/autogen\")\n\t\t\t\t\t\t|> range(start:-4h, stop:-2h)\n\t\t\t\t\t\t|> count()", }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() - }, - name: "from".to_string() - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { + }, + expression: PipeExpr( + PipeExpr { base: BaseNode { - location: loc.get(1, 6, 1, 27), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![Property { - base: BaseNode { - location: loc.get(1, 6, 1, 27), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 3, column: 17", + source: "from(bucket:\"mydb/autogen\")\n\t\t\t\t\t\t|> range(start:-4h, stop:-2h)\n\t\t\t\t\t\t|> count()", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 6, 1, 12), - ..BaseNode::default() - }, - name: "bucket".to_string() - }), - separator: vec![], - value: Some(Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 13, 1, 27), - ..BaseNode::default() - }, - value: "mydb/autogen".to_string() - })), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - })), - call: CallExpr { - base: BaseNode { - location: loc.get(2, 10, 2, 36), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 10, 2, 15), - ..BaseNode::default() - }, - name: "range".to_string() - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(2, 16, 2, 35), - ..BaseNode::default() }, - lbrace: vec![], - with: None, - properties: vec![ - Property { + argument: PipeExpr( + PipeExpr { base: BaseNode { - location: loc.get(2, 16, 2, 25), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 2, column: 36", + source: "from(bucket:\"mydb/autogen\")\n\t\t\t\t\t\t|> range(start:-4h, stop:-2h)", + }, }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 16, 2, 21), - ..BaseNode::default() + argument: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 28", + source: "from(bucket:\"mydb/autogen\")", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "from", + }, + }, + name: "from", + }, + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 27", + source: "bucket:\"mydb/autogen\"", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 27", + source: "bucket:\"mydb/autogen\"", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 12", + source: "bucket", + }, + }, + name: "bucket", + }, + ), + separator: [], + value: Some( + StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 13", + end: "line: 1, column: 27", + source: "\"mydb/autogen\"", + }, + }, + value: "mydb/autogen", + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], }, - name: "start".to_string() - }), - separator: vec![], - value: Some(Expression::Unary(Box::new(UnaryExpr { + ), + call: CallExpr { base: BaseNode { - location: loc.get(2, 22, 2, 25), - ..BaseNode::default() - }, - operator: Operator::SubtractionOperator, - argument: Expression::Duration(DurationLit { - base: BaseNode { - location: loc.get(2, 23, 2, 25), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 10", + end: "line: 2, column: 36", + source: "range(start:-4h, stop:-2h)", }, - values: vec![Duration { - magnitude: 4, - unit: "h".to_string() - }] - }) - }))), - comma: vec![], + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 10", + end: "line: 2, column: 15", + source: "range", + }, + }, + name: "range", + }, + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 16", + end: "line: 2, column: 35", + source: "start:-4h, stop:-2h", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 16", + end: "line: 2, column: 25", + source: "start:-4h", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 16", + end: "line: 2, column: 21", + source: "start", + }, + }, + name: "start", + }, + ), + separator: [], + value: Some( + Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 22", + end: "line: 2, column: 25", + source: "-4h", + }, + }, + operator: SubtractionOperator, + argument: Duration( + DurationLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 23", + end: "line: 2, column: 25", + source: "4h", + }, + }, + values: [ + Duration { + magnitude: 4, + unit: "h", + }, + ], + }, + ), + }, + ), + ), + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 27", + end: "line: 2, column: 35", + source: "stop:-2h", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 27", + end: "line: 2, column: 31", + source: "stop", + }, + }, + name: "stop", + }, + ), + separator: [], + value: Some( + Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 32", + end: "line: 2, column: 35", + source: "-2h", + }, + }, + operator: SubtractionOperator, + argument: Duration( + DurationLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 33", + end: "line: 2, column: 35", + source: "2h", + }, + }, + values: [ + Duration { + magnitude: 2, + unit: "h", + }, + ], + }, + ), + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], + }, }, - Property { - base: BaseNode { - location: loc.get(2, 27, 2, 35), - ..BaseNode::default() + ), + call: CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 10", + end: "line: 3, column: 17", + source: "count()", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 27, 2, 31), - ..BaseNode::default() - }, - name: "stop".to_string() - }), - separator: vec![], - value: Some(Expression::Unary(Box::new(UnaryExpr { + }, + callee: Identifier( + Identifier { base: BaseNode { - location: loc.get(2, 32, 2, 35), - ..BaseNode::default() - }, - operator: Operator::SubtractionOperator, - argument: Expression::Duration(DurationLit { - base: BaseNode { - location: loc.get(2, 33, 2, 35), - ..BaseNode::default() + location: SourceLocation { + start: "line: 3, column: 10", + end: "line: 3, column: 15", + source: "count", }, - values: vec![Duration { - magnitude: 2, - unit: "h".to_string() - }] - }) - }))), - comma: vec![], - } - ], - rbrace: vec![], - }))], - rparen: vec![], - } - })), - call: CallExpr { - base: BaseNode { - location: loc.get(3, 10, 3, 17), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(3, 10, 3, 15), - ..BaseNode::default() + }, + name: "count", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, }, - name: "count".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - } - })) - }))], - eof: vec![], + ), + }, + ), + ], + eof: [], } - ) + "#]].assert_debug_eq(&parsed); } #[test] @@ -905,243 +1451,399 @@ fn from_with_range_limit_and_count() { |> count()"#, ); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 4, 17), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 4, column: 17", + source: "from(bucket:\"mydb/autogen\")\n\t\t\t\t\t\t|> range(start:-4h, stop:-2h)\n\t\t\t\t\t\t|> limit(n:10)\n\t\t\t\t\t\t|> count()", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 4, 17), - ..BaseNode::default() - }, - expression: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(1, 1, 4, 17), - ..BaseNode::default() - }, - argument: Expression::PipeExpr(Box::new(PipeExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 3, 21), - ..BaseNode::default() - }, - argument: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(1, 1, 2, 36), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 4, column: 17", + source: "from(bucket:\"mydb/autogen\")\n\t\t\t\t\t\t|> range(start:-4h, stop:-2h)\n\t\t\t\t\t\t|> limit(n:10)\n\t\t\t\t\t\t|> count()", }, - argument: Expression::Call(Box::new(CallExpr { + }, + expression: PipeExpr( + PipeExpr { base: BaseNode { - location: loc.get(1, 1, 1, 28), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 4, column: 17", + source: "from(bucket:\"mydb/autogen\")\n\t\t\t\t\t\t|> range(start:-4h, stop:-2h)\n\t\t\t\t\t\t|> limit(n:10)\n\t\t\t\t\t\t|> count()", }, - name: "from".to_string() - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 6, 1, 27), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![Property { - base: BaseNode { - location: loc.get(1, 6, 1, 27), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 6, 1, 12), - ..BaseNode::default() - }, - name: "bucket".to_string() - }), - separator: vec![], - value: Some(Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 13, 1, 27), - ..BaseNode::default() - }, - value: "mydb/autogen".to_string() - })), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - })), - call: CallExpr { - base: BaseNode { - location: loc.get(2, 10, 2, 36), - ..BaseNode::default() }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 10, 2, 15), - ..BaseNode::default() - }, - name: "range".to_string() - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(2, 16, 2, 35), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![ - Property { - base: BaseNode { - location: loc.get(2, 16, 2, 25), - ..BaseNode::default() + argument: PipeExpr( + PipeExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 3, column: 21", + source: "from(bucket:\"mydb/autogen\")\n\t\t\t\t\t\t|> range(start:-4h, stop:-2h)\n\t\t\t\t\t\t|> limit(n:10)", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 16, 2, 21), - ..BaseNode::default() - }, - name: "start".to_string() - }), - separator: vec![], - value: Some(Expression::Unary(Box::new(UnaryExpr { + }, + argument: PipeExpr( + PipeExpr { base: BaseNode { - location: loc.get(2, 22, 2, 25), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 2, column: 36", + source: "from(bucket:\"mydb/autogen\")\n\t\t\t\t\t\t|> range(start:-4h, stop:-2h)", + }, }, - operator: Operator::SubtractionOperator, - argument: Expression::Duration(DurationLit { + argument: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 28", + source: "from(bucket:\"mydb/autogen\")", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "from", + }, + }, + name: "from", + }, + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 27", + source: "bucket:\"mydb/autogen\"", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 27", + source: "bucket:\"mydb/autogen\"", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 12", + source: "bucket", + }, + }, + name: "bucket", + }, + ), + separator: [], + value: Some( + StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 13", + end: "line: 1, column: 27", + source: "\"mydb/autogen\"", + }, + }, + value: "mydb/autogen", + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], + }, + ), + call: CallExpr { base: BaseNode { - location: loc.get(2, 23, 2, 25), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 10", + end: "line: 2, column: 36", + source: "range(start:-4h, stop:-2h)", + }, }, - values: vec![Duration { - magnitude: 4, - unit: "h".to_string() - }] - }) - }))), - comma: vec![], - }, - Property { - base: BaseNode { - location: loc.get(2, 27, 2, 35), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 27, 2, 31), - ..BaseNode::default() + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 10", + end: "line: 2, column: 15", + source: "range", + }, + }, + name: "range", + }, + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 16", + end: "line: 2, column: 35", + source: "start:-4h, stop:-2h", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 16", + end: "line: 2, column: 25", + source: "start:-4h", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 16", + end: "line: 2, column: 21", + source: "start", + }, + }, + name: "start", + }, + ), + separator: [], + value: Some( + Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 22", + end: "line: 2, column: 25", + source: "-4h", + }, + }, + operator: SubtractionOperator, + argument: Duration( + DurationLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 23", + end: "line: 2, column: 25", + source: "4h", + }, + }, + values: [ + Duration { + magnitude: 4, + unit: "h", + }, + ], + }, + ), + }, + ), + ), + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 27", + end: "line: 2, column: 35", + source: "stop:-2h", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 27", + end: "line: 2, column: 31", + source: "stop", + }, + }, + name: "stop", + }, + ), + separator: [], + value: Some( + Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 32", + end: "line: 2, column: 35", + source: "-2h", + }, + }, + operator: SubtractionOperator, + argument: Duration( + DurationLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 33", + end: "line: 2, column: 35", + source: "2h", + }, + }, + values: [ + Duration { + magnitude: 2, + unit: "h", + }, + ], + }, + ), + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], }, - name: "stop".to_string() - }), - separator: vec![], - value: Some(Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(2, 32, 2, 35), - ..BaseNode::default() + }, + ), + call: CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 10", + end: "line: 3, column: 21", + source: "limit(n:10)", }, - operator: Operator::SubtractionOperator, - argument: Expression::Duration(DurationLit { + }, + callee: Identifier( + Identifier { base: BaseNode { - location: loc.get(2, 33, 2, 35), - ..BaseNode::default() + location: SourceLocation { + start: "line: 3, column: 10", + end: "line: 3, column: 15", + source: "limit", + }, }, - values: vec![Duration { - magnitude: 2, - unit: "h".to_string() - }] - }) - }))), - comma: vec![], - } - ], - rbrace: vec![], - }))], - rparen: vec![], - } - })), - call: CallExpr { - base: BaseNode { - location: loc.get(3, 10, 3, 21), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(3, 10, 3, 15), - ..BaseNode::default() - }, - name: "limit".to_string() - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(3, 16, 3, 20), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![Property { - base: BaseNode { - location: loc.get(3, 16, 3, 20), - ..BaseNode::default() + name: "limit", + }, + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 16", + end: "line: 3, column: 20", + source: "n:10", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 16", + end: "line: 3, column: 20", + source: "n:10", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 16", + end: "line: 3, column: 17", + source: "n", + }, + }, + name: "n", + }, + ), + separator: [], + value: Some( + Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 18", + end: "line: 3, column: 20", + source: "10", + }, + }, + value: 10, + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], + }, }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(3, 16, 3, 17), - ..BaseNode::default() + ), + call: CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 10", + end: "line: 4, column: 17", + source: "count()", }, - name: "n".to_string() - }), - separator: vec![], - value: Some(Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(3, 18, 3, 20), - ..BaseNode::default() + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 10", + end: "line: 4, column: 15", + source: "count", + }, + }, + name: "count", }, - value: 10 - })), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - } - })), - call: CallExpr { - base: BaseNode { - location: loc.get(4, 10, 4, 17), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(4, 10, 4, 15), - ..BaseNode::default() + ), + lparen: [], + arguments: [], + rparen: [], + }, }, - name: "count".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - } - })) - }))], - eof: vec![], + ), + }, + ), + ], + eof: [], } - ) + "#]].assert_debug_eq(&parsed); } #[test] @@ -1153,486 +1855,794 @@ b = from(bucket:"dbB/autogen") |> range(start:-1h) join(tables:[a,b], on:["host"], fn: (a,b) => a["_field"] + b["_field"])"#, ); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(2, 1, 4, 72), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 1", + end: "line: 4, column: 72", + source: "a = from(bucket:\"dbA/autogen\") |> range(start:-1h)\nb = from(bucket:\"dbB/autogen\") |> range(start:-1h)\njoin(tables:[a,b], on:[\"host\"], fn: (a,b) => a[\"_field\"] + b[\"_field\"])", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![ - Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(2, 1, 2, 51), - ..BaseNode::default() - }, - id: Identifier { + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(2, 1, 2, 2), - ..BaseNode::default() - }, - name: "a".to_string() - }, - init: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(2, 5, 2, 51), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 1", + end: "line: 2, column: 51", + source: "a = from(bucket:\"dbA/autogen\") |> range(start:-1h)", + }, }, - argument: Expression::Call(Box::new(CallExpr { + id: Identifier { base: BaseNode { - location: loc.get(2, 5, 2, 31), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 5, 2, 9), - ..BaseNode::default() - }, - name: "from".to_string() - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(2, 10, 2, 30), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 1", + end: "line: 2, column: 2", + source: "a", }, - lbrace: vec![], - with: None, - properties: vec![Property { - base: BaseNode { - location: loc.get(2, 10, 2, 30), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 10, 2, 16), - ..BaseNode::default() - }, - name: "bucket".to_string() - }), - separator: vec![], - value: Some(Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(2, 17, 2, 30), - ..BaseNode::default() - }, - value: "dbA/autogen".to_string() - })), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - })), - call: CallExpr { - base: BaseNode { - location: loc.get(2, 35, 2, 51), - ..BaseNode::default() }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 35, 2, 40), - ..BaseNode::default() - }, - name: "range".to_string() - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { + name: "a", + }, + init: PipeExpr( + PipeExpr { base: BaseNode { - location: loc.get(2, 41, 2, 50), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![Property { - base: BaseNode { - location: loc.get(2, 41, 2, 50), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 5", + end: "line: 2, column: 51", + source: "from(bucket:\"dbA/autogen\") |> range(start:-1h)", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 41, 2, 46), - ..BaseNode::default() - }, - name: "start".to_string() - }), - separator: vec![], - value: Some(Expression::Unary(Box::new(UnaryExpr { + }, + argument: Call( + CallExpr { base: BaseNode { - location: loc.get(2, 47, 2, 50), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 5", + end: "line: 2, column: 31", + source: "from(bucket:\"dbA/autogen\")", + }, }, - operator: Operator::SubtractionOperator, - argument: Expression::Duration(DurationLit { - base: BaseNode { - location: loc.get(2, 48, 2, 50), - ..BaseNode::default() + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 5", + end: "line: 2, column: 9", + source: "from", + }, + }, + name: "from", }, - values: vec![Duration { - magnitude: 1, - unit: "h".to_string() - }] - }) - }))), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - } - })) - })), - Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(3, 1, 3, 51), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(3, 1, 3, 2), - ..BaseNode::default() - }, - name: "b".to_string() - }, - init: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(3, 5, 3, 51), - ..BaseNode::default() - }, - argument: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(3, 5, 3, 31), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(3, 5, 3, 9), - ..BaseNode::default() - }, - name: "from".to_string() - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(3, 10, 3, 30), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![Property { - base: BaseNode { - location: loc.get(3, 10, 3, 30), - ..BaseNode::default() + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 10", + end: "line: 2, column: 30", + source: "bucket:\"dbA/autogen\"", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 10", + end: "line: 2, column: 30", + source: "bucket:\"dbA/autogen\"", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 10", + end: "line: 2, column: 16", + source: "bucket", + }, + }, + name: "bucket", + }, + ), + separator: [], + value: Some( + StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 17", + end: "line: 2, column: 30", + source: "\"dbA/autogen\"", + }, + }, + value: "dbA/autogen", + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(3, 10, 3, 16), - ..BaseNode::default() - }, - name: "bucket".to_string() - }), - separator: vec![], - value: Some(Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(3, 17, 3, 30), - ..BaseNode::default() - }, - value: "dbB/autogen".to_string() - })), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - })), - call: CallExpr { - base: BaseNode { - location: loc.get(3, 35, 3, 51), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(3, 35, 3, 40), - ..BaseNode::default() - }, - name: "range".to_string() - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(3, 41, 3, 50), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![Property { + ), + call: CallExpr { base: BaseNode { - location: loc.get(3, 41, 3, 50), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(3, 41, 3, 46), - ..BaseNode::default() - }, - name: "start".to_string() - }), - separator: vec![], - value: Some(Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(3, 47, 3, 50), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 35", + end: "line: 2, column: 51", + source: "range(start:-1h)", }, - operator: Operator::SubtractionOperator, - argument: Expression::Duration(DurationLit { + }, + callee: Identifier( + Identifier { base: BaseNode { - location: loc.get(3, 48, 3, 50), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 35", + end: "line: 2, column: 40", + source: "range", + }, + }, + name: "range", + }, + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 41", + end: "line: 2, column: 50", + source: "start:-1h", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 41", + end: "line: 2, column: 50", + source: "start:-1h", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 41", + end: "line: 2, column: 46", + source: "start", + }, + }, + name: "start", + }, + ), + separator: [], + value: Some( + Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 47", + end: "line: 2, column: 50", + source: "-1h", + }, + }, + operator: SubtractionOperator, + argument: Duration( + DurationLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 48", + end: "line: 2, column: 50", + source: "1h", + }, + }, + values: [ + Duration { + magnitude: 1, + unit: "h", + }, + ], + }, + ), + }, + ), + ), + comma: [], + }, + ], + rbrace: [], }, - values: vec![Duration { - magnitude: 1, - unit: "h".to_string() - }] - }) - }))), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - } - })) - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(4, 1, 4, 72), - ..BaseNode::default() + ), + ], + rparen: [], + }, + }, + ), }, - expression: Expression::Call(Box::new(CallExpr { + ), + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(4, 1, 4, 72), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(4, 1, 4, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 3, column: 1", + end: "line: 3, column: 51", + source: "b = from(bucket:\"dbB/autogen\") |> range(start:-1h)", }, - name: "join".to_string() - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { + }, + id: Identifier { base: BaseNode { - location: loc.get(4, 6, 4, 71), - ..BaseNode::default() + location: SourceLocation { + start: "line: 3, column: 1", + end: "line: 3, column: 2", + source: "b", + }, }, - lbrace: vec![], - with: None, - properties: vec![ - Property { - base: BaseNode { - location: loc.get(4, 6, 4, 18), - ..BaseNode::default() + name: "b", + }, + init: PipeExpr( + PipeExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 5", + end: "line: 3, column: 51", + source: "from(bucket:\"dbB/autogen\") |> range(start:-1h)", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(4, 6, 4, 12), - ..BaseNode::default() - }, - name: "tables".to_string() - }), - separator: vec![], - value: Some(Expression::Array(Box::new(ArrayExpr { + }, + argument: Call( + CallExpr { base: BaseNode { - location: loc.get(4, 13, 4, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 3, column: 5", + end: "line: 3, column: 31", + source: "from(bucket:\"dbB/autogen\")", + }, }, - lbrack: vec![], - elements: vec![ - ArrayItem { - expression: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(4, 14, 4, 15), - ..BaseNode::default() + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 5", + end: "line: 3, column: 9", + source: "from", }, - name: "a".to_string() - }), - comma: vec![], + }, + name: "from", }, - ArrayItem { - expression: Expression::Identifier(Identifier { + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { base: BaseNode { - location: loc.get(4, 16, 4, 17), - ..BaseNode::default() + location: SourceLocation { + start: "line: 3, column: 10", + end: "line: 3, column: 30", + source: "bucket:\"dbB/autogen\"", + }, }, - name: "b".to_string() - }), - comma: vec![], - } + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 10", + end: "line: 3, column: 30", + source: "bucket:\"dbB/autogen\"", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 10", + end: "line: 3, column: 16", + source: "bucket", + }, + }, + name: "bucket", + }, + ), + separator: [], + value: Some( + StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 17", + end: "line: 3, column: 30", + source: "\"dbB/autogen\"", + }, + }, + value: "dbB/autogen", + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), ], - rbrack: vec![], - }))), - comma: vec![], - }, - Property { - base: BaseNode { - location: loc.get(4, 20, 4, 31), - ..BaseNode::default() + rparen: [], }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(4, 20, 4, 22), - ..BaseNode::default() + ), + call: CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 35", + end: "line: 3, column: 51", + source: "range(start:-1h)", }, - name: "on".to_string() - }), - separator: vec![], - value: Some(Expression::Array(Box::new(ArrayExpr { - base: BaseNode { - location: loc.get(4, 23, 4, 31), - ..BaseNode::default() + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 35", + end: "line: 3, column: 40", + source: "range", + }, + }, + name: "range", }, - lbrack: vec![], - elements: vec![ArrayItem { - expression: Expression::StringLit(StringLit { + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { base: BaseNode { - location: loc.get(4, 24, 4, 30), - ..BaseNode::default() + location: SourceLocation { + start: "line: 3, column: 41", + end: "line: 3, column: 50", + source: "start:-1h", + }, }, - value: "host".to_string() - }), - comma: vec![], - }], - rbrack: vec![], - }))), - comma: vec![], + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 41", + end: "line: 3, column: 50", + source: "start:-1h", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 41", + end: "line: 3, column: 46", + source: "start", + }, + }, + name: "start", + }, + ), + separator: [], + value: Some( + Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 47", + end: "line: 3, column: 50", + source: "-1h", + }, + }, + operator: SubtractionOperator, + argument: Duration( + DurationLit { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 48", + end: "line: 3, column: 50", + source: "1h", + }, + }, + values: [ + Duration { + magnitude: 1, + unit: "h", + }, + ], + }, + ), + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], }, - Property { - base: BaseNode { - location: loc.get(4, 33, 4, 71), - ..BaseNode::default() + }, + ), + }, + ), + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 1", + end: "line: 4, column: 72", + source: "join(tables:[a,b], on:[\"host\"], fn: (a,b) => a[\"_field\"] + b[\"_field\"])", + }, + }, + expression: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 1", + end: "line: 4, column: 72", + source: "join(tables:[a,b], on:[\"host\"], fn: (a,b) => a[\"_field\"] + b[\"_field\"])", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(4, 33, 4, 35), - ..BaseNode::default() - }, - name: "fn".to_string() - }), - separator: vec![], - value: Some(Expression::Function(Box::new(FunctionExpr { + }, + callee: Identifier( + Identifier { base: BaseNode { - location: loc.get(4, 37, 4, 71), - ..BaseNode::default() + location: SourceLocation { + start: "line: 4, column: 1", + end: "line: 4, column: 5", + source: "join", + }, }, - lparen: vec![], - params: vec![ - Property { - base: BaseNode { - location: loc.get(4, 38, 4, 39), - ..BaseNode::default() + name: "join", + }, + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 6", + end: "line: 4, column: 71", + source: "tables:[a,b], on:[\"host\"], fn: (a,b) => a[\"_field\"] + b[\"_field\"]", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(4, 38, 4, 39), - ..BaseNode::default() - }, - name: "a".to_string() - }), - separator: vec![], - value: None, - comma: vec![], }, - Property { - base: BaseNode { - location: loc.get(4, 40, 4, 41), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { + lbrace: [], + with: None, + properties: [ + Property { base: BaseNode { - location: loc.get(4, 40, 4, 41), - ..BaseNode::default() + location: SourceLocation { + start: "line: 4, column: 6", + end: "line: 4, column: 18", + source: "tables:[a,b]", + }, }, - name: "b".to_string() - }), - separator: vec![], - value: None, - comma: vec![], - } - ], - rparen: vec![], - arrow: vec![], - body: FunctionBody::Expr(Expression::Binary(Box::new( - BinaryExpr { - base: BaseNode { - location: loc.get(4, 46, 4, 71), - ..BaseNode::default() + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 6", + end: "line: 4, column: 12", + source: "tables", + }, + }, + name: "tables", + }, + ), + separator: [], + value: Some( + Array( + ArrayExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 13", + end: "line: 4, column: 18", + source: "[a,b]", + }, + }, + lbrack: [], + elements: [ + ArrayItem { + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 14", + end: "line: 4, column: 15", + source: "a", + }, + }, + name: "a", + }, + ), + comma: [], + }, + ArrayItem { + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 16", + end: "line: 4, column: 17", + source: "b", + }, + }, + name: "b", + }, + ), + comma: [], + }, + ], + rbrack: [], + }, + ), + ), + comma: [], }, - operator: Operator::AdditionOperator, - left: Expression::Member(Box::new(MemberExpr { + Property { base: BaseNode { - location: loc.get(4, 46, 4, 57), - ..BaseNode::default() - }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(4, 46, 4, 47), - ..BaseNode::default() + location: SourceLocation { + start: "line: 4, column: 20", + end: "line: 4, column: 31", + source: "on:[\"host\"]", }, - name: "a".to_string() - }), - lbrack: vec![], - property: PropertyKey::StringLit(StringLit { - base: BaseNode { - location: loc.get(4, 48, 4, 56), - ..BaseNode::default() + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 20", + end: "line: 4, column: 22", + source: "on", + }, + }, + name: "on", }, - value: "_field".to_string() - }), - rbrack: vec![], - })), - right: Expression::Member(Box::new(MemberExpr { + ), + separator: [], + value: Some( + Array( + ArrayExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 23", + end: "line: 4, column: 31", + source: "[\"host\"]", + }, + }, + lbrack: [], + elements: [ + ArrayItem { + expression: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 24", + end: "line: 4, column: 30", + source: "\"host\"", + }, + }, + value: "host", + }, + ), + comma: [], + }, + ], + rbrack: [], + }, + ), + ), + comma: [], + }, + Property { base: BaseNode { - location: loc.get(4, 60, 4, 71), - ..BaseNode::default() - }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(4, 60, 4, 61), - ..BaseNode::default() + location: SourceLocation { + start: "line: 4, column: 33", + end: "line: 4, column: 71", + source: "fn: (a,b) => a[\"_field\"] + b[\"_field\"]", }, - name: "b".to_string() - }), - lbrack: vec![], - property: PropertyKey::StringLit(StringLit { - base: BaseNode { - location: loc.get(4, 62, 4, 70), - ..BaseNode::default() + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 33", + end: "line: 4, column: 35", + source: "fn", + }, + }, + name: "fn", }, - value: "_field".to_string() - }), - rbrack: vec![], - })) - } - ))), - }))), - comma: vec![], - } - ], - rbrace: vec![], - }))], - rparen: vec![], - })) - })) + ), + separator: [], + value: Some( + Function( + FunctionExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 37", + end: "line: 4, column: 71", + source: "(a,b) => a[\"_field\"] + b[\"_field\"]", + }, + }, + lparen: [], + params: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 38", + end: "line: 4, column: 39", + source: "a", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 38", + end: "line: 4, column: 39", + source: "a", + }, + }, + name: "a", + }, + ), + separator: [], + value: None, + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 40", + end: "line: 4, column: 41", + source: "b", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 40", + end: "line: 4, column: 41", + source: "b", + }, + }, + name: "b", + }, + ), + separator: [], + value: None, + comma: [], + }, + ], + rparen: [], + arrow: [], + body: Expr( + Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 46", + end: "line: 4, column: 71", + source: "a[\"_field\"] + b[\"_field\"]", + }, + }, + operator: AdditionOperator, + left: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 46", + end: "line: 4, column: 57", + source: "a[\"_field\"]", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 46", + end: "line: 4, column: 47", + source: "a", + }, + }, + name: "a", + }, + ), + lbrack: [], + property: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 48", + end: "line: 4, column: 56", + source: "\"_field\"", + }, + }, + value: "_field", + }, + ), + rbrack: [], + }, + ), + right: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 60", + end: "line: 4, column: 71", + source: "b[\"_field\"]", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 60", + end: "line: 4, column: 61", + source: "b", + }, + }, + name: "b", + }, + ), + lbrack: [], + property: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 62", + end: "line: 4, column: 70", + source: "\"_field\"", + }, + }, + value: "_field", + }, + ), + rbrack: [], + }, + ), + }, + ), + ), + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], + }, + ), + }, + ), ], - eof: vec![], - }, - ) + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] @@ -1650,738 +2660,1215 @@ b = from(bucket:"Flux/autogen") join(tables:[a,b], on:["t1"], fn: (a,b) => (a["_field"] - b["_field"]) / b["_field"])"#, ); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - let stmt_a = Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(2, 1, 4, 21), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(2, 1, 2, 2), - ..BaseNode::default() - }, - name: "a".to_string(), - }, - init: Expression::PipeExpr(Box::new(PipeExpr { + expect![[r#" + File { base: BaseNode { - location: loc.get(2, 5, 4, 21), - ..BaseNode::default() - }, - argument: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(2, 5, 3, 48), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 1", + end: "line: 10, column: 86", + source: "a = from(bucket:\"Flux/autogen\")\n\t|> filter(fn: (r) => r[\"_measurement\"] == \"a\")\n\t|> range(start:-1h)\n\nb = from(bucket:\"Flux/autogen\")\n\t|> filter(fn: (r) => r[\"_measurement\"] == \"b\")\n\t|> range(start:-1h)\n\njoin(tables:[a,b], on:[\"t1\"], fn: (a,b) => (a[\"_field\"] - b[\"_field\"]) / b[\"_field\"])", }, - argument: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(2, 5, 2, 32), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 5, 2, 9), - ..BaseNode::default() - }, - name: "from".to_string(), - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { + }, + name: "", + metadata: "parser-type=rust", + package: None, + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(2, 10, 2, 31), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![Property { - base: BaseNode { - location: loc.get(2, 10, 2, 31), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 1", + end: "line: 4, column: 21", + source: "a = from(bucket:\"Flux/autogen\")\n\t|> filter(fn: (r) => r[\"_measurement\"] == \"a\")\n\t|> range(start:-1h)", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 10, 2, 16), - ..BaseNode::default() - }, - name: "bucket".to_string(), - }), - separator: vec![], - value: Some(Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(2, 17, 2, 31), - ..BaseNode::default() - }, - value: "Flux/autogen".to_string(), - })), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - })), - call: CallExpr { - base: BaseNode { - location: loc.get(3, 5, 3, 48), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(3, 5, 3, 11), - ..BaseNode::default() }, - name: "filter".to_string(), - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(3, 12, 3, 47), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![Property { + id: Identifier { base: BaseNode { - location: loc.get(3, 12, 3, 47), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(3, 12, 3, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 1", + end: "line: 2, column: 2", + source: "a", }, - name: "fn".to_string(), - }), - separator: vec![], - value: Some(Expression::Function(Box::new(FunctionExpr { + }, + name: "a", + }, + init: PipeExpr( + PipeExpr { base: BaseNode { - location: loc.get(3, 16, 3, 47), - ..BaseNode::default() - }, - lparen: vec![], - params: vec![Property { - base: BaseNode { - location: loc.get(3, 17, 3, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 5", + end: "line: 4, column: 21", + source: "from(bucket:\"Flux/autogen\")\n\t|> filter(fn: (r) => r[\"_measurement\"] == \"a\")\n\t|> range(start:-1h)", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(3, 17, 3, 18), - ..BaseNode::default() - }, - name: "r".to_string(), - }), - separator: vec![], - value: None, - comma: vec![], - }], - rparen: vec![], - arrow: vec![], - body: FunctionBody::Expr(Expression::Binary(Box::new( - BinaryExpr { + }, + argument: PipeExpr( + PipeExpr { base: BaseNode { - location: loc.get(3, 23, 3, 47), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 5", + end: "line: 3, column: 48", + source: "from(bucket:\"Flux/autogen\")\n\t|> filter(fn: (r) => r[\"_measurement\"] == \"a\")", + }, }, - operator: Operator::EqualOperator, - left: Expression::Member(Box::new(MemberExpr { + argument: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 5", + end: "line: 2, column: 32", + source: "from(bucket:\"Flux/autogen\")", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 5", + end: "line: 2, column: 9", + source: "from", + }, + }, + name: "from", + }, + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 10", + end: "line: 2, column: 31", + source: "bucket:\"Flux/autogen\"", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 10", + end: "line: 2, column: 31", + source: "bucket:\"Flux/autogen\"", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 10", + end: "line: 2, column: 16", + source: "bucket", + }, + }, + name: "bucket", + }, + ), + separator: [], + value: Some( + StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 17", + end: "line: 2, column: 31", + source: "\"Flux/autogen\"", + }, + }, + value: "Flux/autogen", + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], + }, + ), + call: CallExpr { base: BaseNode { - location: loc.get(3, 23, 3, 40), - ..BaseNode::default() + location: SourceLocation { + start: "line: 3, column: 5", + end: "line: 3, column: 48", + source: "filter(fn: (r) => r[\"_measurement\"] == \"a\")", + }, }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(3, 23, 3, 24), - ..BaseNode::default() + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 5", + end: "line: 3, column: 11", + source: "filter", + }, + }, + name: "filter", }, - name: "r".to_string(), - }), - lbrack: vec![], - property: PropertyKey::StringLit(StringLit { + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 12", + end: "line: 3, column: 47", + source: "fn: (r) => r[\"_measurement\"] == \"a\"", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 12", + end: "line: 3, column: 47", + source: "fn: (r) => r[\"_measurement\"] == \"a\"", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 12", + end: "line: 3, column: 14", + source: "fn", + }, + }, + name: "fn", + }, + ), + separator: [], + value: Some( + Function( + FunctionExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 16", + end: "line: 3, column: 47", + source: "(r) => r[\"_measurement\"] == \"a\"", + }, + }, + lparen: [], + params: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 17", + end: "line: 3, column: 18", + source: "r", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 17", + end: "line: 3, column: 18", + source: "r", + }, + }, + name: "r", + }, + ), + separator: [], + value: None, + comma: [], + }, + ], + rparen: [], + arrow: [], + body: Expr( + Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 23", + end: "line: 3, column: 47", + source: "r[\"_measurement\"] == \"a\"", + }, + }, + operator: EqualOperator, + left: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 23", + end: "line: 3, column: 40", + source: "r[\"_measurement\"]", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 23", + end: "line: 3, column: 24", + source: "r", + }, + }, + name: "r", + }, + ), + lbrack: [], + property: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 25", + end: "line: 3, column: 39", + source: "\"_measurement\"", + }, + }, + value: "_measurement", + }, + ), + rbrack: [], + }, + ), + right: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 44", + end: "line: 3, column: 47", + source: "\"a\"", + }, + }, + value: "a", + }, + ), + }, + ), + ), + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], + }, + }, + ), + call: CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 5", + end: "line: 4, column: 21", + source: "range(start:-1h)", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 5", + end: "line: 4, column: 10", + source: "range", + }, + }, + name: "range", + }, + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { base: BaseNode { - location: loc.get(3, 25, 3, 39), - ..BaseNode::default() + location: SourceLocation { + start: "line: 4, column: 11", + end: "line: 4, column: 20", + source: "start:-1h", + }, }, - value: "_measurement".to_string(), - }), - rbrack: vec![], - })), - right: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(3, 44, 3, 47), - ..BaseNode::default() + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 11", + end: "line: 4, column: 20", + source: "start:-1h", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 11", + end: "line: 4, column: 16", + source: "start", + }, + }, + name: "start", + }, + ), + separator: [], + value: Some( + Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 17", + end: "line: 4, column: 20", + source: "-1h", + }, + }, + operator: SubtractionOperator, + argument: Duration( + DurationLit { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 18", + end: "line: 4, column: 20", + source: "1h", + }, + }, + values: [ + Duration { + magnitude: 1, + unit: "h", + }, + ], + }, + ), + }, + ), + ), + comma: [], + }, + ], + rbrace: [], }, - value: "a".to_string(), - }), - }, - ))), - }))), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - }, - })), - call: CallExpr { - base: BaseNode { - location: loc.get(4, 5, 4, 21), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(4, 5, 4, 10), - ..BaseNode::default() - }, - name: "range".to_string(), - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(4, 11, 4, 20), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![Property { - base: BaseNode { - location: loc.get(4, 11, 4, 20), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(4, 11, 4, 16), - ..BaseNode::default() - }, - name: "start".to_string(), - }), - separator: vec![], - value: Some(Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(4, 17, 4, 20), - ..BaseNode::default() - }, - operator: Operator::SubtractionOperator, - argument: Expression::Duration(DurationLit { - base: BaseNode { - location: loc.get(4, 18, 4, 20), - ..BaseNode::default() + ), + ], + rparen: [], }, - values: vec![Duration { - magnitude: 1, - unit: "h".to_string(), - }], - }), - }))), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - }, - })), - })); - - let stmt_b = Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(6, 1, 8, 21), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(6, 1, 6, 2), - ..BaseNode::default() - }, - name: "b".to_string(), - }, - init: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(6, 5, 8, 21), - ..BaseNode::default() - }, - argument: Expression::PipeExpr(Box::new(PipeExpr { - base: BaseNode { - location: loc.get(6, 5, 7, 48), - ..BaseNode::default() - }, - argument: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(6, 5, 6, 32), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(6, 5, 6, 9), - ..BaseNode::default() - }, - name: "from".to_string(), - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(6, 10, 6, 31), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![Property { - base: BaseNode { - location: loc.get(6, 10, 6, 31), - ..BaseNode::default() }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(6, 10, 6, 16), - ..BaseNode::default() - }, - name: "bucket".to_string(), - }), - separator: vec![], - value: Some(Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(6, 17, 6, 31), - ..BaseNode::default() - }, - value: "Flux/autogen".to_string(), - })), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - })), - call: CallExpr { - base: BaseNode { - location: loc.get(7, 5, 7, 48), - ..BaseNode::default() + ), }, - callee: Expression::Identifier(Identifier { + ), + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(7, 5, 7, 11), - ..BaseNode::default() - }, - name: "filter".to_string(), - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(7, 12, 7, 47), - ..BaseNode::default() + location: SourceLocation { + start: "line: 6, column: 1", + end: "line: 8, column: 21", + source: "b = from(bucket:\"Flux/autogen\")\n\t|> filter(fn: (r) => r[\"_measurement\"] == \"b\")\n\t|> range(start:-1h)", + }, }, - lbrace: vec![], - with: None, - properties: vec![Property { + id: Identifier { base: BaseNode { - location: loc.get(7, 12, 7, 47), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(7, 12, 7, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 6, column: 1", + end: "line: 6, column: 2", + source: "b", }, - name: "fn".to_string(), - }), - separator: vec![], - value: Some(Expression::Function(Box::new(FunctionExpr { + }, + name: "b", + }, + init: PipeExpr( + PipeExpr { base: BaseNode { - location: loc.get(7, 16, 7, 47), - ..BaseNode::default() - }, - lparen: vec![], - params: vec![Property { - base: BaseNode { - location: loc.get(7, 17, 7, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 6, column: 5", + end: "line: 8, column: 21", + source: "from(bucket:\"Flux/autogen\")\n\t|> filter(fn: (r) => r[\"_measurement\"] == \"b\")\n\t|> range(start:-1h)", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(7, 17, 7, 18), - ..BaseNode::default() - }, - name: "r".to_string(), - }), - separator: vec![], - value: None, - comma: vec![], - }], - rparen: vec![], - arrow: vec![], - body: FunctionBody::Expr(Expression::Binary(Box::new( - BinaryExpr { + }, + argument: PipeExpr( + PipeExpr { base: BaseNode { - location: loc.get(7, 23, 7, 47), - ..BaseNode::default() - }, - operator: Operator::EqualOperator, - left: Expression::Member(Box::new(MemberExpr { - base: BaseNode { - location: loc.get(7, 23, 7, 40), - ..BaseNode::default() + location: SourceLocation { + start: "line: 6, column: 5", + end: "line: 7, column: 48", + source: "from(bucket:\"Flux/autogen\")\n\t|> filter(fn: (r) => r[\"_measurement\"] == \"b\")", }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(7, 23, 7, 24), - ..BaseNode::default() - }, - name: "r".to_string(), - }), - lbrack: vec![], - property: PropertyKey::StringLit(StringLit { + }, + argument: Call( + CallExpr { base: BaseNode { - location: loc.get(7, 25, 7, 39), - ..BaseNode::default() + location: SourceLocation { + start: "line: 6, column: 5", + end: "line: 6, column: 32", + source: "from(bucket:\"Flux/autogen\")", + }, }, - value: "_measurement".to_string(), - }), - rbrack: vec![], - })), - right: Expression::StringLit(StringLit { + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 6, column: 5", + end: "line: 6, column: 9", + source: "from", + }, + }, + name: "from", + }, + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 6, column: 10", + end: "line: 6, column: 31", + source: "bucket:\"Flux/autogen\"", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 6, column: 10", + end: "line: 6, column: 31", + source: "bucket:\"Flux/autogen\"", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 6, column: 10", + end: "line: 6, column: 16", + source: "bucket", + }, + }, + name: "bucket", + }, + ), + separator: [], + value: Some( + StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 6, column: 17", + end: "line: 6, column: 31", + source: "\"Flux/autogen\"", + }, + }, + value: "Flux/autogen", + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], + }, + ), + call: CallExpr { base: BaseNode { - location: loc.get(7, 44, 7, 47), - ..BaseNode::default() + location: SourceLocation { + start: "line: 7, column: 5", + end: "line: 7, column: 48", + source: "filter(fn: (r) => r[\"_measurement\"] == \"b\")", + }, }, - value: "b".to_string(), - }), + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 7, column: 5", + end: "line: 7, column: 11", + source: "filter", + }, + }, + name: "filter", + }, + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 7, column: 12", + end: "line: 7, column: 47", + source: "fn: (r) => r[\"_measurement\"] == \"b\"", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 7, column: 12", + end: "line: 7, column: 47", + source: "fn: (r) => r[\"_measurement\"] == \"b\"", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 7, column: 12", + end: "line: 7, column: 14", + source: "fn", + }, + }, + name: "fn", + }, + ), + separator: [], + value: Some( + Function( + FunctionExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 7, column: 16", + end: "line: 7, column: 47", + source: "(r) => r[\"_measurement\"] == \"b\"", + }, + }, + lparen: [], + params: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 7, column: 17", + end: "line: 7, column: 18", + source: "r", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 7, column: 17", + end: "line: 7, column: 18", + source: "r", + }, + }, + name: "r", + }, + ), + separator: [], + value: None, + comma: [], + }, + ], + rparen: [], + arrow: [], + body: Expr( + Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 7, column: 23", + end: "line: 7, column: 47", + source: "r[\"_measurement\"] == \"b\"", + }, + }, + operator: EqualOperator, + left: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 7, column: 23", + end: "line: 7, column: 40", + source: "r[\"_measurement\"]", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 7, column: 23", + end: "line: 7, column: 24", + source: "r", + }, + }, + name: "r", + }, + ), + lbrack: [], + property: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 7, column: 25", + end: "line: 7, column: 39", + source: "\"_measurement\"", + }, + }, + value: "_measurement", + }, + ), + rbrack: [], + }, + ), + right: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 7, column: 44", + end: "line: 7, column: 47", + source: "\"b\"", + }, + }, + value: "b", + }, + ), + }, + ), + ), + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], + }, }, - ))), - }))), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - }, - })), - call: CallExpr { - base: BaseNode { - location: loc.get(8, 5, 8, 21), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(8, 5, 8, 10), - ..BaseNode::default() - }, - name: "range".to_string(), - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(8, 11, 8, 20), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![Property { - base: BaseNode { - location: loc.get(8, 11, 8, 20), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(8, 11, 8, 16), - ..BaseNode::default() - }, - name: "start".to_string(), - }), - separator: vec![], - value: Some(Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(8, 17, 8, 20), - ..BaseNode::default() - }, - operator: Operator::SubtractionOperator, - argument: Expression::Duration(DurationLit { - base: BaseNode { - location: loc.get(8, 18, 8, 20), - ..BaseNode::default() - }, - values: vec![Duration { - magnitude: 1, - unit: "h".to_string(), - }], - }), - }))), - comma: vec![], - }], - rbrace: vec![], - }))], - rparen: vec![], - }, - })), - })); - - let stmt_expr = Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(10, 1, 10, 86), - ..BaseNode::default() - }, - expression: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(10, 1, 10, 86), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(10, 1, 10, 5), - ..BaseNode::default() - }, - name: "join".to_string(), - }), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(10, 6, 10, 85), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![ - Property { - base: BaseNode { - location: loc.get(10, 6, 10, 18), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(10, 6, 10, 12), - ..BaseNode::default() - }, - name: "tables".to_string(), - }), - separator: vec![], - value: Some(Expression::Array(Box::new(ArrayExpr { - base: BaseNode { - location: loc.get(10, 13, 10, 18), - ..BaseNode::default() - }, - lbrack: vec![], - elements: vec![ - ArrayItem { - expression: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(10, 14, 10, 15), - ..BaseNode::default() + ), + call: CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 8, column: 5", + end: "line: 8, column: 21", + source: "range(start:-1h)", }, - name: "a".to_string(), - }), - comma: vec![], - }, - ArrayItem { - expression: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(10, 16, 10, 17), - ..BaseNode::default() + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 8, column: 5", + end: "line: 8, column: 10", + source: "range", + }, + }, + name: "range", }, - name: "b".to_string(), - }), - comma: vec![], + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 8, column: 11", + end: "line: 8, column: 20", + source: "start:-1h", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 8, column: 11", + end: "line: 8, column: 20", + source: "start:-1h", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 8, column: 11", + end: "line: 8, column: 16", + source: "start", + }, + }, + name: "start", + }, + ), + separator: [], + value: Some( + Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 8, column: 17", + end: "line: 8, column: 20", + source: "-1h", + }, + }, + operator: SubtractionOperator, + argument: Duration( + DurationLit { + base: BaseNode { + location: SourceLocation { + start: "line: 8, column: 18", + end: "line: 8, column: 20", + source: "1h", + }, + }, + values: [ + Duration { + magnitude: 1, + unit: "h", + }, + ], + }, + ), + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], }, - ], - rbrack: vec![], - }))), - comma: vec![], - }, - Property { - base: BaseNode { - location: loc.get(10, 20, 10, 29), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(10, 20, 10, 22), - ..BaseNode::default() - }, - name: "on".to_string(), - }), - separator: vec![], - value: Some(Expression::Array(Box::new(ArrayExpr { - base: BaseNode { - location: loc.get(10, 23, 10, 29), - ..BaseNode::default() }, - lbrack: vec![], - elements: vec![ArrayItem { - expression: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(10, 24, 10, 28), - ..BaseNode::default() - }, - value: "t1".to_string(), - }), - comma: vec![], - }], - rbrack: vec![], - }))), - comma: vec![], + ), }, - Property { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(10, 31, 10, 85), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(10, 31, 10, 33), - ..BaseNode::default() + location: SourceLocation { + start: "line: 10, column: 1", + end: "line: 10, column: 86", + source: "join(tables:[a,b], on:[\"t1\"], fn: (a,b) => (a[\"_field\"] - b[\"_field\"]) / b[\"_field\"])", }, - name: "fn".to_string(), - }), - separator: vec![], - value: Some(Expression::Function(Box::new(FunctionExpr { - base: BaseNode { - location: loc.get(10, 35, 10, 85), - ..BaseNode::default() - }, - lparen: vec![], - params: vec![ - Property { - base: BaseNode { - location: loc.get(10, 36, 10, 37), - ..BaseNode::default() + }, + expression: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 1", + end: "line: 10, column: 86", + source: "join(tables:[a,b], on:[\"t1\"], fn: (a,b) => (a[\"_field\"] - b[\"_field\"]) / b[\"_field\"])", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(10, 36, 10, 37), - ..BaseNode::default() - }, - name: "a".to_string(), - }), - separator: vec![], - value: None, - comma: vec![], }, - Property { - base: BaseNode { - location: loc.get(10, 38, 10, 39), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { + callee: Identifier( + Identifier { base: BaseNode { - location: loc.get(10, 38, 10, 39), - ..BaseNode::default() + location: SourceLocation { + start: "line: 10, column: 1", + end: "line: 10, column: 5", + source: "join", + }, }, - name: "b".to_string(), - }), - separator: vec![], - value: None, - comma: vec![], - }, - ], - rparen: vec![], - arrow: vec![], - body: FunctionBody::Expr(Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(10, 44, 10, 85), - ..BaseNode::default() - }, - operator: Operator::DivisionOperator, - left: Expression::Paren(Box::new(ParenExpr { - base: BaseNode { - location: loc.get(10, 44, 10, 71), - ..BaseNode::default() + name: "join", }, - lparen: vec![], - expression: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(10, 45, 10, 70), - ..BaseNode::default() - }, - operator: Operator::SubtractionOperator, - left: Expression::Member(Box::new(MemberExpr { + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { base: BaseNode { - location: loc.get(10, 45, 10, 56), - ..BaseNode::default() - }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(10, 45, 10, 46), - ..BaseNode::default() + location: SourceLocation { + start: "line: 10, column: 6", + end: "line: 10, column: 85", + source: "tables:[a,b], on:[\"t1\"], fn: (a,b) => (a[\"_field\"] - b[\"_field\"]) / b[\"_field\"]", }, - name: "a".to_string(), - }), - lbrack: vec![], - property: PropertyKey::StringLit(StringLit { - base: BaseNode { - location: loc.get(10, 47, 10, 55), - ..BaseNode::default() - }, - value: "_field".to_string(), - }), - rbrack: vec![], - })), - right: Expression::Member(Box::new(MemberExpr { - base: BaseNode { - location: loc.get(10, 59, 10, 70), - ..BaseNode::default() }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(10, 59, 10, 60), - ..BaseNode::default() + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 6", + end: "line: 10, column: 18", + source: "tables:[a,b]", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 6", + end: "line: 10, column: 12", + source: "tables", + }, + }, + name: "tables", + }, + ), + separator: [], + value: Some( + Array( + ArrayExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 13", + end: "line: 10, column: 18", + source: "[a,b]", + }, + }, + lbrack: [], + elements: [ + ArrayItem { + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 14", + end: "line: 10, column: 15", + source: "a", + }, + }, + name: "a", + }, + ), + comma: [], + }, + ArrayItem { + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 16", + end: "line: 10, column: 17", + source: "b", + }, + }, + name: "b", + }, + ), + comma: [], + }, + ], + rbrack: [], + }, + ), + ), + comma: [], }, - name: "b".to_string(), - }), - lbrack: vec![], - property: PropertyKey::StringLit(StringLit { - base: BaseNode { - location: loc.get(10, 61, 10, 69), - ..BaseNode::default() + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 20", + end: "line: 10, column: 29", + source: "on:[\"t1\"]", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 20", + end: "line: 10, column: 22", + source: "on", + }, + }, + name: "on", + }, + ), + separator: [], + value: Some( + Array( + ArrayExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 23", + end: "line: 10, column: 29", + source: "[\"t1\"]", + }, + }, + lbrack: [], + elements: [ + ArrayItem { + expression: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 24", + end: "line: 10, column: 28", + source: "\"t1\"", + }, + }, + value: "t1", + }, + ), + comma: [], + }, + ], + rbrack: [], + }, + ), + ), + comma: [], }, - value: "_field".to_string(), - }), - rbrack: vec![], - })), - })), - rparen: vec![], - })), - right: Expression::Member(Box::new(MemberExpr { - base: BaseNode { - location: loc.get(10, 74, 10, 85), - ..BaseNode::default() - }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(10, 74, 10, 75), - ..BaseNode::default() - }, - name: "b".to_string(), - }), - lbrack: vec![], - property: PropertyKey::StringLit(StringLit { - base: BaseNode { - location: loc.get(10, 76, 10, 84), - ..BaseNode::default() + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 31", + end: "line: 10, column: 85", + source: "fn: (a,b) => (a[\"_field\"] - b[\"_field\"]) / b[\"_field\"]", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 31", + end: "line: 10, column: 33", + source: "fn", + }, + }, + name: "fn", + }, + ), + separator: [], + value: Some( + Function( + FunctionExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 35", + end: "line: 10, column: 85", + source: "(a,b) => (a[\"_field\"] - b[\"_field\"]) / b[\"_field\"]", + }, + }, + lparen: [], + params: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 36", + end: "line: 10, column: 37", + source: "a", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 36", + end: "line: 10, column: 37", + source: "a", + }, + }, + name: "a", + }, + ), + separator: [], + value: None, + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 38", + end: "line: 10, column: 39", + source: "b", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 38", + end: "line: 10, column: 39", + source: "b", + }, + }, + name: "b", + }, + ), + separator: [], + value: None, + comma: [], + }, + ], + rparen: [], + arrow: [], + body: Expr( + Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 44", + end: "line: 10, column: 85", + source: "(a[\"_field\"] - b[\"_field\"]) / b[\"_field\"]", + }, + }, + operator: DivisionOperator, + left: Paren( + ParenExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 44", + end: "line: 10, column: 71", + source: "(a[\"_field\"] - b[\"_field\"])", + }, + }, + lparen: [], + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 45", + end: "line: 10, column: 70", + source: "a[\"_field\"] - b[\"_field\"]", + }, + }, + operator: SubtractionOperator, + left: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 45", + end: "line: 10, column: 56", + source: "a[\"_field\"]", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 45", + end: "line: 10, column: 46", + source: "a", + }, + }, + name: "a", + }, + ), + lbrack: [], + property: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 47", + end: "line: 10, column: 55", + source: "\"_field\"", + }, + }, + value: "_field", + }, + ), + rbrack: [], + }, + ), + right: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 59", + end: "line: 10, column: 70", + source: "b[\"_field\"]", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 59", + end: "line: 10, column: 60", + source: "b", + }, + }, + name: "b", + }, + ), + lbrack: [], + property: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 61", + end: "line: 10, column: 69", + source: "\"_field\"", + }, + }, + value: "_field", + }, + ), + rbrack: [], + }, + ), + }, + ), + rparen: [], + }, + ), + right: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 74", + end: "line: 10, column: 85", + source: "b[\"_field\"]", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 74", + end: "line: 10, column: 75", + source: "b", + }, + }, + name: "b", + }, + ), + lbrack: [], + property: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 10, column: 76", + end: "line: 10, column: 84", + source: "\"_field\"", + }, + }, + value: "_field", + }, + ), + rbrack: [], + }, + ), + }, + ), + ), + }, + ), + ), + comma: [], + }, + ], + rbrace: [], }, - value: "_field".to_string(), - }), - rbrack: vec![], - })), - }))), - }))), - comma: vec![], + ), + ], + rparen: [], + }, + ), }, - ], - rbrace: vec![], - }))], - rparen: vec![], - })), - })); - - assert_eq!( - parsed, - File { - base: BaseNode { - location: loc.get(2, 1, 10, 86), - ..BaseNode::default() - }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), - package: None, - imports: vec![], - body: vec![stmt_a, stmt_b, stmt_expr], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } diff --git a/libflux/flux-core/src/parser/tests/literals.rs b/libflux/flux-core/src/parser/tests/literals.rs index 32074a4f2c..b50202272f 100644 --- a/libflux/flux-core/src/parser/tests/literals.rs +++ b/libflux/flux-core/src/parser/tests/literals.rs @@ -1,759 +1,1034 @@ -use pretty_assertions::assert_eq; - use super::*; -use crate::ast::tests::Locator; #[test] fn regex_literal() { let mut p = Parser::new(r#"/.*/"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "/.*/", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() - }, - expression: Expression::Regexp(RegexpLit { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "/.*/", + }, + }, + expression: Regexp( + RegexpLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "/.*/", + }, + }, + value: ".*", + }, + ), }, - value: ".*".to_string() - }) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn regex_literal_with_escape_sequence() { let mut p = Parser::new(r#"/a\/b\\c\d/"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "/a\\/b\\\\c\\d/", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - expression: Expression::Regexp(RegexpLit { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "/a\\/b\\\\c\\d/", + }, + }, + expression: Regexp( + RegexpLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "/a\\/b\\\\c\\d/", + }, + }, + value: "a/b\\\\c\\d", + }, + ), }, - value: r#"a/b\\c\d"#.to_string() - }) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn regex_literal_with_hex_escape() { let mut p = Parser::new(r#"/^\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e(ZZ)?$/"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 46), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 46", + source: "/^\\xe6\\x97\\xa5\\xe6\\x9c\\xac\\xe8\\xaa\\x9e(ZZ)?$/", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 46), - ..BaseNode::default() - }, - expression: Expression::Regexp(RegexpLit { - base: BaseNode { - location: loc.get(1, 1, 1, 46), - ..BaseNode::default() + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 46", + source: "/^\\xe6\\x97\\xa5\\xe6\\x9c\\xac\\xe8\\xaa\\x9e(ZZ)?$/", + }, + }, + expression: Regexp( + RegexpLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 46", + source: "/^\\xe6\\x97\\xa5\\xe6\\x9c\\xac\\xe8\\xaa\\x9e(ZZ)?$/", + }, + }, + value: "^日本語(ZZ)?$", + }, + ), }, - value: r#"^日本語(ZZ)?$"#.to_string() - }) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] fn regex_literal_empty_pattern() { let mut p = Parser::new(r#"/(:?)/"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "/(:?)/", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() - }, - expression: Expression::Regexp(RegexpLit { - base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "/(:?)/", + }, + }, + expression: Regexp( + RegexpLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "/(:?)/", + }, + }, + value: "(:?)", + }, + ), }, - value: r#"(:?)"#.to_string() - }) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn bad_regex_literal() { let mut p = Parser::new(r#"/*/"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "/*/", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() - }, - expression: Expression::Regexp(RegexpLit { - base: BaseNode { - location: loc.get(1, 1, 1, 4), - errors: vec![ - "regex parse error: * error: repetition operator missing expression" - .to_string() - ], - ..BaseNode::default() + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "/*/", + }, + }, + expression: Regexp( + RegexpLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "/*/", + }, + errors: [ + "regex parse error: * error: repetition operator missing expression", + ], + }, + value: "", + }, + ), }, - value: "".to_string() - }) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] fn duration_literal_all_units() { let mut p = Parser::new(r#"dur = 1y3mo2w1d4h1m30s1ms2µs70ns"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 34), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 34", + source: "dur = 1y3mo2w1d4h1m30s1ms2µs70ns", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 34), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() - }, - name: "dur".to_string() - }, - init: Expression::Duration(DurationLit { - base: BaseNode { - location: loc.get(1, 7, 1, 34), - ..BaseNode::default() - }, - values: vec![ - Duration { - magnitude: 1, - unit: "y".to_string() - }, - Duration { - magnitude: 3, - unit: "mo".to_string() - }, - Duration { - magnitude: 2, - unit: "w".to_string() - }, - Duration { - magnitude: 1, - unit: "d".to_string() - }, - Duration { - magnitude: 4, - unit: "h".to_string() - }, - Duration { - magnitude: 1, - unit: "m".to_string() - }, - Duration { - magnitude: 30, - unit: "s".to_string() - }, - Duration { - magnitude: 1, - unit: "ms".to_string() + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 34", + source: "dur = 1y3mo2w1d4h1m30s1ms2µs70ns", + }, }, - Duration { - magnitude: 2, - unit: "us".to_string() + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "dur", + }, + }, + name: "dur", }, - Duration { - magnitude: 70, - unit: "ns".to_string() - } - ] - }) - }))], - eof: vec![], - }, - ) + init: Duration( + DurationLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 34", + source: "1y3mo2w1d4h1m30s1ms2µs70ns", + }, + }, + values: [ + Duration { + magnitude: 1, + unit: "y", + }, + Duration { + magnitude: 3, + unit: "mo", + }, + Duration { + magnitude: 2, + unit: "w", + }, + Duration { + magnitude: 1, + unit: "d", + }, + Duration { + magnitude: 4, + unit: "h", + }, + Duration { + magnitude: 1, + unit: "m", + }, + Duration { + magnitude: 30, + unit: "s", + }, + Duration { + magnitude: 1, + unit: "ms", + }, + Duration { + magnitude: 2, + unit: "us", + }, + Duration { + magnitude: 70, + unit: "ns", + }, + ], + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn duration_literal_leading_zero() { let mut p = Parser::new(r#"dur = 01y02mo03w04d05h06m07s08ms09µs010ns"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 43), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 43", + source: "dur = 01y02mo03w04d05h06m07s08ms09µs010ns", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 43), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() - }, - name: "dur".to_string() - }, - init: Expression::Duration(DurationLit { - base: BaseNode { - location: loc.get(1, 7, 1, 43), - ..BaseNode::default() - }, - values: vec![ - Duration { - magnitude: 1, - unit: "y".to_string() - }, - Duration { - magnitude: 2, - unit: "mo".to_string() - }, - Duration { - magnitude: 3, - unit: "w".to_string() - }, - Duration { - magnitude: 4, - unit: "d".to_string() - }, - Duration { - magnitude: 5, - unit: "h".to_string() - }, - Duration { - magnitude: 6, - unit: "m".to_string() - }, - Duration { - magnitude: 7, - unit: "s".to_string() - }, - Duration { - magnitude: 8, - unit: "ms".to_string() + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 43", + source: "dur = 01y02mo03w04d05h06m07s08ms09µs010ns", + }, }, - Duration { - magnitude: 9, - unit: "us".to_string() + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "dur", + }, + }, + name: "dur", }, - Duration { - magnitude: 10, - unit: "ns".to_string() - } - ] - }) - }))], - eof: vec![], - }, - ) + init: Duration( + DurationLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 43", + source: "01y02mo03w04d05h06m07s08ms09µs010ns", + }, + }, + values: [ + Duration { + magnitude: 1, + unit: "y", + }, + Duration { + magnitude: 2, + unit: "mo", + }, + Duration { + magnitude: 3, + unit: "w", + }, + Duration { + magnitude: 4, + unit: "d", + }, + Duration { + magnitude: 5, + unit: "h", + }, + Duration { + magnitude: 6, + unit: "m", + }, + Duration { + magnitude: 7, + unit: "s", + }, + Duration { + magnitude: 8, + unit: "ms", + }, + Duration { + magnitude: 9, + unit: "us", + }, + Duration { + magnitude: 10, + unit: "ns", + }, + ], + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn duration_literal_months() { let mut p = Parser::new(r#"dur = 6mo"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 10", + source: "dur = 6mo", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 10), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() - }, - name: "dur".to_string() - }, - init: Expression::Duration(DurationLit { - base: BaseNode { - location: loc.get(1, 7, 1, 10), - ..BaseNode::default() + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 10", + source: "dur = 6mo", + }, + }, + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "dur", + }, + }, + name: "dur", + }, + init: Duration( + DurationLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 10", + source: "6mo", + }, + }, + values: [ + Duration { + magnitude: 6, + unit: "mo", + }, + ], + }, + ), }, - values: vec![Duration { - magnitude: 6, - unit: "mo".to_string() - }] - }) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn duration_literal_milliseconds() { let mut p = Parser::new(r#"dur = 500ms"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "dur = 500ms", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() - }, - name: "dur".to_string() - }, - init: Expression::Duration(DurationLit { - base: BaseNode { - location: loc.get(1, 7, 1, 12), - ..BaseNode::default() + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "dur = 500ms", + }, + }, + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "dur", + }, + }, + name: "dur", + }, + init: Duration( + DurationLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 12", + source: "500ms", + }, + }, + values: [ + Duration { + magnitude: 500, + unit: "ms", + }, + ], + }, + ), }, - values: vec![Duration { - magnitude: 500, - unit: "ms".to_string() - }] - }) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn duration_literal_months_minutes_milliseconds() { let mut p = Parser::new(r#"dur = 6mo30m500ms"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "dur = 6mo30m500ms", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 18), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() - }, - name: "dur".to_string() - }, - init: Expression::Duration(DurationLit { - base: BaseNode { - location: loc.get(1, 7, 1, 18), - ..BaseNode::default() - }, - values: vec![ - Duration { - magnitude: 6, - unit: "mo".to_string() + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "dur = 6mo30m500ms", + }, }, - Duration { - magnitude: 30, - unit: "m".to_string() + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "dur", + }, + }, + name: "dur", }, - Duration { - magnitude: 500, - unit: "ms".to_string() - } - ] - }) - }))], - eof: vec![], - }, - ) + init: Duration( + DurationLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 18", + source: "6mo30m500ms", + }, + }, + values: [ + Duration { + magnitude: 6, + unit: "mo", + }, + Duration { + magnitude: 30, + unit: "m", + }, + Duration { + magnitude: 500, + unit: "ms", + }, + ], + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn date_literal_in_the_default_location() { let mut p = Parser::new(r#"now = 2018-11-29"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 17), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 17", + source: "now = 2018-11-29", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 17), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() - }, - name: "now".to_string() - }, - init: Expression::DateTime(DateTimeLit { - base: BaseNode { - location: loc.get(1, 7, 1, 17), - ..BaseNode::default() + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 17", + source: "now = 2018-11-29", + }, + }, + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "now", + }, + }, + name: "now", + }, + init: DateTime( + DateTimeLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 17", + source: "2018-11-29", + }, + }, + value: 2018-11-29T00:00:00+00:00, + }, + ), }, - value: chrono::DateTime::parse_from_rfc3339("2018-11-29T00:00:00Z").unwrap() - }) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn date_time_literal_arg() { let mut p = Parser::new(r#"range(start: 2018-11-29T09:00:00Z)"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 35), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 35", + source: "range(start: 2018-11-29T09:00:00Z)", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 35), - ..BaseNode::default() - }, - expression: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 35), - errors: vec![], - ..BaseNode::default() - }, - arguments: vec![Expression::Object(Box::new(ObjectExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 7, 1, 34), - ..BaseNode::default() - }, - lbrace: vec![], - rbrace: vec![], - with: None, - properties: vec![Property { - base: BaseNode { - location: loc.get(1, 7, 1, 34), - errors: vec![], - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 35", + source: "range(start: 2018-11-29T09:00:00Z)", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 7, 1, 12), - ..BaseNode::default() - }, - name: "start".to_string(), - }), - comma: vec![], - separator: vec![], - value: Some(Expression::DateTime(DateTimeLit { + }, + expression: Call( + CallExpr { base: BaseNode { - location: loc.get(1, 14, 1, 34), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 35", + source: "range(start: 2018-11-29T09:00:00Z)", + }, }, - value: chrono::DateTime::parse_from_rfc3339("2018-11-29T09:00:00Z") - .unwrap() - })), - }], - }))], - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - name: "range".to_string(), - }), - lparen: vec![], - rparen: vec![], - })) - }))], - eof: vec![], - }, - ) + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "range", + }, + }, + name: "range", + }, + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 34", + source: "start: 2018-11-29T09:00:00Z", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 34", + source: "start: 2018-11-29T09:00:00Z", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 12", + source: "start", + }, + }, + name: "start", + }, + ), + separator: [], + value: Some( + DateTime( + DateTimeLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 34", + source: "2018-11-29T09:00:00Z", + }, + }, + value: 2018-11-29T09:00:00+00:00, + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], + }, + ), + }, + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] fn date_time_literal_no_offset_error() { let mut p = Parser::new(r#"t = 2018-11-29T09:00:00"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 24), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 24", + source: "t = 2018-11-29T09:00:00", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 24), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "t".to_string(), - }, - init: Expression::Bad(Box::new(BadExpr { - base: BaseNode { - location: loc.get(1, 5, 1, 24), - ..BaseNode::default() + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 24", + source: "t = 2018-11-29T09:00:00", + }, + }, + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "t", + }, + }, + name: "t", + }, + init: Bad( + BadExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 24", + source: "2018-11-29T09:00:00", + }, + }, + text: "invalid date time literal, missing time offset", + expression: None, + }, + ), }, - text: "invalid date time literal, missing time offset".to_string(), - expression: None - })), - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn date_time_literal() { let mut p = Parser::new(r#"now = 2018-11-29T09:00:00Z"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 27), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 27", + source: "now = 2018-11-29T09:00:00Z", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 27), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() - }, - name: "now".to_string() - }, - init: Expression::DateTime(DateTimeLit { - base: BaseNode { - location: loc.get(1, 7, 1, 27), - ..BaseNode::default() + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 27", + source: "now = 2018-11-29T09:00:00Z", + }, + }, + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "now", + }, + }, + name: "now", + }, + init: DateTime( + DateTimeLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 27", + source: "2018-11-29T09:00:00Z", + }, + }, + value: 2018-11-29T09:00:00+00:00, + }, + ), }, - value: chrono::DateTime::parse_from_rfc3339("2018-11-29T09:00:00Z").unwrap() - }) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn date_time_literal_with_fractional_seconds() { let mut p = Parser::new(r#"now = 2018-11-29T09:00:00.100000000Z"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 37), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 37", + source: "now = 2018-11-29T09:00:00.100000000Z", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 37), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() - }, - name: "now".to_string() - }, - init: Expression::DateTime(DateTimeLit { - base: BaseNode { - location: loc.get(1, 7, 1, 37), - ..BaseNode::default() + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 37", + source: "now = 2018-11-29T09:00:00.100000000Z", + }, + }, + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "now", + }, + }, + name: "now", + }, + init: DateTime( + DateTimeLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 37", + source: "2018-11-29T09:00:00.100000000Z", + }, + }, + value: 2018-11-29T09:00:00.100+00:00, + }, + ), }, - value: chrono::DateTime::parse_from_rfc3339("2018-11-29T09:00:00.100000000Z") - .unwrap() - }) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn integer_literal_overflow() { let mut p = Parser::new(r#"100000000000000000000000000000"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 31), - .. BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 31", + source: "100000000000000000000000000000", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 31), - .. BaseNode::default() }, - expression: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 1, 1, 31), - errors: vec!["invalid integer literal \"100000000000000000000000000000\": value out of range".to_string()], - .. BaseNode::default() + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 31", + source: "100000000000000000000000000000", + }, + }, + expression: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 31", + source: "100000000000000000000000000000", + }, + errors: [ + "invalid integer literal \"100000000000000000000000000000\": value out of range", + ], + }, + value: 0, + }, + ), }, - value: 0, - }) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } diff --git a/libflux/flux-core/src/parser/tests/objects.rs b/libflux/flux-core/src/parser/tests/objects.rs index 471d977bf6..35e756868e 100644 --- a/libflux/flux-core/src/parser/tests/objects.rs +++ b/libflux/flux-core/src/parser/tests/objects.rs @@ -1,7 +1,4 @@ -use pretty_assertions::assert_eq; - use super::*; -use crate::ast::tests::Locator; #[test] fn map_member_expressions() { @@ -12,378 +9,577 @@ fn map_member_expressions() { "#, ); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 3, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 3, column: 13", + source: "m = {key1: 1, key2:\"value2\"}\n\t\t\tm.key1\n\t\t\tm[\"key2\"]", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![ - Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 29), - ..BaseNode::default() - }, - id: Identifier { + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 29", + source: "m = {key1: 1, key2:\"value2\"}", + }, }, - name: "m".to_string() - }, - init: Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 5, 1, 29), - ..BaseNode::default() + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "m", + }, + }, + name: "m", }, - lbrace: vec![], - with: None, - properties: vec![ - Property { + init: Object( + ObjectExpr { base: BaseNode { - location: loc.get(1, 6, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 29", + source: "{key1: 1, key2:\"value2\"}", + }, }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 6, 1, 10), - ..BaseNode::default() + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 13", + source: "key1: 1", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 10", + source: "key1", + }, + }, + name: "key1", + }, + ), + separator: [], + value: Some( + Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 13", + source: "1", + }, + }, + value: 1, + }, + ), + ), + comma: [], }, - name: "key1".to_string() - }), - separator: vec![], - value: Some(Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 12, 1, 13), - ..BaseNode::default() + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 28", + source: "key2:\"value2\"", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 19", + source: "key2", + }, + }, + name: "key2", + }, + ), + separator: [], + value: Some( + StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 20", + end: "line: 1, column: 28", + source: "\"value2\"", + }, + }, + value: "value2", + }, + ), + ), + comma: [], }, - value: 1 - })), - comma: vec![], + ], + rbrace: [], }, - Property { + ), + }, + ), + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 10", + source: "m.key1", + }, + }, + expression: Member( + MemberExpr { base: BaseNode { - location: loc.get(1, 15, 1, 28), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 10", + source: "m.key1", + }, }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 15, 1, 19), - ..BaseNode::default() + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 5", + source: "m", + }, + }, + name: "m", }, - name: "key2".to_string() - }), - separator: vec![], - value: Some(Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 20, 1, 28), - ..BaseNode::default() + ), + lbrack: [], + property: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 6", + end: "line: 2, column: 10", + source: "key1", + }, + }, + name: "key1", }, - value: "value2".to_string() - })), - comma: vec![], - } - ], - rbrace: vec![], - })) - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(2, 4, 2, 10), - ..BaseNode::default() - }, - expression: Expression::Member(Box::new(MemberExpr { - base: BaseNode { - location: loc.get(2, 4, 2, 10), - ..BaseNode::default() - }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 4, 2, 5), - ..BaseNode::default() - }, - name: "m".to_string() - }), - lbrack: vec![], - property: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 6, 2, 10), - ..BaseNode::default() + ), + rbrack: [], }, - name: "key1".to_string() - }), - rbrack: vec![], - })) - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(3, 4, 3, 13), - ..BaseNode::default() + ), }, - expression: Expression::Member(Box::new(MemberExpr { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(3, 4, 3, 13), - ..BaseNode::default() - }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(3, 4, 3, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 3, column: 4", + end: "line: 3, column: 13", + source: "m[\"key2\"]", }, - name: "m".to_string() - }), - lbrack: vec![], - property: PropertyKey::StringLit(StringLit { - base: BaseNode { - location: loc.get(3, 6, 3, 12), - ..BaseNode::default() + }, + expression: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 4", + end: "line: 3, column: 13", + source: "m[\"key2\"]", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 4", + end: "line: 3, column: 5", + source: "m", + }, + }, + name: "m", + }, + ), + lbrack: [], + property: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 6", + end: "line: 3, column: 12", + source: "\"key2\"", + }, + }, + value: "key2", + }, + ), + rbrack: [], }, - value: "key2".to_string() - }), - rbrack: vec![], - })) - })) + ), + }, + ), ], - eof: vec![], - }, - ) + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn object_with_string_literal_key() { let mut p = Parser::new(r#"x = {"a": 10}"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 14", + source: "x = {\"a\": 10}", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 14), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "x".to_string() - }, - init: Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 5, 1, 14), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![Property { + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(1, 6, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 14", + source: "x = {\"a\": 10}", + }, }, - key: PropertyKey::StringLit(StringLit { + id: Identifier { base: BaseNode { - location: loc.get(1, 6, 1, 9), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "x", + }, }, - value: "a".to_string() - }), - separator: vec![], - value: Some(Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 11, 1, 13), - ..BaseNode::default() + name: "x", + }, + init: Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 14", + source: "{\"a\": 10}", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 13", + source: "\"a\": 10", + }, + }, + key: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 9", + source: "\"a\"", + }, + }, + value: "a", + }, + ), + separator: [], + value: Some( + Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 13", + source: "10", + }, + }, + value: 10, + }, + ), + ), + comma: [], + }, + ], + rbrace: [], }, - value: 10 - })), - comma: vec![], - }], - rbrace: vec![], - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn object_with_mixed_keys() { let mut p = Parser::new(r#"x = {"a": 10, b: 11}"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 21), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 21", + source: "x = {\"a\": 10, b: 11}", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 21), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "x".to_string() - }, - init: Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 5, 1, 21), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![ - Property { - base: BaseNode { - location: loc.get(1, 6, 1, 13), - ..BaseNode::default() + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 21", + source: "x = {\"a\": 10, b: 11}", }, - key: PropertyKey::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 6, 1, 9), - ..BaseNode::default() - }, - value: "a".to_string() - }), - separator: vec![], - value: Some(Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 11, 1, 13), - ..BaseNode::default() - }, - value: 10 - })), - comma: vec![], }, - Property { + id: Identifier { base: BaseNode { - location: loc.get(1, 15, 1, 20), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 15, 1, 16), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "x", }, - name: "b".to_string() - }), - separator: vec![], - value: Some(Expression::Integer(IntegerLit { + }, + name: "x", + }, + init: Object( + ObjectExpr { base: BaseNode { - location: loc.get(1, 18, 1, 20), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 21", + source: "{\"a\": 10, b: 11}", + }, }, - value: 11 - })), - comma: vec![], - } - ], - rbrace: vec![], - })) - }))], - eof: vec![], - }, - ) + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 13", + source: "\"a\": 10", + }, + }, + key: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 9", + source: "\"a\"", + }, + }, + value: "a", + }, + ), + separator: [], + value: Some( + Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 13", + source: "10", + }, + }, + value: 10, + }, + ), + ), + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 20", + source: "b: 11", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 16", + source: "b", + }, + }, + name: "b", + }, + ), + separator: [], + value: Some( + Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 18", + end: "line: 1, column: 20", + source: "11", + }, + }, + value: 11, + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn implicit_key_object_literal() { let mut p = Parser::new(r#"x = {a, b}"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 11), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 11", + source: "x = {a, b}", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 11), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "x".to_string() - }, - init: Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 5, 1, 11), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![ - Property { - base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 11", + source: "x = {a, b}", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() - }, - name: "a".to_string() - }), - separator: vec![], - value: None, - comma: vec![], }, - Property { + id: Identifier { base: BaseNode { - location: loc.get(1, 9, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "x", + }, }, - key: PropertyKey::Identifier(Identifier { + name: "x", + }, + init: Object( + ObjectExpr { base: BaseNode { - location: loc.get(1, 9, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 11", + source: "{a, b}", + }, }, - name: "b".to_string() - }), - separator: vec![], - value: None, - comma: vec![], - } - ], - rbrace: vec![], - })) - }))], - eof: vec![], - }, - ) + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "a", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "a", + }, + }, + name: "a", + }, + ), + separator: [], + value: None, + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 10", + source: "b", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 10", + source: "b", + }, + }, + name: "b", + }, + ), + separator: [], + value: None, + comma: [], + }, + ], + rbrace: [], + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } // TODO(affo): that error is injected by ast.Check(). @@ -391,78 +587,110 @@ fn implicit_key_object_literal() { fn implicit_key_object_literal_error() { let mut p = Parser::new(r#"x = {"a", b}"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "x = {\"a\", b}", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 13), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "x".to_string() - }, - init: Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 5, 1, 13), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![ - Property { - // TODO(affo): this should error with ast.Check: "string literal key "a" must have a value". - base: BaseNode { - location: loc.get(1, 6, 1, 9), - ..BaseNode::default() + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "x = {\"a\", b}", }, - key: PropertyKey::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 6, 1, 9), - ..BaseNode::default() - }, - value: "a".to_string() - }), - separator: vec![], - value: None, - comma: vec![], }, - Property { + id: Identifier { base: BaseNode { - location: loc.get(1, 11, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "x", + }, }, - key: PropertyKey::Identifier(Identifier { + name: "x", + }, + init: Object( + ObjectExpr { base: BaseNode { - location: loc.get(1, 11, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 13", + source: "{\"a\", b}", + }, }, - name: "b".to_string() - }), - separator: vec![], - value: None, - comma: vec![], - } - ], - rbrace: vec![], - })) - }))], - eof: vec![], - }, - ) + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 9", + source: "\"a\"", + }, + }, + key: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 9", + source: "\"a\"", + }, + }, + value: "a", + }, + ), + separator: [], + value: None, + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 12", + source: "b", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 12", + source: "b", + }, + }, + name: "b", + }, + ), + separator: [], + value: None, + comma: [], + }, + ], + rbrace: [], + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } // TODO(affo): that error is injected by ast.Check(). @@ -470,252 +698,375 @@ fn implicit_key_object_literal_error() { fn implicit_and_explicit_keys_object_literal_error() { let mut p = Parser::new(r#"x = {a, b:c}"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "x = {a, b:c}", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 13), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "x".to_string() - }, - init: Expression::Object(Box::new(ObjectExpr { - // TODO(affo): this should error in ast.Check(): "cannot mix implicit and explicit properties". - base: BaseNode { - location: loc.get(1, 5, 1, 13), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![ - Property { - base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "x = {a, b:c}", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() - }, - name: "a".to_string() - }), - separator: vec![], - value: None, - comma: vec![], }, - Property { + id: Identifier { base: BaseNode { - location: loc.get(1, 9, 1, 12), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 9, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "x", }, - name: "b".to_string() - }), - separator: vec![], - value: Some(Expression::Identifier(Identifier { + }, + name: "x", + }, + init: Object( + ObjectExpr { base: BaseNode { - location: loc.get(1, 11, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 13", + source: "{a, b:c}", + }, }, - name: "c".to_string() - })), - comma: vec![], - } - ], - rbrace: vec![], - })) - }))], - eof: vec![], - }, - ) + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "a", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "a", + }, + }, + name: "a", + }, + ), + separator: [], + value: None, + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 12", + source: "b:c", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 10", + source: "b", + }, + }, + name: "b", + }, + ), + separator: [], + value: Some( + Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 12", + source: "c", + }, + }, + name: "c", + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn object_with() { let mut p = Parser::new(r#"{a with b:c, d:e}"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "{a with b:c, d:e}", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 18), - ..BaseNode::default() - }, - expression: Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 18), - ..BaseNode::default() - }, - lbrace: vec![], - with: Some(WithSource { - source: Identifier { - base: BaseNode { - location: loc.get(1, 2, 1, 3), - ..BaseNode::default() + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "{a with b:c, d:e}", }, - name: "a".to_string() }, - with: vec![] - }), - properties: vec![ - Property { - base: BaseNode { - location: loc.get(1, 9, 1, 12), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 9, 1, 10), - ..BaseNode::default() - }, - name: "b".to_string() - }), - separator: vec![], - value: Some(Expression::Identifier(Identifier { + expression: Object( + ObjectExpr { base: BaseNode { - location: loc.get(1, 11, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "{a with b:c, d:e}", + }, }, - name: "c".to_string() - })), - comma: vec![], - }, - Property { - base: BaseNode { - location: loc.get(1, 14, 1, 17), - ..BaseNode::default() + lbrace: [], + with: Some( + WithSource { + source: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 3", + source: "a", + }, + }, + name: "a", + }, + with: [], + }, + ), + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 12", + source: "b:c", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 10", + source: "b", + }, + }, + name: "b", + }, + ), + separator: [], + value: Some( + Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 12", + source: "c", + }, + }, + name: "c", + }, + ), + ), + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 17", + source: "d:e", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 15", + source: "d", + }, + }, + name: "d", + }, + ), + separator: [], + value: Some( + Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 16", + end: "line: 1, column: 17", + source: "e", + }, + }, + name: "e", + }, + ), + ), + comma: [], + }, + ], + rbrace: [], }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 14, 1, 15), - ..BaseNode::default() - }, - name: "d".to_string() - }), - separator: vec![], - value: Some(Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 16, 1, 17), - ..BaseNode::default() - }, - name: "e".to_string() - })), - comma: vec![], - } - ], - rbrace: vec![], - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn object_with_implicit_keys() { let mut p = Parser::new(r#"{a with b, c}"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 14", + source: "{a with b, c}", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 14), - ..BaseNode::default() - }, - expression: Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 14), - ..BaseNode::default() - }, - lbrace: vec![], - with: Some(WithSource { - source: Identifier { - base: BaseNode { - location: loc.get(1, 2, 1, 3), - ..BaseNode::default() + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 14", + source: "{a with b, c}", }, - name: "a".to_string() }, - with: vec![], - }), - properties: vec![ - Property { - base: BaseNode { - location: loc.get(1, 9, 1, 10), - ..BaseNode::default() - }, - key: PropertyKey::Identifier(Identifier { + expression: Object( + ObjectExpr { base: BaseNode { - location: loc.get(1, 9, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 14", + source: "{a with b, c}", + }, }, - name: "b".to_string() - }), - separator: vec![], - value: None, - comma: vec![], - }, - Property { - base: BaseNode { - location: loc.get(1, 12, 1, 13), - ..BaseNode::default() + lbrace: [], + with: Some( + WithSource { + source: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 3", + source: "a", + }, + }, + name: "a", + }, + with: [], + }, + ), + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 10", + source: "b", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 10", + source: "b", + }, + }, + name: "b", + }, + ), + separator: [], + value: None, + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 13", + source: "c", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 13", + source: "c", + }, + }, + name: "c", + }, + ), + separator: [], + value: None, + comma: [], + }, + ], + rbrace: [], }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 12, 1, 13), - ..BaseNode::default() - }, - name: "c".to_string() - }), - separator: vec![], - value: None, - comma: vec![], - } - ], - rbrace: vec![], - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } diff --git a/libflux/flux-core/src/parser/tests/operator_precedence.rs b/libflux/flux-core/src/parser/tests/operator_precedence.rs index 8faa86b493..631c0f89c5 100644 --- a/libflux/flux-core/src/parser/tests/operator_precedence.rs +++ b/libflux/flux-core/src/parser/tests/operator_precedence.rs @@ -1,588 +1,906 @@ -use pretty_assertions::assert_eq; - use super::*; -use crate::ast::tests::Locator; #[test] fn binary_operator_precedence() { let mut p = Parser::new(r#"a / b - 1.0"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "a / b - 1.0", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - expression: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - operator: Operator::SubtractionOperator, - left: Expression::Binary(Box::new(BinaryExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - operator: Operator::DivisionOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "a".to_string() - }), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 5, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "a / b - 1.0", }, - name: "b".to_string() - }) - })), - right: Expression::Float(FloatLit { - base: BaseNode { - location: loc.get(1, 9, 1, 12), - ..BaseNode::default() }, - value: 1.0 - }) - })) - }))], - eof: vec![], - }, - ) + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "a / b - 1.0", + }, + }, + operator: SubtractionOperator, + left: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "a / b", + }, + }, + operator: DivisionOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, + }, + name: "a", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 6", + source: "b", + }, + }, + name: "b", + }, + ), + }, + ), + right: Float( + FloatLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 12", + source: "1.0", + }, + }, + value: 1.0, + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn binary_operator_precedence_literals_only() { let mut p = Parser::new(r#"2 / "a" - 1.0"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 14", + source: "2 / \"a\" - 1.0", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 14), - ..BaseNode::default() - }, - expression: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 14), - ..BaseNode::default() - }, - operator: Operator::SubtractionOperator, - left: Expression::Binary(Box::new(BinaryExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 8), - ..BaseNode::default() - }, - operator: Operator::DivisionOperator, - left: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 14", + source: "2 / \"a\" - 1.0", }, - value: 2 - }), - right: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 5, 1, 8), - ..BaseNode::default() - }, - value: "a".to_string() - }) - })), - right: Expression::Float(FloatLit { - base: BaseNode { - location: loc.get(1, 11, 1, 14), - ..BaseNode::default() }, - value: 1.0 - }) - })) - }))], - eof: vec![], - }, - ) + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 14", + source: "2 / \"a\" - 1.0", + }, + }, + operator: SubtractionOperator, + left: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 8", + source: "2 / \"a\"", + }, + }, + operator: DivisionOperator, + left: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "2", + }, + }, + value: 2, + }, + ), + right: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 8", + source: "\"a\"", + }, + }, + value: "a", + }, + ), + }, + ), + right: Float( + FloatLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 14", + source: "1.0", + }, + }, + value: 1.0, + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn binary_operator_precedence_double_subtraction() { let mut p = Parser::new(r#"1 - 2 - 3"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 10", + source: "1 - 2 - 3", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 10), - ..BaseNode::default() - }, - expression: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 10), - ..BaseNode::default() - }, - operator: Operator::SubtractionOperator, - left: Expression::Binary(Box::new(BinaryExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - operator: Operator::SubtractionOperator, - left: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - value: 1 - }), - right: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 5, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 10", + source: "1 - 2 - 3", }, - value: 2 - }) - })), - right: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 9, 1, 10), - ..BaseNode::default() }, - value: 3 - }) - })) - }))], - eof: vec![], - }, - ) + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 10", + source: "1 - 2 - 3", + }, + }, + operator: SubtractionOperator, + left: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "1 - 2", + }, + }, + operator: SubtractionOperator, + left: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "1", + }, + }, + value: 1, + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 6", + source: "2", + }, + }, + value: 2, + }, + ), + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 10", + source: "3", + }, + }, + value: 3, + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn binary_operator_precedence_double_subtraction_with_parens() { let mut p = Parser::new(r#"1 - (2 - 3)"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "1 - (2 - 3)", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - expression: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - operator: Operator::SubtractionOperator, - left: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - value: 1 - }), - right: Expression::Paren(Box::new(ParenExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 5, 1, 12), - ..BaseNode::default() - }, - lparen: vec![], - expression: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 6, 1, 11), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "1 - (2 - 3)", }, - operator: Operator::SubtractionOperator, - left: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() - }, - value: 2 - }), - right: Expression::Integer(IntegerLit { + }, + expression: Binary( + BinaryExpr { base: BaseNode { - location: loc.get(1, 10, 1, 11), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "1 - (2 - 3)", + }, }, - value: 3 - }) - })), - rparen: vec![], - })) - })) - }))], - eof: vec![], - }, - ) + operator: SubtractionOperator, + left: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "1", + }, + }, + value: 1, + }, + ), + right: Paren( + ParenExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 12", + source: "(2 - 3)", + }, + }, + lparen: [], + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 11", + source: "2 - 3", + }, + }, + operator: SubtractionOperator, + left: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "2", + }, + }, + value: 2, + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 11", + source: "3", + }, + }, + value: 3, + }, + ), + }, + ), + rparen: [], + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn binary_operator_precedence_double_sum() { let mut p = Parser::new(r#"1 + 2 + 3"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 10", + source: "1 + 2 + 3", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 10), - ..BaseNode::default() - }, - expression: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 10), - ..BaseNode::default() - }, - operator: Operator::AdditionOperator, - left: Expression::Binary(Box::new(BinaryExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - operator: Operator::AdditionOperator, - left: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - value: 1 - }), - right: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 5, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 10", + source: "1 + 2 + 3", }, - value: 2 - }) - })), - right: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 9, 1, 10), - ..BaseNode::default() }, - value: 3 - }) - })) - }))], - eof: vec![], - }, - ) + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 10", + source: "1 + 2 + 3", + }, + }, + operator: AdditionOperator, + left: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "1 + 2", + }, + }, + operator: AdditionOperator, + left: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "1", + }, + }, + value: 1, + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 6", + source: "2", + }, + }, + value: 2, + }, + ), + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 10", + source: "3", + }, + }, + value: 3, + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn binary_operator_precedence_exponent() { let mut p = Parser::new(r#"5 * 1 ^ 5"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 10", + source: "5 * 1 ^ 5", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 10), - ..BaseNode::default() - }, - expression: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 10), - ..BaseNode::default() - }, - operator: Operator::MultiplicationOperator, - left: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - value: 5 - }), - right: Expression::Binary(Box::new(BinaryExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 5, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 10", + source: "5 * 1 ^ 5", + }, }, - operator: Operator::PowerOperator, - left: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 5, 1, 6), - ..BaseNode::default() + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 10", + source: "5 * 1 ^ 5", + }, + }, + operator: MultiplicationOperator, + left: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "5", + }, + }, + value: 5, + }, + ), + right: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 10", + source: "1 ^ 5", + }, + }, + operator: PowerOperator, + left: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 6", + source: "1", + }, + }, + value: 1, + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 10", + source: "5", + }, + }, + value: 5, + }, + ), + }, + ), }, - value: 1 - }), - right: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 9, 1, 10), - ..BaseNode::default() - }, - value: 5 - }) - })), - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn binary_operator_precedence_double_sum_with_parens() { let mut p = Parser::new(r#"1 + (2 + 3)"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "1 + (2 + 3)", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - expression: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - operator: Operator::AdditionOperator, - left: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - value: 1 - }), - right: Expression::Paren(Box::new(ParenExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 5, 1, 12), - ..BaseNode::default() - }, - lparen: vec![], - expression: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 6, 1, 11), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "1 + (2 + 3)", }, - operator: Operator::AdditionOperator, - left: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() - }, - value: 2 - }), - right: Expression::Integer(IntegerLit { + }, + expression: Binary( + BinaryExpr { base: BaseNode { - location: loc.get(1, 10, 1, 11), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "1 + (2 + 3)", + }, }, - value: 3 - }) - })), - rparen: vec![], - })) - })) - }))], - eof: vec![], - }, - ) + operator: AdditionOperator, + left: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "1", + }, + }, + value: 1, + }, + ), + right: Paren( + ParenExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 12", + source: "(2 + 3)", + }, + }, + lparen: [], + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 11", + source: "2 + 3", + }, + }, + operator: AdditionOperator, + left: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "2", + }, + }, + value: 2, + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 11", + source: "3", + }, + }, + value: 3, + }, + ), + }, + ), + rparen: [], + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn binary_operator_precedence_exponent_with_parens() { let mut p = Parser::new(r#"2 ^ (1 + 3)"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "2 ^ (1 + 3)", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - expression: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - operator: Operator::PowerOperator, - left: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - value: 2 - }), - right: Expression::Paren(Box::new(ParenExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 5, 1, 12), - ..BaseNode::default() - }, - lparen: vec![], - expression: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 6, 1, 11), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "2 ^ (1 + 3)", }, - operator: Operator::AdditionOperator, - left: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() - }, - value: 1 - }), - right: Expression::Integer(IntegerLit { + }, + expression: Binary( + BinaryExpr { base: BaseNode { - location: loc.get(1, 10, 1, 11), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "2 ^ (1 + 3)", + }, }, - value: 3 - }) - })), - rparen: vec![], - })) - })) - }))], - eof: vec![], - }, - ) + operator: PowerOperator, + left: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "2", + }, + }, + value: 2, + }, + ), + right: Paren( + ParenExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 12", + source: "(1 + 3)", + }, + }, + lparen: [], + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 11", + source: "1 + 3", + }, + }, + operator: AdditionOperator, + left: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "1", + }, + }, + value: 1, + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 11", + source: "3", + }, + }, + value: 3, + }, + ), + }, + ), + rparen: [], + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn logical_unary_operator_precedence() { let mut p = Parser::new(r#"not -1 == a"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "not -1 == a", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - expression: Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - operator: Operator::NotOperator, - argument: Expression::Binary(Box::new(BinaryExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 5, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "not -1 == a", + }, }, - operator: Operator::EqualOperator, - left: Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(1, 5, 1, 7), - ..BaseNode::default() - }, - operator: Operator::SubtractionOperator, - argument: Expression::Integer(IntegerLit { + expression: Unary( + UnaryExpr { base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "not -1 == a", + }, }, - value: 1 - }) - })), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 11, 1, 12), - ..BaseNode::default() - }, - name: "a".to_string() - }) - })) - })) - }))], - eof: vec![], - }, - ) + operator: NotOperator, + argument: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 12", + source: "-1 == a", + }, + }, + operator: EqualOperator, + left: Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 7", + source: "-1", + }, + }, + operator: SubtractionOperator, + argument: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "1", + }, + }, + value: 1, + }, + ), + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 12", + source: "a", + }, + }, + name: "a", + }, + ), + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] @@ -592,1039 +910,1644 @@ fn all_operators_precedence() { k / l < m + n - o or p() <= q() or r >= s and not t =~ /a/ and u !~ /a/"#, ); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 2, 72), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 2, column: 72", + source: "a() == b.a + b.c * d < 100 and e != f[g] and h > i * j and\nk / l < m + n - o or p() <= q() or r >= s and not t =~ /a/ and u !~ /a/", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 2, 72), - ..BaseNode::default() - }, - expression: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(1, 1, 2, 72), - ..BaseNode::default() - }, - operator: LogicalOperator::OrOperator, - left: Expression::Logical(Box::new(LogicalExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 2, 32), - ..BaseNode::default() - }, - operator: LogicalOperator::OrOperator, - left: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(1, 1, 2, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 2, column: 72", + source: "a() == b.a + b.c * d < 100 and e != f[g] and h > i * j and\nk / l < m + n - o or p() <= q() or r >= s and not t =~ /a/ and u !~ /a/", }, - operator: LogicalOperator::AndOperator, - left: Expression::Logical(Box::new(LogicalExpr { + }, + expression: Logical( + LogicalExpr { base: BaseNode { - location: loc.get(1, 1, 1, 55), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 2, column: 72", + source: "a() == b.a + b.c * d < 100 and e != f[g] and h > i * j and\nk / l < m + n - o or p() <= q() or r >= s and not t =~ /a/ and u !~ /a/", + }, }, - operator: LogicalOperator::AndOperator, - left: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 41), - ..BaseNode::default() - }, - operator: LogicalOperator::AndOperator, - left: Expression::Binary(Box::new(BinaryExpr { + operator: OrOperator, + left: Logical( + LogicalExpr { base: BaseNode { - location: loc.get(1, 1, 1, 27), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 2, column: 32", + source: "a() == b.a + b.c * d < 100 and e != f[g] and h > i * j and\nk / l < m + n - o or p() <= q()", + }, }, - operator: Operator::LessThanOperator, - left: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 21), - ..BaseNode::default() - }, - operator: Operator::EqualOperator, - left: Expression::Call(Box::new(CallExpr { + operator: OrOperator, + left: Logical( + LogicalExpr { base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "a".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })), - right: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 8, 1, 21), - ..BaseNode::default() - }, - operator: Operator::AdditionOperator, - left: Expression::Member(Box::new(MemberExpr { - base: BaseNode { - location: loc.get(1, 8, 1, 11), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 2, column: 18", + source: "a() == b.a + b.c * d < 100 and e != f[g] and h > i * j and\nk / l < m + n - o", }, - object: Expression::Identifier(Identifier { + }, + operator: AndOperator, + left: Logical( + LogicalExpr { base: BaseNode { - location: loc.get(1, 8, 1, 9), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 55", + source: "a() == b.a + b.c * d < 100 and e != f[g] and h > i * j", + }, }, - name: "b".to_string() - }), - lbrack: vec![], - property: PropertyKey::Identifier(Identifier { + operator: AndOperator, + left: Logical( + LogicalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 41", + source: "a() == b.a + b.c * d < 100 and e != f[g]", + }, + }, + operator: AndOperator, + left: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 27", + source: "a() == b.a + b.c * d < 100", + }, + }, + operator: LessThanOperator, + left: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 21", + source: "a() == b.a + b.c * d", + }, + }, + operator: EqualOperator, + left: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "a()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, + }, + name: "a", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), + right: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 21", + source: "b.a + b.c * d", + }, + }, + operator: AdditionOperator, + left: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 11", + source: "b.a", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 9", + source: "b", + }, + }, + name: "b", + }, + ), + lbrack: [], + property: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 11", + source: "a", + }, + }, + name: "a", + }, + ), + rbrack: [], + }, + ), + right: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 21", + source: "b.c * d", + }, + }, + operator: MultiplicationOperator, + left: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 17", + source: "b.c", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 15", + source: "b", + }, + }, + name: "b", + }, + ), + lbrack: [], + property: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 16", + end: "line: 1, column: 17", + source: "c", + }, + }, + name: "c", + }, + ), + rbrack: [], + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 20", + end: "line: 1, column: 21", + source: "d", + }, + }, + name: "d", + }, + ), + }, + ), + }, + ), + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 24", + end: "line: 1, column: 27", + source: "100", + }, + }, + value: 100, + }, + ), + }, + ), + right: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 32", + end: "line: 1, column: 41", + source: "e != f[g]", + }, + }, + operator: NotEqualOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 32", + end: "line: 1, column: 33", + source: "e", + }, + }, + name: "e", + }, + ), + right: Index( + IndexExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 37", + end: "line: 1, column: 41", + source: "f[g]", + }, + }, + array: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 37", + end: "line: 1, column: 38", + source: "f", + }, + }, + name: "f", + }, + ), + lbrack: [], + index: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 39", + end: "line: 1, column: 40", + source: "g", + }, + }, + name: "g", + }, + ), + rbrack: [], + }, + ), + }, + ), + }, + ), + right: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 46", + end: "line: 1, column: 55", + source: "h > i * j", + }, + }, + operator: GreaterThanOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 46", + end: "line: 1, column: 47", + source: "h", + }, + }, + name: "h", + }, + ), + right: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 50", + end: "line: 1, column: 55", + source: "i * j", + }, + }, + operator: MultiplicationOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 50", + end: "line: 1, column: 51", + source: "i", + }, + }, + name: "i", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 54", + end: "line: 1, column: 55", + source: "j", + }, + }, + name: "j", + }, + ), + }, + ), + }, + ), + }, + ), + right: Binary( + BinaryExpr { base: BaseNode { - location: loc.get(1, 10, 1, 11), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 1", + end: "line: 2, column: 18", + source: "k / l < m + n - o", + }, }, - name: "a".to_string() - }), - rbrack: vec![], - })), - right: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 14, 1, 21), - ..BaseNode::default() - }, - operator: Operator::MultiplicationOperator, - left: Expression::Member(Box::new( - MemberExpr { - base: BaseNode { - location: loc.get(1, 14, 1, 17), - ..BaseNode::default() + operator: LessThanOperator, + left: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 1", + end: "line: 2, column: 6", + source: "k / l", + }, + }, + operator: DivisionOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 1", + end: "line: 2, column: 2", + source: "k", + }, + }, + name: "k", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 5", + end: "line: 2, column: 6", + source: "l", + }, + }, + name: "l", + }, + ), }, - object: Expression::Identifier( - Identifier { - base: BaseNode { - location: loc - .get(1, 14, 1, 15), - ..BaseNode::default() + ), + right: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 9", + end: "line: 2, column: 18", + source: "m + n - o", }, - name: "b".to_string() - } - ), - lbrack: vec![], - property: PropertyKey::Identifier( - Identifier { - base: BaseNode { - location: loc - .get(1, 16, 1, 17), - ..BaseNode::default() + }, + operator: SubtractionOperator, + left: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 9", + end: "line: 2, column: 14", + source: "m + n", + }, + }, + operator: AdditionOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 9", + end: "line: 2, column: 10", + source: "m", + }, + }, + name: "m", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 14", + source: "n", + }, + }, + name: "n", + }, + ), + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 17", + end: "line: 2, column: 18", + source: "o", + }, + }, + name: "o", + }, + ), + }, + ), + }, + ), + }, + ), + right: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 22", + end: "line: 2, column: 32", + source: "p() <= q()", + }, + }, + operator: LessThanEqualOperator, + left: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 22", + end: "line: 2, column: 25", + source: "p()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 22", + end: "line: 2, column: 23", + source: "p", }, - name: "c".to_string() - } - ), - rbrack: vec![], - } - )), - right: Expression::Identifier(Identifier { + }, + name: "p", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), + right: Call( + CallExpr { base: BaseNode { - location: loc.get(1, 20, 1, 21), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 29", + end: "line: 2, column: 32", + source: "q()", + }, }, - name: "d".to_string() - }) - })) - })) - })), - right: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 24, 1, 27), - ..BaseNode::default() - }, - value: 100 - }) - })), - right: Expression::Binary(Box::new(BinaryExpr { + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 29", + end: "line: 2, column: 30", + source: "q", + }, + }, + name: "q", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), + }, + ), + }, + ), + right: Logical( + LogicalExpr { base: BaseNode { - location: loc.get(1, 32, 1, 41), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 36", + end: "line: 2, column: 72", + source: "r >= s and not t =~ /a/ and u !~ /a/", + }, }, - operator: Operator::NotEqualOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 32, 1, 33), - ..BaseNode::default() - }, - name: "e".to_string() - }), - right: Expression::Index(Box::new(IndexExpr { - base: BaseNode { - location: loc.get(1, 37, 1, 41), - ..BaseNode::default() - }, - array: Expression::Identifier(Identifier { + operator: AndOperator, + left: Logical( + LogicalExpr { base: BaseNode { - location: loc.get(1, 37, 1, 38), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 36", + end: "line: 2, column: 59", + source: "r >= s and not t =~ /a/", + }, }, - name: "f".to_string() - }), - lbrack: vec![], - index: Expression::Identifier(Identifier { + operator: AndOperator, + left: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 36", + end: "line: 2, column: 42", + source: "r >= s", + }, + }, + operator: GreaterThanEqualOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 36", + end: "line: 2, column: 37", + source: "r", + }, + }, + name: "r", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 41", + end: "line: 2, column: 42", + source: "s", + }, + }, + name: "s", + }, + ), + }, + ), + right: Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 47", + end: "line: 2, column: 59", + source: "not t =~ /a/", + }, + }, + operator: NotOperator, + argument: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 51", + end: "line: 2, column: 59", + source: "t =~ /a/", + }, + }, + operator: RegexpMatchOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 51", + end: "line: 2, column: 52", + source: "t", + }, + }, + name: "t", + }, + ), + right: Regexp( + RegexpLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 56", + end: "line: 2, column: 59", + source: "/a/", + }, + }, + value: "a", + }, + ), + }, + ), + }, + ), + }, + ), + right: Binary( + BinaryExpr { base: BaseNode { - location: loc.get(1, 39, 1, 40), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 64", + end: "line: 2, column: 72", + source: "u !~ /a/", + }, }, - name: "g".to_string() - }), - rbrack: vec![], - })) - })) - })), - right: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 46, 1, 55), - ..BaseNode::default() - }, - operator: Operator::GreaterThanOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 46, 1, 47), - ..BaseNode::default() - }, - name: "h".to_string() - }), - right: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 50, 1, 55), - ..BaseNode::default() - }, - operator: Operator::MultiplicationOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 50, 1, 51), - ..BaseNode::default() - }, - name: "i".to_string() - }), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 54, 1, 55), - ..BaseNode::default() - }, - name: "j".to_string() - }) - })) - })) - })), - right: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(2, 1, 2, 18), - ..BaseNode::default() - }, - operator: Operator::LessThanOperator, - left: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(2, 1, 2, 6), - ..BaseNode::default() - }, - operator: Operator::DivisionOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 1, 2, 2), - ..BaseNode::default() - }, - name: "k".to_string() - }), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 5, 2, 6), - ..BaseNode::default() - }, - name: "l".to_string() - }) - })), - right: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(2, 9, 2, 18), - ..BaseNode::default() - }, - operator: Operator::SubtractionOperator, - left: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(2, 9, 2, 14), - ..BaseNode::default() - }, - operator: Operator::AdditionOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 9, 2, 10), - ..BaseNode::default() - }, - name: "m".to_string() - }), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 13, 2, 14), - ..BaseNode::default() - }, - name: "n".to_string() - }) - })), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 17, 2, 18), - ..BaseNode::default() - }, - name: "o".to_string() - }) - })) - })) - })), - right: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(2, 22, 2, 32), - ..BaseNode::default() - }, - operator: Operator::LessThanEqualOperator, - left: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(2, 22, 2, 25), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 22, 2, 23), - ..BaseNode::default() - }, - name: "p".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })), - right: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(2, 29, 2, 32), - ..BaseNode::default() - }, - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 29, 2, 30), - ..BaseNode::default() - }, - name: "q".to_string() - }), - lparen: vec![], - arguments: vec![], - rparen: vec![], - })) - })) - })), - right: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(2, 36, 2, 72), - ..BaseNode::default() - }, - operator: LogicalOperator::AndOperator, - left: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(2, 36, 2, 59), - ..BaseNode::default() - }, - operator: LogicalOperator::AndOperator, - left: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(2, 36, 2, 42), - ..BaseNode::default() - }, - operator: Operator::GreaterThanEqualOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 36, 2, 37), - ..BaseNode::default() - }, - name: "r".to_string() - }), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 41, 2, 42), - ..BaseNode::default() - }, - name: "s".to_string() - }) - })), - right: Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(2, 47, 2, 59), - ..BaseNode::default() - }, - operator: Operator::NotOperator, - argument: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(2, 51, 2, 59), - ..BaseNode::default() - }, - operator: Operator::RegexpMatchOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 51, 2, 52), - ..BaseNode::default() - }, - name: "t".to_string() - }), - right: Expression::Regexp(RegexpLit { - base: BaseNode { - location: loc.get(2, 56, 2, 59), - ..BaseNode::default() - }, - value: "a".to_string() - }) - })) - })) - })), - right: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(2, 64, 2, 72), - ..BaseNode::default() + operator: NotRegexpMatchOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 64", + end: "line: 2, column: 65", + source: "u", + }, + }, + name: "u", + }, + ), + right: Regexp( + RegexpLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 69", + end: "line: 2, column: 72", + source: "/a/", + }, + }, + value: "a", + }, + ), + }, + ), + }, + ), }, - operator: Operator::NotRegexpMatchOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 64, 2, 65), - ..BaseNode::default() - }, - name: "u".to_string() - }), - right: Expression::Regexp(RegexpLit { - base: BaseNode { - location: loc.get(2, 69, 2, 72), - ..BaseNode::default() - }, - value: "a".to_string() - }) - })) - })) - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] fn logical_operators_precedence_1() { let mut p = Parser::new(r#"not a or b"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 11), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 11", + source: "not a or b", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 11), - ..BaseNode::default() - }, - expression: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 11), - ..BaseNode::default() - }, - operator: LogicalOperator::OrOperator, - left: Expression::Unary(Box::new(UnaryExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - operator: Operator::NotOperator, - argument: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 5, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 11", + source: "not a or b", }, - name: "a".to_string() - }) - })), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 10, 1, 11), - ..BaseNode::default() }, - name: "b".to_string() - }) - })) - }))], - eof: vec![], - }, - ) + expression: Logical( + LogicalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 11", + source: "not a or b", + }, + }, + operator: OrOperator, + left: Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "not a", + }, + }, + operator: NotOperator, + argument: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 6", + source: "a", + }, + }, + name: "a", + }, + ), + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 11", + source: "b", + }, + }, + name: "b", + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn logical_operators_precedence_2() { let mut p = Parser::new(r#"a or not b"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 11), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 11", + source: "a or not b", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 11), - ..BaseNode::default() - }, - expression: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 11), - ..BaseNode::default() - }, - operator: LogicalOperator::OrOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "a".to_string() - }), - right: Expression::Unary(Box::new(UnaryExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 6, 1, 11), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 11", + source: "a or not b", + }, }, - operator: Operator::NotOperator, - argument: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 10, 1, 11), - ..BaseNode::default() - }, - name: "b".to_string() - }) - })) - })) - }))], - eof: vec![], - }, - ) + expression: Logical( + LogicalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 11", + source: "a or not b", + }, + }, + operator: OrOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, + }, + name: "a", + }, + ), + right: Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 11", + source: "not b", + }, + }, + operator: NotOperator, + argument: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 11", + source: "b", + }, + }, + name: "b", + }, + ), + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn logical_operators_precedence_3() { let mut p = Parser::new(r#"not a and b"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "not a and b", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - expression: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - operator: LogicalOperator::AndOperator, - left: Expression::Unary(Box::new(UnaryExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - operator: Operator::NotOperator, - argument: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 5, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "not a and b", }, - name: "a".to_string() - }) - })), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 11, 1, 12), - ..BaseNode::default() }, - name: "b".to_string() - }) - })) - }))], - eof: vec![], - }, - ) + expression: Logical( + LogicalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "not a and b", + }, + }, + operator: AndOperator, + left: Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "not a", + }, + }, + operator: NotOperator, + argument: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 6", + source: "a", + }, + }, + name: "a", + }, + ), + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 12", + source: "b", + }, + }, + name: "b", + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn logical_operators_precedence_4() { let mut p = Parser::new(r#"a and not b"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "a and not b", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - expression: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - operator: LogicalOperator::AndOperator, - left: Expression::Identifier(Identifier { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "a".to_string() - }), - right: Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(1, 7, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "a and not b", + }, }, - operator: Operator::NotOperator, - argument: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 11, 1, 12), - ..BaseNode::default() - }, - name: "b".to_string() - }) - })) - })) - }))], - eof: vec![], - }, - ) + expression: Logical( + LogicalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "a and not b", + }, + }, + operator: AndOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, + }, + name: "a", + }, + ), + right: Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 12", + source: "not b", + }, + }, + operator: NotOperator, + argument: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 12", + source: "b", + }, + }, + name: "b", + }, + ), + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn logical_operators_precedence_5() { let mut p = Parser::new(r#"a and b or c"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "a and b or c", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 13), - ..BaseNode::default() - }, - expression: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 13), - ..BaseNode::default() - }, - operator: LogicalOperator::OrOperator, - left: Expression::Logical(Box::new(LogicalExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 8), - ..BaseNode::default() - }, - operator: LogicalOperator::AndOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "a and b or c", }, - name: "a".to_string() - }), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 7, 1, 8), - ..BaseNode::default() - }, - name: "b".to_string() - }) - })), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 12, 1, 13), - ..BaseNode::default() }, - name: "c".to_string() - }) - })) - }))], - eof: vec![], - }, - ) + expression: Logical( + LogicalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "a and b or c", + }, + }, + operator: OrOperator, + left: Logical( + LogicalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 8", + source: "a and b", + }, + }, + operator: AndOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, + }, + name: "a", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 8", + source: "b", + }, + }, + name: "b", + }, + ), + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 13", + source: "c", + }, + }, + name: "c", + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn logical_operators_precedence_6() { let mut p = Parser::new(r#"a or b and c"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "a or b and c", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 13), - ..BaseNode::default() - }, - expression: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 13), - ..BaseNode::default() - }, - operator: LogicalOperator::OrOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "a".to_string() - }), - right: Expression::Logical(Box::new(LogicalExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 6, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "a or b and c", + }, }, - operator: LogicalOperator::AndOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() + expression: Logical( + LogicalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "a or b and c", + }, + }, + operator: OrOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, + }, + name: "a", + }, + ), + right: Logical( + LogicalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 13", + source: "b and c", + }, + }, + operator: AndOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "b", + }, + }, + name: "b", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 13", + source: "c", + }, + }, + name: "c", + }, + ), + }, + ), }, - name: "b".to_string() - }), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 12, 1, 13), - ..BaseNode::default() - }, - name: "c".to_string() - }) - })) - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn logical_operators_precedence_7() { let mut p = Parser::new(r#"not (a or b)"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "not (a or b)", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 13), - ..BaseNode::default() - }, - expression: Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 13), - ..BaseNode::default() - }, - operator: Operator::NotOperator, - argument: Expression::Paren(Box::new(ParenExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 5, 1, 13), - ..BaseNode::default() - }, - lparen: vec![], - expression: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(1, 6, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "not (a or b)", }, - operator: LogicalOperator::OrOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() - }, - name: "a".to_string() - }), - right: Expression::Identifier(Identifier { + }, + expression: Unary( + UnaryExpr { base: BaseNode { - location: loc.get(1, 11, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "not (a or b)", + }, }, - name: "b".to_string() - }) - })), - rparen: vec![], - })) - })) - }))], - eof: vec![], - }, - ) + operator: NotOperator, + argument: Paren( + ParenExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 13", + source: "(a or b)", + }, + }, + lparen: [], + expression: Logical( + LogicalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 12", + source: "a or b", + }, + }, + operator: OrOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "a", + }, + }, + name: "a", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 12", + source: "b", + }, + }, + name: "b", + }, + ), + }, + ), + rparen: [], + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn logical_operators_precedence_8() { let mut p = Parser::new(r#"not (a and b)"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 14", + source: "not (a and b)", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 14), - ..BaseNode::default() - }, - expression: Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 14), - ..BaseNode::default() - }, - operator: Operator::NotOperator, - argument: Expression::Paren(Box::new(ParenExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 5, 1, 14), - ..BaseNode::default() - }, - lparen: vec![], - expression: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(1, 6, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 14", + source: "not (a and b)", }, - operator: LogicalOperator::AndOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() - }, - name: "a".to_string() - }), - right: Expression::Identifier(Identifier { + }, + expression: Unary( + UnaryExpr { base: BaseNode { - location: loc.get(1, 12, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 14", + source: "not (a and b)", + }, }, - name: "b".to_string() - }) - })), - rparen: vec![], - })) - })) - }))], - eof: vec![], - }, - ) + operator: NotOperator, + argument: Paren( + ParenExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 14", + source: "(a and b)", + }, + }, + lparen: [], + expression: Logical( + LogicalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 13", + source: "a and b", + }, + }, + operator: AndOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "a", + }, + }, + name: "a", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 13", + source: "b", + }, + }, + name: "b", + }, + ), + }, + ), + rparen: [], + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn logical_operators_precedence_9() { let mut p = Parser::new(r#"(a or b) and c"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 15), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 15", + source: "(a or b) and c", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 15), - ..BaseNode::default() - }, - expression: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 15), - ..BaseNode::default() - }, - operator: LogicalOperator::AndOperator, - left: Expression::Paren(Box::new(ParenExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 9), - ..BaseNode::default() - }, - lparen: vec![], - expression: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(1, 2, 1, 8), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 15", + source: "(a or b) and c", }, - operator: LogicalOperator::OrOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 2, 1, 3), - ..BaseNode::default() - }, - name: "a".to_string() - }), - right: Expression::Identifier(Identifier { + }, + expression: Logical( + LogicalExpr { base: BaseNode { - location: loc.get(1, 7, 1, 8), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 15", + source: "(a or b) and c", + }, }, - name: "b".to_string() - }) - })), - rparen: vec![], - })), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 14, 1, 15), - ..BaseNode::default() - }, - name: "c".to_string() - }) - })) - }))], - eof: vec![], - }, - ) + operator: AndOperator, + left: Paren( + ParenExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 9", + source: "(a or b)", + }, + }, + lparen: [], + expression: Logical( + LogicalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 8", + source: "a or b", + }, + }, + operator: OrOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 3", + source: "a", + }, + }, + name: "a", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 8", + source: "b", + }, + }, + name: "b", + }, + ), + }, + ), + rparen: [], + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 15", + source: "c", + }, + }, + name: "c", + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn logical_operators_precedence_10() { let mut p = Parser::new(r#"a and (b or c)"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 15), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 15", + source: "a and (b or c)", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 15), - ..BaseNode::default() - }, - expression: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 15), - ..BaseNode::default() - }, - operator: LogicalOperator::AndOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "a".to_string() - }), - right: Expression::Paren(Box::new(ParenExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 7, 1, 15), - ..BaseNode::default() - }, - lparen: vec![], - expression: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(1, 8, 1, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 15", + source: "a and (b or c)", }, - operator: LogicalOperator::OrOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 8, 1, 9), - ..BaseNode::default() - }, - name: "b".to_string() - }), - right: Expression::Identifier(Identifier { + }, + expression: Logical( + LogicalExpr { base: BaseNode { - location: loc.get(1, 13, 1, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 15", + source: "a and (b or c)", + }, }, - name: "c".to_string() - }) - })), - rparen: vec![], - })) - })) - }))], - eof: vec![], - }, - ) + operator: AndOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, + }, + name: "a", + }, + ), + right: Paren( + ParenExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 15", + source: "(b or c)", + }, + }, + lparen: [], + expression: Logical( + LogicalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 14", + source: "b or c", + }, + }, + operator: OrOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 9", + source: "b", + }, + }, + name: "b", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 13", + end: "line: 1, column: 14", + source: "c", + }, + }, + name: "c", + }, + ), + }, + ), + rparen: [], + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } // The following test case demonstrates confusing behavior: @@ -1637,244 +2560,374 @@ fn two_logical_operations_with_parens() { (a or b) and c"#, ); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 2, 15), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 2, column: 15", + source: "not (a and b)\n(a or b) and c", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 2, 15), - ..BaseNode::default() - }, - expression: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(1, 1, 2, 15), - ..BaseNode::default() - }, - operator: LogicalOperator::AndOperator, - left: Expression::Unary(Box::new(UnaryExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 2, 9), - ..BaseNode::default() - }, - operator: Operator::NotOperator, - argument: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(1, 5, 2, 9), - errors: vec!["expected comma in property list, got OR".to_string()], - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 2, column: 15", + source: "not (a and b)\n(a or b) and c", }, - callee: Expression::Paren(Box::new(ParenExpr { - base: BaseNode { - location: loc.get(1, 5, 1, 14), - ..BaseNode::default() - }, - lparen: vec![], - expression: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(1, 6, 1, 13), - ..BaseNode::default() - }, - operator: LogicalOperator::AndOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() - }, - name: "a".to_string() - }), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 12, 1, 13), - ..BaseNode::default() - }, - name: "b".to_string() - }) - })), - rparen: vec![], - })), - lparen: vec![], - arguments: vec![Expression::Object(Box::new(ObjectExpr { + }, + expression: Logical( + LogicalExpr { base: BaseNode { - location: loc.get(2, 2, 2, 8), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 2, column: 15", + source: "not (a and b)\n(a or b) and c", + }, }, - lbrace: vec![], - with: None, - properties: vec![ - Property { + operator: AndOperator, + left: Unary( + UnaryExpr { base: BaseNode { - location: loc.get(2, 2, 2, 3), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 2, column: 9", + source: "not (a and b)\n(a or b)", + }, }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 2, 2, 3), - ..BaseNode::default() - }, - name: "a".to_string() - }), - separator: vec![], - value: None, - comma: vec![], - }, - Property { + operator: NotOperator, + argument: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 2, column: 9", + source: "(a and b)\n(a or b)", + }, + errors: [ + "expected comma in property list, got OR", + ], + }, + callee: Paren( + ParenExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 14", + source: "(a and b)", + }, + }, + lparen: [], + expression: Logical( + LogicalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 13", + source: "a and b", + }, + }, + operator: AndOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "a", + }, + }, + name: "a", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 13", + source: "b", + }, + }, + name: "b", + }, + ), + }, + ), + rparen: [], + }, + ), + lparen: [], + arguments: [ + Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 2", + end: "line: 2, column: 8", + source: "a or b", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 2", + end: "line: 2, column: 3", + source: "a", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 2", + end: "line: 2, column: 3", + source: "a", + }, + }, + name: "a", + }, + ), + separator: [], + value: None, + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 8", + source: "or b", + }, + errors: [ + "unexpected token for property key: OR (or)", + ], + }, + key: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 4", + end: "line: 2, column: 4", + source: "", + }, + }, + value: "", + }, + ), + separator: [], + value: None, + comma: [], + }, + ], + rbrace: [], + }, + ), + ], + rparen: [], + }, + ), + }, + ), + right: Identifier( + Identifier { base: BaseNode { - location: loc.get(2, 4, 2, 8), - errors: vec![ - "unexpected token for property key: OR (or)" - .to_string() - ], - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 14", + end: "line: 2, column: 15", + source: "c", + }, }, - key: PropertyKey::StringLit(StringLit { - base: BaseNode { - location: loc.get(2, 4, 2, 4), - ..BaseNode::default() - }, - value: "".to_string() - }), - separator: vec![], - value: None, - comma: vec![], - } - ], - rbrace: vec![], - }))], - rparen: vec![], - })) - })), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 14, 2, 15), - ..BaseNode::default() - }, - name: "c".to_string() - }) - })) - }))], - eof: vec![], - }, - ) + name: "c", + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] fn binary_expression() { let mut p = Parser::new(r#"_value < 10.0"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 14", + source: "_value < 10.0", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 14), - ..BaseNode::default() - }, - expression: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 14), - ..BaseNode::default() - }, - operator: Operator::LessThanOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() - }, - name: "_value".to_string() - }), - right: Expression::Float(FloatLit { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 10, 1, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 14", + source: "_value < 10.0", + }, }, - value: 10.0 - }) - })) - }))], - eof: vec![], - }, - ) + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 14", + source: "_value < 10.0", + }, + }, + operator: LessThanOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "_value", + }, + }, + name: "_value", + }, + ), + right: Float( + FloatLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 14", + source: "10.0", + }, + }, + value: 10.0, + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn member_expression_binary_expression() { let mut p = Parser::new(r#"r._value < 10.0"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 16), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 16", + source: "r._value < 10.0", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 16), - ..BaseNode::default() - }, - expression: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 16), - ..BaseNode::default() - }, - operator: Operator::LessThanOperator, - left: Expression::Member(Box::new(MemberExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 1, 1, 9), - ..BaseNode::default() - }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 16", + source: "r._value < 10.0", }, - name: "r".to_string() - }), - lbrack: vec![], - property: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 3, 1, 9), - ..BaseNode::default() - }, - name: "_value".to_string() - }), - rbrack: vec![], - })), - right: Expression::Float(FloatLit { - base: BaseNode { - location: loc.get(1, 12, 1, 16), - ..BaseNode::default() }, - value: 10.0 - }) - })) - }))], - eof: vec![], - }, - ) + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 16", + source: "r._value < 10.0", + }, + }, + operator: LessThanOperator, + left: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 9", + source: "r._value", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "r", + }, + }, + name: "r", + }, + ), + lbrack: [], + property: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 3", + end: "line: 1, column: 9", + source: "_value", + }, + }, + name: "_value", + }, + ), + rbrack: [], + }, + ), + right: Float( + FloatLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 16", + source: "10.0", + }, + }, + value: 10.0, + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] @@ -1886,117 +2939,181 @@ fn var_as_binary_expression_of_other_vars() { d = a"#, ); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 4, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 4, column: 18", + source: "a = 1\n b = 2\n c = a + b\n d = a", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![ - Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - id: Identifier { + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "a = 1", + }, }, - name: "a".to_string() - }, - init: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 5, 1, 6), - ..BaseNode::default() + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, + }, + name: "a", }, - value: 1 - }) - })), - Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(2, 13, 2, 18), - ..BaseNode::default() + init: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 6", + source: "1", + }, + }, + value: 1, + }, + ), }, - id: Identifier { + ), + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(2, 13, 2, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 18", + source: "b = 2", + }, }, - name: "b".to_string() - }, - init: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(2, 17, 2, 18), - ..BaseNode::default() + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 14", + source: "b", + }, + }, + name: "b", }, - value: 2 - }) - })), - Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(3, 13, 3, 22), - ..BaseNode::default() + init: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 17", + end: "line: 2, column: 18", + source: "2", + }, + }, + value: 2, + }, + ), }, - id: Identifier { + ), + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(3, 13, 3, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 3, column: 13", + end: "line: 3, column: 22", + source: "c = a + b", + }, + }, + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 13", + end: "line: 3, column: 14", + source: "c", + }, + }, + name: "c", }, - name: "c".to_string() + init: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 17", + end: "line: 3, column: 22", + source: "a + b", + }, + }, + operator: AdditionOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 17", + end: "line: 3, column: 18", + source: "a", + }, + }, + name: "a", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 3, column: 21", + end: "line: 3, column: 22", + source: "b", + }, + }, + name: "b", + }, + ), + }, + ), }, - init: Expression::Binary(Box::new(BinaryExpr { + ), + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(3, 17, 3, 22), - ..BaseNode::default() + location: SourceLocation { + start: "line: 4, column: 13", + end: "line: 4, column: 18", + source: "d = a", + }, }, - operator: Operator::AdditionOperator, - left: Expression::Identifier(Identifier { + id: Identifier { base: BaseNode { - location: loc.get(3, 17, 3, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 4, column: 13", + end: "line: 4, column: 14", + source: "d", + }, }, - name: "a".to_string() - }), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(3, 21, 3, 22), - ..BaseNode::default() - }, - name: "b".to_string() - }) - })) - })), - Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(4, 13, 4, 18), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(4, 13, 4, 14), - ..BaseNode::default() + name: "d", }, - name: "d".to_string() + init: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 17", + end: "line: 4, column: 18", + source: "a", + }, + }, + name: "a", + }, + ), }, - init: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(4, 17, 4, 18), - ..BaseNode::default() - }, - name: "a".to_string() - }) - })) + ), ], - eof: vec![], - }, - ) + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] @@ -2006,70 +3123,103 @@ fn var_as_unary_expression_of_other_vars() { c = -a"#, ); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 2, 19), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 2, column: 19", + source: "a = 5\n c = -a", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![ - Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - id: Identifier { + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "a".to_string() - }, - init: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 5, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "a = 5", + }, }, - value: 5 - }) - })), - Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(2, 13, 2, 19), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(2, 13, 2, 14), - ..BaseNode::default() + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, + }, + name: "a", }, - name: "c".to_string() + init: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 6", + source: "5", + }, + }, + value: 5, + }, + ), }, - init: Expression::Unary(Box::new(UnaryExpr { + ), + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(2, 17, 2, 19), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 19", + source: "c = -a", + }, }, - operator: Operator::SubtractionOperator, - argument: Expression::Identifier(Identifier { + id: Identifier { base: BaseNode { - location: loc.get(2, 18, 2, 19), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 14", + source: "c", + }, + }, + name: "c", + }, + init: Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 17", + end: "line: 2, column: 19", + source: "-a", + }, + }, + operator: SubtractionOperator, + argument: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 18", + end: "line: 2, column: 19", + source: "a", + }, + }, + name: "a", + }, + ), }, - name: "a".to_string() - }) - })) - })) + ), + }, + ), ], - eof: vec![], - }, - ) + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] @@ -2079,269 +3229,415 @@ fn var_as_both_binary_and_unary_expressions() { c = 10 * -a"#, ); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 2, 24), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 2, column: 24", + source: "a = 5\n c = 10 * -a", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![ - Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - id: Identifier { + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "a = 5", + }, }, - name: "a".to_string() - }, - init: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 5, 1, 6), - ..BaseNode::default() + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, + }, + name: "a", }, - value: 5 - }) - })), - Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(2, 13, 2, 24), - ..BaseNode::default() + init: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 6", + source: "5", + }, + }, + value: 5, + }, + ), }, - id: Identifier { + ), + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(2, 13, 2, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 24", + source: "c = 10 * -a", + }, + }, + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 14", + source: "c", + }, + }, + name: "c", }, - name: "c".to_string() + init: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 17", + end: "line: 2, column: 24", + source: "10 * -a", + }, + }, + operator: MultiplicationOperator, + left: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 17", + end: "line: 2, column: 19", + source: "10", + }, + }, + value: 10, + }, + ), + right: Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 22", + end: "line: 2, column: 24", + source: "-a", + }, + }, + operator: SubtractionOperator, + argument: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 23", + end: "line: 2, column: 24", + source: "a", + }, + }, + name: "a", + }, + ), + }, + ), + }, + ), }, - init: Expression::Binary(Box::new(BinaryExpr { + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); +} + +#[test] +fn unary_expressions_within_logical_expression() { + let mut p = Parser::new( + r#"a = 5.0 + 10.0 * -a == -0.5 or a == 6.0"#, + ); + let parsed = p.parse_file("".to_string()); + expect![[r#" + File { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 2, column: 42", + source: "a = 5.0\n 10.0 * -a == -0.5 or a == 6.0", + }, + }, + name: "", + metadata: "parser-type=rust", + package: None, + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(2, 17, 2, 24), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 8", + source: "a = 5.0", + }, }, - operator: Operator::MultiplicationOperator, - left: Expression::Integer(IntegerLit { + id: Identifier { base: BaseNode { - location: loc.get(2, 17, 2, 19), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", + }, }, - value: 10 - }), - right: Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(2, 22, 2, 24), - ..BaseNode::default() + name: "a", + }, + init: Float( + FloatLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 8", + source: "5.0", + }, + }, + value: 5.0, + }, + ), + }, + ), + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 42", + source: "10.0 * -a == -0.5 or a == 6.0", + }, + }, + expression: Logical( + LogicalExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 42", + source: "10.0 * -a == -0.5 or a == 6.0", + }, + }, + operator: OrOperator, + left: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 30", + source: "10.0 * -a == -0.5", + }, + }, + operator: EqualOperator, + left: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 22", + source: "10.0 * -a", + }, + }, + operator: MultiplicationOperator, + left: Float( + FloatLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 17", + source: "10.0", + }, + }, + value: 10.0, + }, + ), + right: Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 20", + end: "line: 2, column: 22", + source: "-a", + }, + }, + operator: SubtractionOperator, + argument: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 21", + end: "line: 2, column: 22", + source: "a", + }, + }, + name: "a", + }, + ), + }, + ), + }, + ), + right: Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 26", + end: "line: 2, column: 30", + source: "-0.5", + }, + }, + operator: SubtractionOperator, + argument: Float( + FloatLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 27", + end: "line: 2, column: 30", + source: "0.5", + }, + }, + value: 0.5, + }, + ), + }, + ), + }, + ), + right: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 34", + end: "line: 2, column: 42", + source: "a == 6.0", + }, + }, + operator: EqualOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 34", + end: "line: 2, column: 35", + source: "a", + }, + }, + name: "a", + }, + ), + right: Float( + FloatLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 39", + end: "line: 2, column: 42", + source: "6.0", + }, + }, + value: 6.0, + }, + ), + }, + ), }, - operator: Operator::SubtractionOperator, - argument: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 23, 2, 24), - ..BaseNode::default() - }, - name: "a".to_string() - }) - })) - })) - })) + ), + }, + ), ], - eof: vec![], - }, - ) + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] -fn unary_expressions_within_logical_expression() { - let mut p = Parser::new( - r#"a = 5.0 - 10.0 * -a == -0.5 or a == 6.0"#, - ); +fn unary_expression_with_member_expression() { + let mut p = Parser::new(r#"not m.b"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 2, 42), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 8", + source: "not m.b", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![ - Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 8), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "a".to_string() - }, - init: Expression::Float(FloatLit { - base: BaseNode { - location: loc.get(1, 5, 1, 8), - ..BaseNode::default() - }, - value: 5.0 - }) - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(2, 13, 2, 42), - ..BaseNode::default() - }, - expression: Expression::Logical(Box::new(LogicalExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(2, 13, 2, 42), - ..BaseNode::default() - }, - operator: LogicalOperator::OrOperator, - left: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(2, 13, 2, 30), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 8", + source: "not m.b", }, - operator: Operator::EqualOperator, - left: Expression::Binary(Box::new(BinaryExpr { + }, + expression: Unary( + UnaryExpr { base: BaseNode { - location: loc.get(2, 13, 2, 22), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 8", + source: "not m.b", + }, }, - operator: Operator::MultiplicationOperator, - left: Expression::Float(FloatLit { - base: BaseNode { - location: loc.get(2, 13, 2, 17), - ..BaseNode::default() - }, - value: 10.0 - }), - right: Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(2, 20, 2, 22), - ..BaseNode::default() - }, - operator: Operator::SubtractionOperator, - argument: Expression::Identifier(Identifier { + operator: NotOperator, + argument: Member( + MemberExpr { base: BaseNode { - location: loc.get(2, 21, 2, 22), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 8", + source: "m.b", + }, }, - name: "a".to_string() - }) - })) - })), - right: Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(2, 26, 2, 30), - ..BaseNode::default() - }, - operator: Operator::SubtractionOperator, - argument: Expression::Float(FloatLit { - base: BaseNode { - location: loc.get(2, 27, 2, 30), - ..BaseNode::default() - }, - value: 0.5 - }) - })) - })), - right: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(2, 34, 2, 42), - ..BaseNode::default() + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 6", + source: "m", + }, + }, + name: "m", + }, + ), + lbrack: [], + property: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 8", + source: "b", + }, + }, + name: "b", + }, + ), + rbrack: [], + }, + ), }, - operator: Operator::EqualOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 34, 2, 35), - ..BaseNode::default() - }, - name: "a".to_string() - }), - right: Expression::Float(FloatLit { - base: BaseNode { - location: loc.get(2, 39, 2, 42), - ..BaseNode::default() - }, - value: 6.0 - }) - })) - })) - })) - ], - eof: vec![], - }, - ) -} - -#[test] -fn unary_expression_with_member_expression() { - let mut p = Parser::new(r#"not m.b"#); - let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - File { - base: BaseNode { - location: loc.get(1, 1, 1, 8), - ..BaseNode::default() - }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), - package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 8), - ..BaseNode::default() - }, - expression: Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 8), - ..BaseNode::default() + ), }, - operator: Operator::NotOperator, - argument: Expression::Member(Box::new(MemberExpr { - base: BaseNode { - location: loc.get(1, 5, 1, 8), - ..BaseNode::default() - }, - object: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 5, 1, 6), - ..BaseNode::default() - }, - name: "m".to_string() - }), - lbrack: vec![], - property: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 7, 1, 8), - ..BaseNode::default() - }, - name: "b".to_string() - }), - rbrack: vec![], - })) - })) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] @@ -2355,135 +3651,216 @@ a = 5.0 or a == 6.0"#, ); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(2, 1, 6, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 1", + end: "line: 6, column: 13", + source: "a = 5.0\n// eval this\n10.0 * -a == -0.5\n\t// or this\n\tor a == 6.0", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![ - Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(2, 1, 2, 8), - ..BaseNode::default() - }, - id: Identifier { + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(2, 1, 2, 2), - comments: vec![ast::Comment { - text: String::from("// define a\n"), - }], - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 1", + end: "line: 2, column: 8", + source: "a = 5.0", + }, }, - name: "a".to_string() - }, - init: Expression::Float(FloatLit { - base: BaseNode { - location: loc.get(2, 5, 2, 8), - ..BaseNode::default() + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 1", + end: "line: 2, column: 2", + source: "a", + }, + comments: [ + Comment { + text: "// define a\n", + }, + ], + }, + name: "a", }, - value: 5.0 - }) - })), - Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(4, 1, 6, 13), - ..BaseNode::default() + init: Float( + FloatLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 5", + end: "line: 2, column: 8", + source: "5.0", + }, + }, + value: 5.0, + }, + ), }, - expression: Expression::Logical(Box::new(LogicalExpr { + ), + Expr( + ExprStmt { base: BaseNode { - location: loc.get(4, 1, 6, 13), - comments: vec![ast::Comment { - text: String::from("// or this\n"), - }], - ..BaseNode::default() - }, - operator: LogicalOperator::OrOperator, - left: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(4, 1, 4, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 4, column: 1", + end: "line: 6, column: 13", + source: "10.0 * -a == -0.5\n\t// or this\n\tor a == 6.0", }, - operator: Operator::EqualOperator, - left: Expression::Binary(Box::new(BinaryExpr { + }, + expression: Logical( + LogicalExpr { base: BaseNode { - location: loc.get(4, 1, 4, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 4, column: 1", + end: "line: 6, column: 13", + source: "10.0 * -a == -0.5\n\t// or this\n\tor a == 6.0", + }, + comments: [ + Comment { + text: "// or this\n", + }, + ], }, - operator: Operator::MultiplicationOperator, - left: Expression::Float(FloatLit { - base: BaseNode { - location: loc.get(4, 1, 4, 5), - comments: vec![ast::Comment { - text: String::from("// eval this\n"), - }], - ..BaseNode::default() - }, - value: 10.0 - }), - right: Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(4, 8, 4, 10), - ..BaseNode::default() - }, - operator: Operator::SubtractionOperator, - argument: Expression::Identifier(Identifier { + operator: OrOperator, + left: Binary( + BinaryExpr { base: BaseNode { - location: loc.get(4, 9, 4, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 4, column: 1", + end: "line: 4, column: 18", + source: "10.0 * -a == -0.5", + }, }, - name: "a".to_string() - }) - })) - })), - right: Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(4, 14, 4, 18), - ..BaseNode::default() - }, - operator: Operator::SubtractionOperator, - argument: Expression::Float(FloatLit { - base: BaseNode { - location: loc.get(4, 15, 4, 18), - ..BaseNode::default() - }, - value: 0.5 - }) - })) - })), - right: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(6, 5, 6, 13), - ..BaseNode::default() + operator: EqualOperator, + left: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 1", + end: "line: 4, column: 10", + source: "10.0 * -a", + }, + }, + operator: MultiplicationOperator, + left: Float( + FloatLit { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 1", + end: "line: 4, column: 5", + source: "10.0", + }, + comments: [ + Comment { + text: "// eval this\n", + }, + ], + }, + value: 10.0, + }, + ), + right: Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 8", + end: "line: 4, column: 10", + source: "-a", + }, + }, + operator: SubtractionOperator, + argument: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 9", + end: "line: 4, column: 10", + source: "a", + }, + }, + name: "a", + }, + ), + }, + ), + }, + ), + right: Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 14", + end: "line: 4, column: 18", + source: "-0.5", + }, + }, + operator: SubtractionOperator, + argument: Float( + FloatLit { + base: BaseNode { + location: SourceLocation { + start: "line: 4, column: 15", + end: "line: 4, column: 18", + source: "0.5", + }, + }, + value: 0.5, + }, + ), + }, + ), + }, + ), + right: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 6, column: 5", + end: "line: 6, column: 13", + source: "a == 6.0", + }, + }, + operator: EqualOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 6, column: 5", + end: "line: 6, column: 6", + source: "a", + }, + }, + name: "a", + }, + ), + right: Float( + FloatLit { + base: BaseNode { + location: SourceLocation { + start: "line: 6, column: 10", + end: "line: 6, column: 13", + source: "6.0", + }, + }, + value: 6.0, + }, + ), + }, + ), }, - operator: Operator::EqualOperator, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(6, 5, 6, 6), - ..BaseNode::default() - }, - name: "a".to_string() - }), - right: Expression::Float(FloatLit { - base: BaseNode { - location: loc.get(6, 10, 6, 13), - ..BaseNode::default() - }, - value: 6.0 - }) - })) - })) - })) + ), + }, + ), ], - eof: vec![], - }, - ) + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] @@ -2493,109 +3870,172 @@ fn mix_unary_logical_and_binary_expressions() { not (f() == 6.0 * x) or fail()"#, ); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(2, 13, 2, 43), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 43", + source: "not (f() == 6.0 * x) or fail()", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(2, 13, 2, 43), - ..BaseNode::default() - }, - expression: Expression::Logical(Box::new(LogicalExpr { - base: BaseNode { - location: loc.get(2, 13, 2, 43), - ..BaseNode::default() - }, - operator: LogicalOperator::OrOperator, - left: Expression::Unary(Box::new(UnaryExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(2, 13, 2, 33), - ..BaseNode::default() - }, - operator: Operator::NotOperator, - argument: Expression::Paren(Box::new(ParenExpr { - base: BaseNode { - location: loc.get(2, 17, 2, 33), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 43", + source: "not (f() == 6.0 * x) or fail()", }, - lparen: vec![], - expression: Expression::Binary(Box::new(BinaryExpr { + }, + expression: Logical( + LogicalExpr { base: BaseNode { - location: loc.get(2, 18, 2, 32), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 43", + source: "not (f() == 6.0 * x) or fail()", + }, }, - operator: Operator::EqualOperator, - left: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(2, 18, 2, 21), - ..BaseNode::default() - }, - lparen: vec![], - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 18, 2, 19), - ..BaseNode::default() - }, - name: "f".to_string() - }), - arguments: vec![], - rparen: vec![], - })), - right: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(2, 25, 2, 32), - ..BaseNode::default() - }, - operator: Operator::MultiplicationOperator, - left: Expression::Float(FloatLit { + operator: OrOperator, + left: Unary( + UnaryExpr { base: BaseNode { - location: loc.get(2, 25, 2, 28), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 33", + source: "not (f() == 6.0 * x)", + }, }, - value: 6.0 - }), - right: Expression::Identifier(Identifier { + operator: NotOperator, + argument: Paren( + ParenExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 17", + end: "line: 2, column: 33", + source: "(f() == 6.0 * x)", + }, + }, + lparen: [], + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 18", + end: "line: 2, column: 32", + source: "f() == 6.0 * x", + }, + }, + operator: EqualOperator, + left: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 18", + end: "line: 2, column: 21", + source: "f()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 18", + end: "line: 2, column: 19", + source: "f", + }, + }, + name: "f", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), + right: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 25", + end: "line: 2, column: 32", + source: "6.0 * x", + }, + }, + operator: MultiplicationOperator, + left: Float( + FloatLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 25", + end: "line: 2, column: 28", + source: "6.0", + }, + }, + value: 6.0, + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 31", + end: "line: 2, column: 32", + source: "x", + }, + }, + name: "x", + }, + ), + }, + ), + }, + ), + rparen: [], + }, + ), + }, + ), + right: Call( + CallExpr { base: BaseNode { - location: loc.get(2, 31, 2, 32), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 37", + end: "line: 2, column: 43", + source: "fail()", + }, }, - name: "x".to_string() - }) - })) - })), - rparen: vec![], - })) - })), - right: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(2, 37, 2, 43), - ..BaseNode::default() - }, - lparen: vec![], - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 37, 2, 41), - ..BaseNode::default() - }, - name: "fail".to_string() - }), - arguments: vec![], - rparen: vec![], - })), - })) - }))], - eof: vec![], - }, - ) + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 37", + end: "line: 2, column: 41", + source: "fail", + }, + }, + name: "fail", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] @@ -2605,259 +4045,399 @@ fn mix_unary_logical_and_binary_expressions_with_extra_parens() { (not (f() == 6.0 * x) or fail())"#, ); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(2, 13, 2, 45), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 45", + source: "(not (f() == 6.0 * x) or fail())", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(2, 13, 2, 45), - ..BaseNode::default() - }, - expression: Expression::Paren(Box::new(ParenExpr { - base: BaseNode { - location: loc.get(2, 13, 2, 45), - ..BaseNode::default() - }, - lparen: vec![], - expression: Expression::Logical(Box::new(LogicalExpr { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(2, 14, 2, 44), - ..BaseNode::default() - }, - operator: LogicalOperator::OrOperator, - left: Expression::Unary(Box::new(UnaryExpr { - base: BaseNode { - location: loc.get(2, 14, 2, 34), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 45", + source: "(not (f() == 6.0 * x) or fail())", }, - operator: Operator::NotOperator, - argument: Expression::Paren(Box::new(ParenExpr { + }, + expression: Paren( + ParenExpr { base: BaseNode { - location: loc.get(2, 18, 2, 34), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 13", + end: "line: 2, column: 45", + source: "(not (f() == 6.0 * x) or fail())", + }, }, - lparen: vec![], - expression: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(2, 19, 2, 33), - ..BaseNode::default() - }, - operator: Operator::EqualOperator, - left: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(2, 19, 2, 22), - ..BaseNode::default() - }, - lparen: vec![], - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 19, 2, 20), - ..BaseNode::default() - }, - name: "f".to_string() - }), - arguments: vec![], - rparen: vec![], - })), - right: Expression::Binary(Box::new(BinaryExpr { + lparen: [], + expression: Logical( + LogicalExpr { base: BaseNode { - location: loc.get(2, 26, 2, 33), - ..BaseNode::default() + location: SourceLocation { + start: "line: 2, column: 14", + end: "line: 2, column: 44", + source: "not (f() == 6.0 * x) or fail()", + }, }, - operator: Operator::MultiplicationOperator, - left: Expression::Float(FloatLit { - base: BaseNode { - location: loc.get(2, 26, 2, 29), - ..BaseNode::default() - }, - value: 6.0 - }), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 32, 2, 33), - ..BaseNode::default() - }, - name: "x".to_string() - }) - })) - })), - rparen: vec![], - })) - })), - right: Expression::Call(Box::new(CallExpr { - base: BaseNode { - location: loc.get(2, 38, 2, 44), - ..BaseNode::default() + operator: OrOperator, + left: Unary( + UnaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 14", + end: "line: 2, column: 34", + source: "not (f() == 6.0 * x)", + }, + }, + operator: NotOperator, + argument: Paren( + ParenExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 18", + end: "line: 2, column: 34", + source: "(f() == 6.0 * x)", + }, + }, + lparen: [], + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 19", + end: "line: 2, column: 33", + source: "f() == 6.0 * x", + }, + }, + operator: EqualOperator, + left: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 19", + end: "line: 2, column: 22", + source: "f()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 19", + end: "line: 2, column: 20", + source: "f", + }, + }, + name: "f", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), + right: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 26", + end: "line: 2, column: 33", + source: "6.0 * x", + }, + }, + operator: MultiplicationOperator, + left: Float( + FloatLit { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 26", + end: "line: 2, column: 29", + source: "6.0", + }, + }, + value: 6.0, + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 32", + end: "line: 2, column: 33", + source: "x", + }, + }, + name: "x", + }, + ), + }, + ), + }, + ), + rparen: [], + }, + ), + }, + ), + right: Call( + CallExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 38", + end: "line: 2, column: 44", + source: "fail()", + }, + }, + callee: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 2, column: 38", + end: "line: 2, column: 42", + source: "fail", + }, + }, + name: "fail", + }, + ), + lparen: [], + arguments: [], + rparen: [], + }, + ), + }, + ), + rparen: [], }, - lparen: vec![], - callee: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(2, 38, 2, 42), - ..BaseNode::default() - }, - name: "fail".to_string() - }), - arguments: vec![], - rparen: vec![], - })), - })), - rparen: vec![], - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] fn modulo_op_ints() { let mut p = Parser::new(r#"3 % 8"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "3 % 8", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - expression: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - operator: Operator::ModuloOperator, - left: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - value: 3 - }), - right: Expression::Integer(IntegerLit { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 5, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "3 % 8", + }, }, - value: 8 - }) - })) - }))], - eof: vec![], - }, - ) + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "3 % 8", + }, + }, + operator: ModuloOperator, + left: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "3", + }, + }, + value: 3, + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 6", + source: "8", + }, + }, + value: 8, + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn modulo_op_floats() { let mut p = Parser::new(r#"8.3 % 3.1"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 10", + source: "8.3 % 3.1", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 10), - ..BaseNode::default() - }, - expression: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 10), - ..BaseNode::default() - }, - operator: Operator::ModuloOperator, - left: Expression::Float(FloatLit { - base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() - }, - value: 8.3 - }), - right: Expression::Float(FloatLit { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 7, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 10", + source: "8.3 % 3.1", + }, }, - value: 3.1 - }) - })) - }))], - eof: vec![], - }, - ) + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 10", + source: "8.3 % 3.1", + }, + }, + operator: ModuloOperator, + left: Float( + FloatLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "8.3", + }, + }, + value: 8.3, + }, + ), + right: Float( + FloatLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 10", + source: "3.1", + }, + }, + value: 3.1, + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn power_op() { let mut p = Parser::new(r#"2 ^ 4"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "2 ^ 4", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - expression: Expression::Binary(Box::new(BinaryExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - operator: Operator::PowerOperator, - left: Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - value: 2 - }), - right: Expression::Integer(IntegerLit { + imports: [], + body: [ + Expr( + ExprStmt { base: BaseNode { - location: loc.get(1, 5, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "2 ^ 4", + }, }, - value: 4 - }) - })) - }))], - eof: vec![], - }, - ) + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "2 ^ 4", + }, + }, + operator: PowerOperator, + left: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "2", + }, + }, + value: 2, + }, + ), + right: Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 6", + source: "4", + }, + }, + value: 4, + }, + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } diff --git a/libflux/flux-core/src/parser/tests/property_list.rs b/libflux/flux-core/src/parser/tests/property_list.rs index cf3f07848c..7cedcf3949 100644 --- a/libflux/flux-core/src/parser/tests/property_list.rs +++ b/libflux/flux-core/src/parser/tests/property_list.rs @@ -1,238 +1,357 @@ use super::*; -use crate::ast::tests::Locator; -use pretty_assertions::assert_eq; - #[test] fn property_list_missing_property() { let mut p = Parser::new(r#"o = {a: "a",, b: 7}"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(&p.source[..]); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 20), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 20", + source: "o = {a: \"a\",, b: 7}", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 20), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "o".to_string() - }, - init: Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 5, 1, 20), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![ - Property { - base: BaseNode { - location: loc.get(1, 6, 1, 12), - ..BaseNode::default() + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 20", + source: "o = {a: \"a\",, b: 7}", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() - }, - name: "a".to_string() - }), - separator: vec![], - value: Some(Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 9, 1, 12), - ..BaseNode::default() - }, - value: "a".to_string() - })), - comma: vec![], }, - Property { + id: Identifier { base: BaseNode { - location: loc.get(1, 13, 1, 13), - errors: vec!["missing property in property list".to_string()], - ..BaseNode::default() - }, - key: PropertyKey::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 13, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "o", }, - value: "".to_string() - }), - separator: vec![], - value: None, - comma: vec![], - }, - Property { - base: BaseNode { - location: loc.get(1, 15, 1, 19), - ..BaseNode::default() }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 15, 1, 16), - ..BaseNode::default() - }, - name: "b".to_string() - }), - separator: vec![], - value: Some(Expression::Integer(IntegerLit { + name: "o", + }, + init: Object( + ObjectExpr { base: BaseNode { - location: loc.get(1, 18, 1, 19), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 20", + source: "{a: \"a\",, b: 7}", + }, }, - value: 7 - })), - comma: vec![], - } - ], - rbrace: vec![], - })) - }))], - eof: vec![], - }, - ) + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 12", + source: "a: \"a\"", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "a", + }, + }, + name: "a", + }, + ), + separator: [], + value: Some( + StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 12", + source: "\"a\"", + }, + }, + value: "a", + }, + ), + ), + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 13", + end: "line: 1, column: 13", + source: "", + }, + errors: [ + "missing property in property list", + ], + }, + key: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 13", + end: "line: 1, column: 13", + source: "", + }, + }, + value: "", + }, + ), + separator: [], + value: None, + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 19", + source: "b: 7", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 16", + source: "b", + }, + }, + name: "b", + }, + ), + separator: [], + value: Some( + Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 18", + end: "line: 1, column: 19", + source: "7", + }, + }, + value: 7, + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn property_list_missing_key() { let mut p = Parser::new(r#"o = {: "a"}"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(&p.source[..]); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "o = {: \"a\"}", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "o".to_string() - }, - init: Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 5, 1, 12), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![Property { + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(1, 6, 1, 11), - errors: vec!["missing property key".to_string()], - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "o = {: \"a\"}", + }, }, - key: PropertyKey::StringLit(StringLit { + id: Identifier { base: BaseNode { - location: loc.get(1, 6, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "o", + }, }, - value: "".to_string() - }), - separator: vec![], - value: Some(Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 8, 1, 11), - ..BaseNode::default() + name: "o", + }, + init: Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 12", + source: "{: \"a\"}", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 11", + source: ": \"a\"", + }, + errors: [ + "missing property key", + ], + }, + key: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 6", + source: "", + }, + }, + value: "", + }, + ), + separator: [], + value: Some( + StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 11", + source: "\"a\"", + }, + }, + value: "a", + }, + ), + ), + comma: [], + }, + ], + rbrace: [], }, - value: "a".to_string() - })), - comma: vec![], - }], - rbrace: vec![], - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn property_list_missing_value() { let mut p = Parser::new(r#"o = {a:}"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(&p.source[..]); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 9), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 9", + source: "o = {a:}", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 9), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "o".to_string() - }, - init: Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 5, 1, 9), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![Property { + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(1, 6, 1, 7), - errors: vec!["missing property value".to_string()], - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 9", + source: "o = {a:}", + }, }, - key: PropertyKey::Identifier(Identifier { + id: Identifier { base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "o", + }, + }, + name: "o", + }, + init: Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 9", + source: "{a:}", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "a", + }, + errors: [ + "missing property value", + ], + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "a", + }, + }, + name: "a", + }, + ), + separator: [], + value: None, + comma: [], + }, + ], + rbrace: [], }, - name: "a".to_string() - }), - separator: vec![], - value: None, - comma: vec![], - }], - rbrace: vec![], - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } // TODO(affo): that error is injected by ast.Check(). @@ -240,279 +359,425 @@ fn property_list_missing_value() { fn property_list_missing_comma() { let mut p = Parser::new(r#"o = {a: "a" b: 30}"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(&p.source[..]); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 19), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 19", + source: "o = {a: \"a\" b: 30}", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 19), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "o".to_string() - }, - init: Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 5, 1, 19), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![ - Property { - base: BaseNode { - location: loc.get(1, 6, 1, 14), - ..BaseNode::default() + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 19", + source: "o = {a: \"a\" b: 30}", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() + }, + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "o", }, - name: "a".to_string() - }), - separator: vec![], - // TODO(affo): ast.Check would add the error "expected an operator between two expressions". - value: Some(Expression::Binary(Box::new(BinaryExpr { + }, + name: "o", + }, + init: Object( + ObjectExpr { base: BaseNode { - location: loc.get(1, 9, 1, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 19", + source: "{a: \"a\" b: 30}", + }, }, - operator: Operator::InvalidOperator, - left: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 9, 1, 12), - ..BaseNode::default() + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 14", + source: "a: \"a\" b", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "a", + }, + }, + name: "a", + }, + ), + separator: [], + value: Some( + Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 14", + source: "\"a\" b", + }, + }, + operator: InvalidOperator, + left: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 12", + source: "\"a\"", + }, + }, + value: "a", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 13", + end: "line: 1, column: 14", + source: "b", + }, + }, + name: "b", + }, + ), + }, + ), + ), + comma: [], }, - value: "a".to_string() - }), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 13, 1, 14), - ..BaseNode::default() + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 18", + source: ": 30", + }, + errors: [ + "missing property key", + ], + }, + key: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 14", + source: "", + }, + }, + value: "", + }, + ), + separator: [], + value: Some( + Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 16", + end: "line: 1, column: 18", + source: "30", + }, + errors: [ + "expected comma in property list, got COLON", + ], + }, + value: 30, + }, + ), + ), + comma: [], }, - name: "b".to_string() - }) - }))), - comma: vec![], - }, - Property { - base: BaseNode { - location: loc.get(1, 14, 1, 18), - errors: vec!["missing property key".to_string()], - ..BaseNode::default() + ], + rbrace: [], }, - key: PropertyKey::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 14, 1, 14), - ..BaseNode::default() - }, - value: "".to_string() - }), - separator: vec![], - value: Some(Expression::Integer(IntegerLit { - base: BaseNode { - location: loc.get(1, 16, 1, 18), - errors: vec![ - "expected comma in property list, got COLON".to_string() - ], - ..BaseNode::default() - }, - value: 30 - })), - comma: vec![], - } - ], - rbrace: vec![], - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] fn property_list_trailing_comma() { let mut p = Parser::new(r#"o = {a: "a",}"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(&p.source[..]); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 14", + source: "o = {a: \"a\",}", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 14), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "o".to_string() - }, - init: Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 5, 1, 14), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![Property { + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(1, 6, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 14", + source: "o = {a: \"a\",}", + }, }, - key: PropertyKey::Identifier(Identifier { + id: Identifier { base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "o", + }, }, - name: "a".to_string() - }), - separator: vec![], - value: Some(Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 9, 1, 12), - ..BaseNode::default() + name: "o", + }, + init: Object( + ObjectExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 14", + source: "{a: \"a\",}", + }, + }, + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 12", + source: "a: \"a\"", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "a", + }, + }, + name: "a", + }, + ), + separator: [], + value: Some( + StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 12", + source: "\"a\"", + }, + }, + value: "a", + }, + ), + ), + comma: [], + }, + ], + rbrace: [], }, - value: "a".to_string() - })), - comma: vec![], - }], - rbrace: vec![], - })) - }))], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn property_list_bad_property() { let mut p = Parser::new(r#"o = {a: "a", 30, b: 7}"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(&p.source[..]); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 23), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 23", + source: "o = {a: \"a\", 30, b: 7}", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 23), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "o".to_string() - }, - init: Expression::Object(Box::new(ObjectExpr { - base: BaseNode { - location: loc.get(1, 5, 1, 23), - ..BaseNode::default() - }, - lbrace: vec![], - with: None, - properties: vec![ - Property { - base: BaseNode { - location: loc.get(1, 6, 1, 12), - ..BaseNode::default() + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 23", + source: "o = {a: \"a\", 30, b: 7}", }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 6, 1, 7), - ..BaseNode::default() - }, - name: "a".to_string() - }), - separator: vec![], - value: Some(Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 9, 1, 12), - ..BaseNode::default() - }, - value: "a".to_string() - })), - comma: vec![], }, - Property { + id: Identifier { base: BaseNode { - location: loc.get(1, 14, 1, 16), - errors: vec![ - "unexpected token for property key: INT (30)".to_string() - ], - ..BaseNode::default() - }, - key: PropertyKey::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 14, 1, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "o", }, - value: "".to_string() - }), - separator: vec![], - value: None, - comma: vec![], - }, - Property { - base: BaseNode { - location: loc.get(1, 18, 1, 22), - ..BaseNode::default() }, - key: PropertyKey::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 18, 1, 19), - ..BaseNode::default() - }, - name: "b".to_string() - }), - separator: vec![], - value: Some(Expression::Integer(IntegerLit { + name: "o", + }, + init: Object( + ObjectExpr { base: BaseNode { - location: loc.get(1, 21, 1, 22), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 23", + source: "{a: \"a\", 30, b: 7}", + }, }, - value: 7 - })), - comma: vec![], - } - ], - rbrace: vec![], - })) - }))], - eof: vec![], - }, - ) + lbrace: [], + with: None, + properties: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 12", + source: "a: \"a\"", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 7", + source: "a", + }, + }, + name: "a", + }, + ), + separator: [], + value: Some( + StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 12", + source: "\"a\"", + }, + }, + value: "a", + }, + ), + ), + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 16", + source: "30", + }, + errors: [ + "unexpected token for property key: INT (30)", + ], + }, + key: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 14", + source: "", + }, + }, + value: "", + }, + ), + separator: [], + value: None, + comma: [], + }, + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 18", + end: "line: 1, column: 22", + source: "b: 7", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 18", + end: "line: 1, column: 19", + source: "b", + }, + }, + name: "b", + }, + ), + separator: [], + value: Some( + Integer( + IntegerLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 21", + end: "line: 1, column: 22", + source: "7", + }, + }, + value: 7, + }, + ), + ), + comma: [], + }, + ], + rbrace: [], + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } diff --git a/libflux/flux-core/src/parser/tests/strings.rs b/libflux/flux-core/src/parser/tests/strings.rs index 9837d6b67c..d3a502335e 100644 --- a/libflux/flux-core/src/parser/tests/strings.rs +++ b/libflux/flux-core/src/parser/tests/strings.rs @@ -1,11 +1,6 @@ use pretty_assertions::assert_eq; use super::*; -use crate::ast::{ - tests::Locator, - Expression::{Array, Member}, - StringExprPart::{Interpolated, Text}, -}; #[test] fn parse_string_literal() { @@ -34,595 +29,903 @@ fn parse_string_literal_invalid_string() { fn string_interpolation_simple() { let mut p = Parser::new(r#""a + b = ${a + b}""#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 19), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 19", + source: "\"a + b = ${a + b}\"", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 19), - ..BaseNode::default() - }, - expression: Expression::StringExpr(Box::new(StringExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 19), - ..BaseNode::default() - }, - parts: vec![ - StringExprPart::Text(TextPart { - base: BaseNode { - location: loc.get(1, 2, 1, 10), - ..BaseNode::default() - }, - value: "a + b = ".to_string(), - }), - StringExprPart::Interpolated(InterpolatedPart { - base: BaseNode { - location: loc.get(1, 10, 1, 18), - ..BaseNode::default() + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 19", + source: "\"a + b = ${a + b}\"", }, - expression: Expression::Binary(Box::new(BinaryExpr { + }, + expression: StringExpr( + StringExpr { base: BaseNode { - location: loc.get(1, 12, 1, 17), - ..BaseNode::default() - }, - left: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 12, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 19", + source: "\"a + b = ${a + b}\"", }, - name: "a".to_string(), - }), - right: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 16, 1, 17), - ..BaseNode::default() - }, - name: "b".to_string(), - }), - operator: Operator::AdditionOperator, - })), - }), - ], - })), - })),], - eof: vec![], - }, - ) + }, + parts: [ + Text( + TextPart { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 10", + source: "a + b = ", + }, + }, + value: "a + b = ", + }, + ), + Interpolated( + InterpolatedPart { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 18", + source: "${a + b}", + }, + }, + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 17", + source: "a + b", + }, + }, + operator: AdditionOperator, + left: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 13", + source: "a", + }, + }, + name: "a", + }, + ), + right: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 16", + end: "line: 1, column: 17", + source: "b", + }, + }, + name: "b", + }, + ), + }, + ), + }, + ), + ], + }, + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn string_interpolation_array() { let mut p = Parser::new(r#"a = ["influx", "test", "InfluxOfflineTimeAlert", "acu:${r.a}"]"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 63), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 63", + source: "a = [\"influx\", \"test\", \"InfluxOfflineTimeAlert\", \"acu:${r.a}\"]", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 63), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - name: "a".to_string(), - }, - init: Array(Box::new(ArrayExpr { - base: BaseNode { - location: loc.get(1, 5, 1, 63), - ..BaseNode::default() - }, - lbrack: vec![], - elements: vec![ - ArrayItem { - expression: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 6, 1, 14), - ..BaseNode::default() - }, - value: "influx".to_string(), - }), - comma: vec![], - }, - ArrayItem { - expression: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 16, 1, 22), - ..BaseNode::default() - }, - value: "test".to_string(), - }), - comma: vec![], + imports: [], + body: [ + Variable( + VariableAssgn { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 63", + source: "a = [\"influx\", \"test\", \"InfluxOfflineTimeAlert\", \"acu:${r.a}\"]", + }, }, - ArrayItem { - expression: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 24, 1, 48), - ..BaseNode::default() + id: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "a", }, - value: "InfluxOfflineTimeAlert".to_string(), - }), - comma: vec![], + }, + name: "a", }, - ArrayItem { - expression: Expression::StringExpr(Box::new(StringExpr { + init: Array( + ArrayExpr { base: BaseNode { - location: loc.get(1, 50, 1, 62), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 63", + source: "[\"influx\", \"test\", \"InfluxOfflineTimeAlert\", \"acu:${r.a}\"]", + }, }, - parts: vec![ - Text(TextPart { - base: BaseNode { - location: loc.get(1, 51, 1, 55), - ..BaseNode::default() - }, - value: "acu:".to_string(), - }), - Interpolated(InterpolatedPart { - base: BaseNode { - location: loc.get(1, 55, 1, 61), - ..BaseNode::default() - }, - expression: Member(Box::new(MemberExpr { - base: BaseNode { - location: loc.get(1, 57, 1, 60), - ..BaseNode::default() + lbrack: [], + elements: [ + ArrayItem { + expression: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 14", + source: "\"influx\"", + }, + }, + value: "influx", + }, + ), + comma: [], + }, + ArrayItem { + expression: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 16", + end: "line: 1, column: 22", + source: "\"test\"", + }, + }, + value: "test", }, - object: Expression::Identifier(Identifier { + ), + comma: [], + }, + ArrayItem { + expression: StringLit( + StringLit { base: BaseNode { - location: loc.get(1, 57, 1, 58), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 24", + end: "line: 1, column: 48", + source: "\"InfluxOfflineTimeAlert\"", + }, }, - name: "r".to_string(), - }), - lbrack: vec![], - property: PropertyKey::Identifier(Identifier { + value: "InfluxOfflineTimeAlert", + }, + ), + comma: [], + }, + ArrayItem { + expression: StringExpr( + StringExpr { base: BaseNode { - location: loc.get(1, 59, 1, 60), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 50", + end: "line: 1, column: 62", + source: "\"acu:${r.a}\"", + }, }, - name: "a".to_string(), - }), - rbrack: vec![], - })), - }), + parts: [ + Text( + TextPart { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 51", + end: "line: 1, column: 55", + source: "acu:", + }, + }, + value: "acu:", + }, + ), + Interpolated( + InterpolatedPart { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 55", + end: "line: 1, column: 61", + source: "${r.a}", + }, + }, + expression: Member( + MemberExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 57", + end: "line: 1, column: 60", + source: "r.a", + }, + }, + object: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 57", + end: "line: 1, column: 58", + source: "r", + }, + }, + name: "r", + }, + ), + lbrack: [], + property: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 59", + end: "line: 1, column: 60", + source: "a", + }, + }, + name: "a", + }, + ), + rbrack: [], + }, + ), + }, + ), + ], + }, + ), + comma: [], + }, ], - }),), - comma: vec![], - }, - ], - rbrack: vec![], - },)), - }),),], - eof: vec![], + rbrack: [], + }, + ), + }, + ), + ], + eof: [], } - ) + "#]].assert_debug_eq(&parsed); } #[test] fn string_interpolation_multiple() { let mut p = Parser::new(r#""a = ${a} and b = ${b}""#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 24), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 24", + source: "\"a = ${a} and b = ${b}\"", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 24), - ..BaseNode::default() - }, - expression: Expression::StringExpr(Box::new(StringExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 24), - ..BaseNode::default() - }, - parts: vec![ - StringExprPart::Text(TextPart { - base: BaseNode { - location: loc.get(1, 2, 1, 6), - ..BaseNode::default() - }, - value: "a = ".to_string(), - }), - StringExprPart::Interpolated(InterpolatedPart { - base: BaseNode { - location: loc.get(1, 6, 1, 10), - ..BaseNode::default() + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 24", + source: "\"a = ${a} and b = ${b}\"", }, - expression: Expression::Identifier(Identifier { + }, + expression: StringExpr( + StringExpr { base: BaseNode { - location: loc.get(1, 8, 1, 9), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 24", + source: "\"a = ${a} and b = ${b}\"", + }, }, - name: "a".to_string(), - }), - }), - StringExprPart::Text(TextPart { - base: BaseNode { - location: loc.get(1, 10, 1, 19), - ..BaseNode::default() - }, - value: " and b = ".to_string(), - }), - StringExprPart::Interpolated(InterpolatedPart { - base: BaseNode { - location: loc.get(1, 19, 1, 23), - ..BaseNode::default() + parts: [ + Text( + TextPart { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 6", + source: "a = ", + }, + }, + value: "a = ", + }, + ), + Interpolated( + InterpolatedPart { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 10", + source: "${a}", + }, + }, + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 9", + source: "a", + }, + }, + name: "a", + }, + ), + }, + ), + Text( + TextPart { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 19", + source: " and b = ", + }, + }, + value: " and b = ", + }, + ), + Interpolated( + InterpolatedPart { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 19", + end: "line: 1, column: 23", + source: "${b}", + }, + }, + expression: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 21", + end: "line: 1, column: 22", + source: "b", + }, + }, + name: "b", + }, + ), + }, + ), + ], }, - expression: Expression::Identifier(Identifier { - base: BaseNode { - location: loc.get(1, 21, 1, 22), - ..BaseNode::default() - }, - name: "b".to_string(), - }), - }), - ], - })), - })),], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn string_interpolation_nested() { let mut p = Parser::new(r#""we ${"can ${"add" + "strings"}"} together""#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 44), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 44", + source: "\"we ${\"can ${\"add\" + \"strings\"}\"} together\"", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 44), - ..BaseNode::default() - }, - expression: Expression::StringExpr(Box::new(StringExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 44), - ..BaseNode::default() - }, - parts: vec![ - StringExprPart::Text(TextPart { - base: BaseNode { - location: loc.get(1, 2, 1, 5), - ..BaseNode::default() - }, - value: "we ".to_string(), - }), - StringExprPart::Interpolated(InterpolatedPart { - base: BaseNode { - location: loc.get(1, 5, 1, 34), - ..BaseNode::default() + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 44", + source: "\"we ${\"can ${\"add\" + \"strings\"}\"} together\"", }, - expression: Expression::StringExpr(Box::new(StringExpr { + }, + expression: StringExpr( + StringExpr { base: BaseNode { - location: loc.get(1, 7, 1, 33), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 44", + source: "\"we ${\"can ${\"add\" + \"strings\"}\"} together\"", + }, }, - parts: vec![ - StringExprPart::Text(TextPart { - base: BaseNode { - location: loc.get(1, 8, 1, 12), - ..BaseNode::default() - }, - value: "can ".to_string(), - }), - StringExprPart::Interpolated(InterpolatedPart { - base: BaseNode { - location: loc.get(1, 12, 1, 32), - ..BaseNode::default() + parts: [ + Text( + TextPart { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 5", + source: "we ", + }, + }, + value: "we ", }, - expression: Expression::Binary(Box::new(BinaryExpr { + ), + Interpolated( + InterpolatedPart { base: BaseNode { - location: loc.get(1, 14, 1, 31), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 34", + source: "${\"can ${\"add\" + \"strings\"}\"}", + }, }, - left: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 14, 1, 19), - ..BaseNode::default() + expression: StringExpr( + StringExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 33", + source: "\"can ${\"add\" + \"strings\"}\"", + }, + }, + parts: [ + Text( + TextPart { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 8", + end: "line: 1, column: 12", + source: "can ", + }, + }, + value: "can ", + }, + ), + Interpolated( + InterpolatedPart { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 12", + end: "line: 1, column: 32", + source: "${\"add\" + \"strings\"}", + }, + }, + expression: Binary( + BinaryExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 31", + source: "\"add\" + \"strings\"", + }, + }, + operator: AdditionOperator, + left: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 19", + source: "\"add\"", + }, + }, + value: "add", + }, + ), + right: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 22", + end: "line: 1, column: 31", + source: "\"strings\"", + }, + }, + value: "strings", + }, + ), + }, + ), + }, + ), + ], }, - value: "add".to_string(), - }), - right: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 22, 1, 31), - ..BaseNode::default() + ), + }, + ), + Text( + TextPart { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 34", + end: "line: 1, column: 43", + source: " together", }, - value: "strings".to_string(), - }), - operator: Operator::AdditionOperator, - })), - }), + }, + value: " together", + }, + ), ], - })) - }), - StringExprPart::Text(TextPart { - base: BaseNode { - location: loc.get(1, 34, 1, 43), - ..BaseNode::default() }, - value: " together".to_string(), - }), - ], - })), - })),], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] fn string_interp_with_escapes() { let mut p = Parser::new(r#""string \"interpolation with ${"escapes"}\"""#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 45), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 45", + source: "\"string \\\"interpolation with ${\"escapes\"}\\\"\"", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 45), - ..BaseNode::default() - }, - expression: Expression::StringExpr(Box::new(StringExpr { - base: BaseNode { - location: loc.get(1, 1, 1, 45), - ..BaseNode::default() - }, - parts: vec![ - StringExprPart::Text(TextPart { - base: BaseNode { - location: loc.get(1, 2, 1, 30), - ..BaseNode::default() - }, - value: "string \"interpolation with ".to_string(), - }), - StringExprPart::Interpolated(InterpolatedPart { - base: BaseNode { - location: loc.get(1, 30, 1, 42), - ..BaseNode::default() + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 45", + source: "\"string \\\"interpolation with ${\"escapes\"}\\\"\"", }, - expression: Expression::StringLit(StringLit { + }, + expression: StringExpr( + StringExpr { base: BaseNode { - location: loc.get(1, 32, 1, 41), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 45", + source: "\"string \\\"interpolation with ${\"escapes\"}\\\"\"", + }, }, - value: "escapes".to_string(), - }), - }), - StringExprPart::Text(TextPart { - base: BaseNode { - location: loc.get(1, 42, 1, 44), - ..BaseNode::default() + parts: [ + Text( + TextPart { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 30", + source: "string \\\"interpolation with ", + }, + }, + value: "string \"interpolation with ", + }, + ), + Interpolated( + InterpolatedPart { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 30", + end: "line: 1, column: 42", + source: "${\"escapes\"}", + }, + }, + expression: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 32", + end: "line: 1, column: 41", + source: "\"escapes\"", + }, + }, + value: "escapes", + }, + ), + }, + ), + Text( + TextPart { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 42", + end: "line: 1, column: 44", + source: "\\\"", + }, + }, + value: "\"", + }, + ), + ], }, - value: "\"".to_string(), - }), - ], - })), - })),], - eof: vec![], - }, - ) + ), + }, + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] fn bad_string_expression() { let mut p = Parser::new(r#"fn = (a) => "${a}"#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "fn = (a) => \"${a}", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Variable(Box::new(VariableAssgn { - base: BaseNode { - location: loc.get(1, 1, 1, 18), - ..BaseNode::default() - }, - id: Identifier { - base: BaseNode { - location: loc.get(1, 1, 1, 3), - ..BaseNode::default() - }, - name: "fn".to_string(), - }, - init: Expression::Function(Box::new(FunctionExpr { - base: BaseNode { - location: loc.get(1, 6, 1, 18), - ..BaseNode::default() - }, - lparen: vec![], - params: vec![Property { + imports: [], + body: [ + Variable( + VariableAssgn { base: BaseNode { - location: loc.get(1, 7, 1, 8), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "fn = (a) => \"${a}", + }, }, - key: PropertyKey::Identifier(Identifier { + id: Identifier { base: BaseNode { - location: loc.get(1, 7, 1, 8), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 3", + source: "fn", + }, }, - name: "a".to_string() - }), - separator: vec![], - value: None, - comma: vec![], - }], - rparen: vec![], - arrow: vec![], - body: FunctionBody::Expr(Expression::StringExpr(Box::new(StringExpr { - base: BaseNode { - location: loc.get(1, 13, 1, 18), - errors: vec![ - "got unexpected token in string expression @1:18-1:18: EOF" - .to_string() - ], - ..BaseNode::default() + name: "fn", }, - parts: vec![], - }))), - })), - }))], - eof: vec![], - }, - ) + init: Function( + FunctionExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 18", + source: "(a) => \"${a}", + }, + }, + lparen: [], + params: [ + Property { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 8", + source: "a", + }, + }, + key: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 8", + source: "a", + }, + }, + name: "a", + }, + ), + separator: [], + value: None, + comma: [], + }, + ], + rparen: [], + arrow: [], + body: Expr( + StringExpr( + StringExpr { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 13", + end: "line: 1, column: 18", + source: "\"${a}", + }, + errors: [ + "got unexpected token in string expression @1:18-1:18: EOF", + ], + }, + parts: [], + }, + ), + ), + }, + ), + }, + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] fn string_with_utf_8() { let mut p = Parser::new(r#""日本語""#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "\"日本語\"", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() - }, - expression: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 1, 1, 12), - ..BaseNode::default() + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "\"日本語\"", + }, + }, + expression: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 12", + source: "\"日本語\"", + }, + }, + value: "日本語", + }, + ), }, - value: "日本語".to_string() - }) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn string_with_byte_values() { let mut p = Parser::new(r#""\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e""#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 39), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 39", + source: "\"\\xe6\\x97\\xa5\\xe6\\x9c\\xac\\xe8\\xaa\\x9e\"", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 39), - ..BaseNode::default() - }, - expression: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 1, 1, 39), - ..BaseNode::default() + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 39", + source: "\"\\xe6\\x97\\xa5\\xe6\\x9c\\xac\\xe8\\xaa\\x9e\"", + }, + }, + expression: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 39", + source: "\"\\xe6\\x97\\xa5\\xe6\\x9c\\xac\\xe8\\xaa\\x9e\"", + }, + }, + value: "日本語", + }, + ), }, - value: "日本語".to_string() - }) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } #[test] fn string_with_mixed_values() { let mut p = Parser::new(r#""hello 日x本 \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e \xc2\xb5s""#); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 1, 63), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 63", + source: "\"hello 日x本 \\xe6\\x97\\xa5\\xe6\\x9c\\xac\\xe8\\xaa\\x9e \\xc2\\xb5s\"", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 1, 63), - ..BaseNode::default() - }, - expression: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 1, 1, 63), - ..BaseNode::default() + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 63", + source: "\"hello 日x本 \\xe6\\x97\\xa5\\xe6\\x9c\\xac\\xe8\\xaa\\x9e \\xc2\\xb5s\"", + }, + }, + expression: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 63", + source: "\"hello 日x本 \\xe6\\x97\\xa5\\xe6\\x9c\\xac\\xe8\\xaa\\x9e \\xc2\\xb5s\"", + }, + }, + value: "hello 日x本 日本語 µs", + }, + ), }, - value: "hello 日x本 日本語 µs".to_string() - }) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] @@ -637,25 +940,47 @@ dollar curly bracket \${ ""#, ); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { - base: BaseNode {location: loc.get(1, 1, 7, 2), .. BaseNode::default() }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 7, column: 2", + source: "\"newline \\n\ncarriage return \\r\nhorizontal tab \\t\ndouble quote \\\"\nbackslash \\\\\ndollar curly bracket \\${\n\"", + }, + }, + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode {location: loc.get(1, 1, 7, 2), .. BaseNode::default() }, - expression: Expression::StringLit(StringLit { - base: BaseNode {location: loc.get(1, 1, 7, 2), .. BaseNode::default() }, - value: "newline \n\ncarriage return \r\nhorizontal tab \t\ndouble quote \"\nbackslash \\\ndollar curly bracket ${\n".to_string() - }) - }))], - eof: vec![], - }, - ) + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 7, column: 2", + source: "\"newline \\n\ncarriage return \\r\nhorizontal tab \\t\ndouble quote \\\"\nbackslash \\\\\ndollar curly bracket \\${\n\"", + }, + }, + expression: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 7, column: 2", + source: "\"newline \\n\ncarriage return \\r\nhorizontal tab \\t\ndouble quote \\\"\nbackslash \\\\\ndollar curly bracket \\${\n\"", + }, + }, + value: "newline \n\ncarriage return \r\nhorizontal tab \t\ndouble quote \"\nbackslash \\\ndollar curly bracket ${\n", + }, + ), + }, + ), + ], + eof: [], + } + "#]].assert_debug_eq(&parsed); } #[test] @@ -668,32 +993,46 @@ string" "#, ); let parsed = p.parse_file("".to_string()); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + expect![[r#" File { base: BaseNode { - location: loc.get(1, 1, 4, 8), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 4, column: 8", + source: "\"\n this is a\nmultiline\nstring\"", + }, }, - name: "".to_string(), - metadata: "parser-type=rust".to_string(), + name: "", + metadata: "parser-type=rust", package: None, - imports: vec![], - body: vec![Statement::Expr(Box::new(ExprStmt { - base: BaseNode { - location: loc.get(1, 1, 4, 8), - ..BaseNode::default() - }, - expression: Expression::StringLit(StringLit { - base: BaseNode { - location: loc.get(1, 1, 4, 8), - ..BaseNode::default() + imports: [], + body: [ + Expr( + ExprStmt { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 4, column: 8", + source: "\"\n this is a\nmultiline\nstring\"", + }, + }, + expression: StringLit( + StringLit { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 4, column: 8", + source: "\"\n this is a\nmultiline\nstring\"", + }, + }, + value: "\n this is a\nmultiline\nstring", + }, + ), }, - value: "\n this is a\nmultiline\nstring".to_string() - }) - }))], - eof: vec![], - }, - ) + ), + ], + eof: [], + } + "#]] + .assert_debug_eq(&parsed); } diff --git a/libflux/flux-core/src/parser/tests/types.rs b/libflux/flux-core/src/parser/tests/types.rs index 377e2e404c..52d3d9ef92 100644 --- a/libflux/flux-core/src/parser/tests/types.rs +++ b/libflux/flux-core/src/parser/tests/types.rs @@ -1,618 +1,867 @@ -use pretty_assertions::assert_eq; - use super::*; -use crate::ast::{self, tests::Locator}; +use crate::ast; + +fn test_type_expression(source: &str, expect: expect_test::Expect) { + let mut parser = Parser::new(source); + let parsed = parser.parse_type_expression(); + + expect.assert_debug_eq(&parsed); +} #[test] fn test_parse_type_expression() { - let mut p = Parser::new(r#"(a:T, b:T) => T where T: Addable + Divisible"#); - let parsed = p.parse_type_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - TypeExpression { - base: BaseNode { - location: loc.get(1, 1, 1, 45), - ..BaseNode::default() - }, - monotype: MonoType::Function(Box::new(FunctionType { + test_type_expression( + r#"(a:T, b:T) => T where T: Addable + Divisible"#, + expect![[r#" + TypeExpression { base: BaseNode { - location: loc.get(1, 1, 1, 16), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 45", + source: "(a:T, b:T) => T where T: Addable + Divisible", + }, }, - parameters: vec![ - ParameterType::Required { + monotype: Function( + FunctionType { base: BaseNode { - location: loc.get(1, 2, 1, 5), - ..BaseNode::default() - }, - name: Identifier { - base: BaseNode { - location: loc.get(1, 2, 1, 3), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 16", + source: "(a:T, b:T) => T", }, - name: "a".to_string(), }, - monotype: MonoType::Tvar(TvarType { - base: BaseNode { - location: loc.get(1, 4, 1, 5), - ..BaseNode::default() + parameters: [ + Required { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 5", + source: "a:T", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 3", + source: "a", + }, + }, + name: "a", + }, + monotype: Tvar( + TvarType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 5", + source: "T", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 5", + source: "T", + }, + }, + name: "T", + }, + }, + ), }, - name: Identifier { + Required { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 10", + source: "b:T", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 8", + source: "b", + }, + }, + name: "b", + }, + monotype: Tvar( + TvarType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 10", + source: "T", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 10", + source: "T", + }, + }, + name: "T", + }, + }, + ), + }, + ], + monotype: Tvar( + TvarType { base: BaseNode { - location: loc.get(1, 4, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 16", + source: "T", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 16", + source: "T", + }, + }, + name: "T", }, - name: "T".to_string(), }, - }), + ), }, - ParameterType::Required { + ), + constraints: [ + TypeConstraint { base: BaseNode { - location: loc.get(1, 7, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 23", + end: "line: 1, column: 45", + source: "T: Addable + Divisible", + }, }, - name: Identifier { + tvar: Identifier { base: BaseNode { - location: loc.get(1, 7, 1, 8), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 23", + end: "line: 1, column: 24", + source: "T", + }, }, - name: "b".to_string(), + name: "T", }, - monotype: MonoType::Tvar(TvarType { - base: BaseNode { - location: loc.get(1, 9, 1, 10), - ..BaseNode::default() + kinds: [ + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 26", + end: "line: 1, column: 33", + source: "Addable", + }, + }, + name: "Addable", }, - name: Identifier { + Identifier { base: BaseNode { - location: loc.get(1, 9, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 36", + end: "line: 1, column: 45", + source: "Divisible", + }, }, - name: "T".to_string(), + name: "Divisible", }, - }), - }, - ], - monotype: MonoType::Tvar(TvarType { - base: BaseNode { - location: loc.get(1, 15, 1, 16), - ..BaseNode::default() - }, - name: Identifier { - base: BaseNode { - location: loc.get(1, 15, 1, 16), - ..BaseNode::default() - }, - name: "T".to_string(), - }, - }), - })), - constraints: vec![TypeConstraint { - base: BaseNode { - location: loc.get(1, 23, 1, 45), - ..BaseNode::default() - }, - tvar: Identifier { - base: BaseNode { - location: loc.get(1, 23, 1, 24), - ..BaseNode::default() - }, - name: "T".to_string(), - }, - kinds: vec![ - Identifier { - base: BaseNode { - location: loc.get(1, 26, 1, 33), - ..BaseNode::default() - }, - name: "Addable".to_string(), - }, - Identifier { - base: BaseNode { - location: loc.get(1, 36, 1, 45), - ..BaseNode::default() - }, - name: "Divisible".to_string(), + ], }, ], - }], - }, - ) + } + "#]], + ); } #[test] fn test_parse_type_expression_tvar() { - let mut p = Parser::new(r#"A"#); - let parsed = p.parse_type_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_type_expression( + r#"A"#, + expect![[r#" TypeExpression { base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() - }, - monotype: MonoType::Tvar(TvarType { - base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "A", }, - name: Identifier { + }, + monotype: Tvar( + TvarType { base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "A", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "A", + }, + }, + name: "A", }, - name: "A".to_string(), - } - }), - constraints: vec![], - }, - ) + }, + ), + constraints: [], + } + "#]], + ); } #[test] fn test_parse_type_expression_int() { - let mut p = Parser::new(r#"int"#); - let parsed = p.parse_type_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_type_expression( + r#"int"#, + expect![[r#" TypeExpression { base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() - }, - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "int", }, - name: Identifier { + }, + monotype: Basic( + NamedType { base: BaseNode { - location: loc.get(1, 1, 1, 4), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "int", + }, }, - name: "int".to_string(), - } - }), - constraints: vec![], - }, - ) + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 4", + source: "int", + }, + }, + name: "int", + }, + }, + ), + constraints: [], + } + "#]], + ); } #[test] fn test_parse_type_expression_uint() { - let mut p = Parser::new(r#"uint"#); - let parsed = p.parse_type_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_type_expression( + r#"uint"#, + expect![[r#" TypeExpression { base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() - }, - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "uint", }, - name: Identifier { - name: "uint".to_string(), + }, + monotype: Basic( + NamedType { base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "uint", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "uint", + }, + }, + name: "uint", }, - } - }), - constraints: vec![], - }, - ) + }, + ), + constraints: [], + } + "#]], + ); } #[test] fn test_parse_type_expression_float() { - let mut p = Parser::new(r#"float"#); - let parsed = p.parse_type_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_type_expression( + r#"float"#, + expect![[r#" TypeExpression { base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "float", }, - name: Identifier { - name: "float".to_string(), + }, + monotype: Basic( + NamedType { base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "float", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "float", + }, + }, + name: "float", }, - } - }), - constraints: vec![], - }, - ) + }, + ), + constraints: [], + } + "#]], + ); } #[test] fn test_parse_type_expression_string() { - let mut p = Parser::new(r#"string"#); - let parsed = p.parse_type_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_type_expression( + r#"string"#, + expect![[r#" TypeExpression { base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() - }, - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "string", }, - name: Identifier { - name: "string".to_string(), + }, + monotype: Basic( + NamedType { base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "string", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "string", + }, + }, + name: "string", }, - } - }), - constraints: vec![], - }, - ) + }, + ), + constraints: [], + } + "#]], + ); } #[test] fn test_parse_type_expression_bool() { - let mut p = Parser::new(r#"bool"#); - let parsed = p.parse_type_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_type_expression( + r#"bool"#, + expect![[r#" TypeExpression { base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() - }, - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "bool", }, - name: Identifier { - name: "bool".to_string(), + }, + monotype: Basic( + NamedType { base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "bool", + }, }, - } - }), - constraints: vec![], - }, - ) + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "bool", + }, + }, + name: "bool", + }, + }, + ), + constraints: [], + } + "#]], + ); } #[test] fn test_parse_type_expression_time() { - let mut p = Parser::new(r#"time"#); - let parsed = p.parse_type_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_type_expression( + r#"time"#, + expect![[r#" TypeExpression { base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() - }, - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "time", }, - name: Identifier { - name: "time".to_string(), + }, + monotype: Basic( + NamedType { base: BaseNode { - location: loc.get(1, 1, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "time", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "time", + }, + }, + name: "time", }, - } - }), - constraints: vec![], - }, - ) + }, + ), + constraints: [], + } + "#]], + ); } #[test] fn test_parse_type_expression_duration() { - let mut p = Parser::new(r#"duration"#); - let parsed = p.parse_type_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_type_expression( + r#"duration"#, + expect![[r#" TypeExpression { base: BaseNode { - location: loc.get(1, 1, 1, 9), - ..BaseNode::default() - }, - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 1, 1, 9), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 9", + source: "duration", }, - name: Identifier { - name: "duration".to_string(), + }, + monotype: Basic( + NamedType { base: BaseNode { - location: loc.get(1, 1, 1, 9), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 9", + source: "duration", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 9", + source: "duration", + }, + }, + name: "duration", }, - } - }), - constraints: vec![], - }, - ) + }, + ), + constraints: [], + } + "#]], + ); } #[test] fn test_parse_type_expression_bytes() { - let mut p = Parser::new(r#"bytes"#); - let parsed = p.parse_type_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_type_expression( + r#"bytes"#, + expect![[r#" TypeExpression { base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "bytes", }, - name: Identifier { - name: "bytes".to_string(), + }, + monotype: Basic( + NamedType { base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "bytes", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "bytes", + }, + }, + name: "bytes", }, - } - }), - constraints: vec![], - }, - ) + }, + ), + constraints: [], + } + "#]], + ); } #[test] fn test_parse_type_expression_regexp() { - let mut p = Parser::new(r#"regexp"#); - let parsed = p.parse_type_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_type_expression( + r#"regexp"#, + expect![[r#" TypeExpression { base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() - }, - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "regexp", }, - name: Identifier { - name: "regexp".to_string(), + }, + monotype: Basic( + NamedType { base: BaseNode { - location: loc.get(1, 1, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "regexp", + }, }, - } - }), - constraints: vec![], - }, - ) + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 7", + source: "regexp", + }, + }, + name: "regexp", + }, + }, + ), + constraints: [], + } + "#]], + ); } #[test] fn test_parse_type_expression_array_int() { - let mut p = Parser::new(r#"[int]"#); - let parsed = p.parse_type_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_type_expression( + r#"[int]"#, + expect![[r#" TypeExpression { base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() - }, - monotype: MonoType::Array(Box::new(ArrayType { - base: BaseNode { - location: loc.get(1, 1, 1, 6), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "[int]", }, - element: MonoType::Basic(NamedType { + }, + monotype: Array( + ArrayType { base: BaseNode { - location: loc.get(1, 2, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 6", + source: "[int]", + }, }, - name: Identifier { - base: BaseNode { - location: loc.get(1, 2, 1, 5), - ..BaseNode::default() - }, - name: "int".to_string(), - } - }) - })), - constraints: vec![], - }, - ) + element: Basic( + NamedType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 5", + source: "int", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 5", + source: "int", + }, + }, + name: "int", + }, + }, + ), + }, + ), + constraints: [], + } + "#]], + ); } #[test] fn test_parse_type_expression_array_string() { - let mut p = Parser::new(r#"[string]"#); - let parsed = p.parse_type_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_type_expression( + r#"[string]"#, + expect![[r#" TypeExpression { base: BaseNode { - location: loc.get(1, 1, 1, 9), - ..BaseNode::default() - }, - monotype: MonoType::Array(Box::new(ArrayType { - base: BaseNode { - location: loc.get(1, 1, 1, 9), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 9", + source: "[string]", }, - element: MonoType::Basic(NamedType { + }, + monotype: Array( + ArrayType { base: BaseNode { - location: loc.get(1, 2, 1, 8), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 9", + source: "[string]", + }, }, - name: Identifier { - base: BaseNode { - location: loc.get(1, 2, 1, 8), - ..BaseNode::default() - }, - name: "string".to_string(), - } - }) - })), - constraints: vec![], + element: Basic( + NamedType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 8", + source: "string", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 8", + source: "string", + }, + }, + name: "string", + }, + }, + ), + }, + ), + constraints: [], } - ) + "#]], + ); } #[test] fn test_parse_type_expression_dict() { - let mut p = Parser::new(r#"[string:int]"#); - let parsed = p.parse_type_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_type_expression( + r#"[string:int]"#, + expect![[r#" TypeExpression { base: BaseNode { - location: loc.get(1, 1, 1, 13), - ..BaseNode::default() - }, - monotype: MonoType::Dict(Box::new(DictType { - base: BaseNode { - location: loc.get(1, 1, 1, 13), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "[string:int]", }, - key: MonoType::Basic(NamedType { + }, + monotype: Dict( + DictType { base: BaseNode { - location: loc.get(1, 2, 1, 8), - ..BaseNode::default() - }, - name: Identifier { - base: BaseNode { - location: loc.get(1, 2, 1, 8), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 13", + source: "[string:int]", }, - name: "string".to_string(), - } - }), - val: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 9, 1, 12), - ..BaseNode::default() }, - name: Identifier { - base: BaseNode { - location: loc.get(1, 9, 1, 12), - ..BaseNode::default() - }, - name: "int".to_string(), - } - }), - })), - constraints: vec![], + key: Basic( + NamedType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 8", + source: "string", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 8", + source: "string", + }, + }, + name: "string", + }, + }, + ), + val: Basic( + NamedType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 12", + source: "int", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 12", + source: "int", + }, + }, + name: "int", + }, + }, + ), + }, + ), + constraints: [], } - ) + "#]], + ); } #[test] fn test_parse_record_type_only_properties() { let mut p = Parser::new(r#"{a:int, b:uint}"#); let parsed = p.parse_record_type(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - MonoType::Record(RecordType { - base: BaseNode { - location: loc.get(1, 1, 1, 16), - ..BaseNode::default() - }, - tvar: None, - properties: vec![ - PropertyType { - base: BaseNode { - location: loc.get(1, 2, 1, 7), - ..BaseNode::default() + expect![[r#" + Record( + RecordType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 16", + source: "{a:int, b:uint}", }, - name: Identifier { - name: "a".to_string(), - base: BaseNode { - location: loc.get(1, 2, 1, 3), - ..BaseNode::default() - }, - } - .into(), - monotype: MonoType::Basic(NamedType { + }, + tvar: None, + properties: [ + PropertyType { base: BaseNode { - location: loc.get(1, 4, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 7", + source: "a:int", + }, }, - name: Identifier { - name: "int".to_string(), - base: BaseNode { - location: loc.get(1, 4, 1, 7), - ..BaseNode::default() + name: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 3", + source: "a", + }, + }, + name: "a", }, - } - }) - }, - PropertyType { - base: BaseNode { - location: loc.get(1, 9, 1, 15), - ..BaseNode::default() + ), + monotype: Basic( + NamedType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 7", + source: "int", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 7", + source: "int", + }, + }, + name: "int", + }, + }, + ), }, - name: Identifier { - name: "b".to_string(), - base: BaseNode { - location: loc.get(1, 9, 1, 10), - ..BaseNode::default() - }, - } - .into(), - monotype: MonoType::Basic(NamedType { + PropertyType { base: BaseNode { - location: loc.get(1, 11, 1, 15), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 15", + source: "b:uint", + }, }, - name: Identifier { - name: "uint".to_string(), - base: BaseNode { - location: loc.get(1, 11, 1, 15), - ..BaseNode::default() - }, - } - }) - } - ] - },) - ) + name: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 10", + source: "b", + }, + }, + name: "b", + }, + ), + monotype: Basic( + NamedType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 15", + source: "uint", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 15", + source: "uint", + }, + }, + name: "uint", + }, + }, + ), + }, + ], + }, + ) + "#]] + .assert_debug_eq(&parsed); } #[test] @@ -624,62 +873,29 @@ fn test_parse_record_type_string_literal_property() { RecordType { base: BaseNode { location: SourceLocation { - file: None, - start: Position { - line: 1, - column: 1, - }, - end: Position { - line: 1, - column: 18, - }, - source: Some( - "{\"a\":int, b:uint}", - ), + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "{\"a\":int, b:uint}", }, - comments: [], - errors: [], }, tvar: None, properties: [ PropertyType { base: BaseNode { location: SourceLocation { - file: None, - start: Position { - line: 1, - column: 2, - }, - end: Position { - line: 1, - column: 9, - }, - source: Some( - "\"a\":int", - ), + start: "line: 1, column: 2", + end: "line: 1, column: 9", + source: "\"a\":int", }, - comments: [], - errors: [], }, name: StringLit( StringLit { base: BaseNode { location: SourceLocation { - file: None, - start: Position { - line: 1, - column: 2, - }, - end: Position { - line: 1, - column: 5, - }, - source: Some( - "\"a\"", - ), + start: "line: 1, column: 2", + end: "line: 1, column: 5", + source: "\"a\"", }, - comments: [], - errors: [], }, value: "a", }, @@ -688,40 +904,18 @@ fn test_parse_record_type_string_literal_property() { NamedType { base: BaseNode { location: SourceLocation { - file: None, - start: Position { - line: 1, - column: 6, - }, - end: Position { - line: 1, - column: 9, - }, - source: Some( - "int", - ), + start: "line: 1, column: 6", + end: "line: 1, column: 9", + source: "int", }, - comments: [], - errors: [], }, name: Identifier { base: BaseNode { location: SourceLocation { - file: None, - start: Position { - line: 1, - column: 6, - }, - end: Position { - line: 1, - column: 9, - }, - source: Some( - "int", - ), + start: "line: 1, column: 6", + end: "line: 1, column: 9", + source: "int", }, - comments: [], - errors: [], }, name: "int", }, @@ -731,41 +925,19 @@ fn test_parse_record_type_string_literal_property() { PropertyType { base: BaseNode { location: SourceLocation { - file: None, - start: Position { - line: 1, - column: 11, - }, - end: Position { - line: 1, - column: 17, - }, - source: Some( - "b:uint", - ), + start: "line: 1, column: 11", + end: "line: 1, column: 17", + source: "b:uint", }, - comments: [], - errors: [], }, name: Identifier( Identifier { base: BaseNode { location: SourceLocation { - file: None, - start: Position { - line: 1, - column: 11, - }, - end: Position { - line: 1, - column: 12, - }, - source: Some( - "b", - ), + start: "line: 1, column: 11", + end: "line: 1, column: 12", + source: "b", }, - comments: [], - errors: [], }, name: "b", }, @@ -774,40 +946,18 @@ fn test_parse_record_type_string_literal_property() { NamedType { base: BaseNode { location: SourceLocation { - file: None, - start: Position { - line: 1, - column: 13, - }, - end: Position { - line: 1, - column: 17, - }, - source: Some( - "uint", - ), + start: "line: 1, column: 13", + end: "line: 1, column: 17", + source: "uint", }, - comments: [], - errors: [], }, name: Identifier { base: BaseNode { location: SourceLocation { - file: None, - start: Position { - line: 1, - column: 13, - }, - end: Position { - line: 1, - column: 17, - }, - source: Some( - "uint", - ), + start: "line: 1, column: 13", + end: "line: 1, column: 17", + source: "uint", }, - comments: [], - errors: [], }, name: "uint", }, @@ -825,653 +975,949 @@ fn test_parse_record_type_string_literal_property() { fn test_parse_record_type_trailing_comma() { let mut p = Parser::new(r#"{a:int,}"#); let parsed = p.parse_record_type(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - MonoType::Record(RecordType { - base: BaseNode { - location: loc.get(1, 1, 1, 9), - ..BaseNode::default() - }, - tvar: None, - properties: vec![PropertyType { + expect![[r#" + Record( + RecordType { base: BaseNode { - location: loc.get(1, 2, 1, 7), - ..BaseNode::default() - }, - name: Identifier { - name: "a".to_string(), - base: BaseNode { - location: loc.get(1, 2, 1, 3), - ..BaseNode::default() - }, - } - .into(), - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 4, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 9", + source: "{a:int,}", }, - name: Identifier { - name: "int".to_string(), + }, + tvar: None, + properties: [ + PropertyType { base: BaseNode { - location: loc.get(1, 4, 1, 7), - ..BaseNode::default() - }, - } - }) - },] - },) - ) + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 7", + source: "a:int", + }, + }, + name: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 3", + source: "a", + }, + }, + name: "a", + }, + ), + monotype: Basic( + NamedType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 7", + source: "int", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 7", + source: "int", + }, + }, + name: "int", + }, + }, + ), + }, + ], + }, + ) + "#]] + .assert_debug_eq(&parsed); } #[test] fn test_parse_record_type_invalid() { let mut p = Parser::new(r#"{a b}"#); let parsed = p.parse_record_type(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - MonoType::Record(RecordType { - base: BaseNode { - location: loc.get(1, 1, 1, 5), - errors: vec!["expected RBRACE, got IDENT".to_string()], - ..BaseNode::default() + expect![[r#" + Record( + RecordType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 5", + source: "{a b", + }, + errors: [ + "expected RBRACE, got IDENT", + ], + }, + tvar: None, + properties: [], }, - tvar: None, - properties: vec![], - }) - ) + ) + "#]] + .assert_debug_eq(&parsed); } #[test] fn test_parse_constraint_one_ident() { let mut p = Parser::new(r#"A : date"#); let parsed = p.parse_constraints(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - vec![TypeConstraint { - base: BaseNode { - location: loc.get(1, 1, 1, 9), - ..BaseNode::default() - }, - tvar: Identifier { + expect![[r#" + [ + TypeConstraint { base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 9", + source: "A : date", + }, }, - name: "A".to_string(), - }, - kinds: vec![Identifier { - base: BaseNode { - location: loc.get(1, 5, 1, 9), - ..BaseNode::default() + tvar: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "A", + }, + }, + name: "A", }, - name: "date".to_string(), - }] - }], - ) + kinds: [ + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 9", + source: "date", + }, + }, + name: "date", + }, + ], + }, + ] + "#]] + .assert_debug_eq(&parsed); } #[test] fn test_parse_record_type_blank() { let mut p = Parser::new(r#"{}"#); let parsed = p.parse_record_type(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - MonoType::Record(RecordType { - base: BaseNode { - location: loc.get(1, 1, 1, 3), - ..BaseNode::default() + expect![[r#" + Record( + RecordType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 3", + source: "{}", + }, + }, + tvar: None, + properties: [], }, - tvar: None, - properties: vec![], - },) - ) + ) + "#]] + .assert_debug_eq(&parsed); } #[test] fn test_parse_type_expression_function_with_no_params() { - let mut p = Parser::new(r#"() => int"#); - let parsed = p.parse_type_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_type_expression( + r#"() => int"#, + expect![[r#" TypeExpression { base: BaseNode { - location: loc.get(1, 1, 1, 10), - ..BaseNode::default() - }, - monotype: MonoType::Function(Box::new(FunctionType { - base: BaseNode { - location: loc.get(1, 1, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 10", + source: "() => int", }, - - parameters: vec![], - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 7, 1, 10), - ..BaseNode::default() - }, - name: Identifier { - base: BaseNode { - location: loc.get(1, 7, 1, 10), - ..BaseNode::default() - }, - name: "int".to_string(), - } - }), - })), - constraints: vec![], - }, - ) -} - -#[test] -fn test_parse_function_type_trailing_comma() { - let mut p = Parser::new(r#"(a:int,) => int"#); - let parsed = p.parse_type_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - TypeExpression { - base: BaseNode { - location: loc.get(1, 1, 1, 16), - ..BaseNode::default() }, - monotype: MonoType::Function(Box::new(FunctionType { - base: BaseNode { - location: loc.get(1, 1, 1, 16), - ..BaseNode::default() - }, - - parameters: vec![ParameterType::Required { + monotype: Function( + FunctionType { base: BaseNode { - location: loc.get(1, 2, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 10", + source: "() => int", + }, }, - name: Identifier { - base: BaseNode { - location: loc.get(1, 2, 1, 3), - ..BaseNode::default() - }, - name: "a".to_string(), - }, - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 4, 1, 7), - ..BaseNode::default() - }, - name: Identifier { + parameters: [], + monotype: Basic( + NamedType { base: BaseNode { - location: loc.get(1, 4, 1, 7), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 10", + source: "int", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 10", + source: "int", + }, + }, + name: "int", }, - name: "int".to_string(), }, - }), - },], - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 13, 1, 16), - ..BaseNode::default() - }, - name: Identifier { - base: BaseNode { - location: loc.get(1, 13, 1, 16), - ..BaseNode::default() - }, - name: "int".to_string(), - } - }), - })), - constraints: vec![], - }, - ) + ), + }, + ), + constraints: [], + } + "#]], + ); } #[test] -fn test_parse_type_expression_function_with_params() { - let mut p = Parser::new(r#"(A: int, B: uint) => int"#); - let parsed = p.parse_type_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, +fn test_parse_function_type_trailing_comma() { + test_type_expression( + r#"(a:int,) => int"#, + expect![[r#" TypeExpression { base: BaseNode { - location: loc.get(1, 1, 1, 25), - ..BaseNode::default() - }, - monotype: MonoType::Function(Box::new(FunctionType { - base: BaseNode { - location: loc.get(1, 1, 1, 25), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 16", + source: "(a:int,) => int", }, - parameters: vec![ - ParameterType::Required { - base: BaseNode { - location: loc.get(1, 2, 1, 8), - ..BaseNode::default() + }, + monotype: Function( + FunctionType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 16", + source: "(a:int,) => int", }, - name: Identifier { + }, + parameters: [ + Required { base: BaseNode { - location: loc.get(1, 2, 1, 3), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 7", + source: "a:int", + }, }, - name: "A".to_string(), + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 3", + source: "a", + }, + }, + name: "a", + }, + monotype: Basic( + NamedType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 7", + source: "int", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 7", + source: "int", + }, + }, + name: "int", + }, + }, + ), }, - monotype: MonoType::Basic(NamedType { + ], + monotype: Basic( + NamedType { base: BaseNode { - location: loc.get(1, 5, 1, 8), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 13", + end: "line: 1, column: 16", + source: "int", + }, }, name: Identifier { base: BaseNode { - location: loc.get(1, 5, 1, 8), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 13", + end: "line: 1, column: 16", + source: "int", + }, }, - name: "int".to_string(), + name: "int", }, - }), + }, + ), + }, + ), + constraints: [], + } + "#]], + ); +} + +#[test] +fn test_parse_type_expression_function_with_params() { + test_type_expression( + r#"(A: int, B: uint) => int"#, + expect![[r#" + TypeExpression { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 25", + source: "(A: int, B: uint) => int", + }, + }, + monotype: Function( + FunctionType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 25", + source: "(A: int, B: uint) => int", + }, }, - ParameterType::Required { - base: BaseNode { - location: loc.get(1, 10, 1, 17), - ..BaseNode::default() + parameters: [ + Required { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 8", + source: "A: int", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 3", + source: "A", + }, + }, + name: "A", + }, + monotype: Basic( + NamedType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 8", + source: "int", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 5", + end: "line: 1, column: 8", + source: "int", + }, + }, + name: "int", + }, + }, + ), }, - name: Identifier { + Required { base: BaseNode { - location: loc.get(1, 10, 1, 11), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 17", + source: "B: uint", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 10", + end: "line: 1, column: 11", + source: "B", + }, + }, + name: "B", }, - name: "B".to_string(), + monotype: Basic( + NamedType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 13", + end: "line: 1, column: 17", + source: "uint", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 13", + end: "line: 1, column: 17", + source: "uint", + }, + }, + name: "uint", + }, + }, + ), }, - monotype: MonoType::Basic(NamedType { + ], + monotype: Basic( + NamedType { base: BaseNode { - location: loc.get(1, 13, 1, 17), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 22", + end: "line: 1, column: 25", + source: "int", + }, }, name: Identifier { base: BaseNode { - location: loc.get(1, 13, 1, 17), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 22", + end: "line: 1, column: 25", + source: "int", + }, }, - name: "uint".to_string(), + name: "int", }, - }), - } - ], - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 22, 1, 25), - ..BaseNode::default() - }, - name: Identifier { - base: BaseNode { - location: loc.get(1, 22, 1, 25), - ..BaseNode::default() - }, - name: "int".to_string(), - } - }), - })), - constraints: vec![], - }, - ) + }, + ), + }, + ), + constraints: [], + } + "#]], + ); } // optional parameters like (.., ?n: ..) -> .. #[test] fn test_parse_type_expression_function_optional_params() { - let mut p = Parser::new(r#"(?A: int) => int"#); - let parsed = p.parse_type_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_type_expression( + r#"(?A: int) => int"#, + expect![[r#" TypeExpression { base: BaseNode { - location: loc.get(1, 1, 1, 17), - ..BaseNode::default() - }, - monotype: MonoType::Function(Box::new(FunctionType { - base: BaseNode { - location: loc.get(1, 1, 1, 17), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 17", + source: "(?A: int) => int", }, - parameters: vec![ParameterType::Optional { + }, + monotype: Function( + FunctionType { base: BaseNode { - location: loc.get(1, 2, 1, 9), - ..BaseNode::default() - }, - name: Identifier { - base: BaseNode { - location: loc.get(1, 3, 1, 4), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 17", + source: "(?A: int) => int", }, - name: "A".to_string(), }, - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 6, 1, 9), - ..BaseNode::default() + parameters: [ + Optional { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 9", + source: "?A: int", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 3", + end: "line: 1, column: 4", + source: "A", + }, + }, + name: "A", + }, + monotype: Basic( + NamedType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 9", + source: "int", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 6", + end: "line: 1, column: 9", + source: "int", + }, + }, + name: "int", + }, + }, + ), + default: None, }, - name: Identifier { + ], + monotype: Basic( + NamedType { base: BaseNode { - location: loc.get(1, 6, 1, 9), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 17", + source: "int", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 17", + source: "int", + }, + }, + name: "int", }, - name: "int".to_string(), }, - }), - default: None, - }], - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 14, 1, 17), - ..BaseNode::default() - }, - name: Identifier { - base: BaseNode { - location: loc.get(1, 14, 1, 17), - ..BaseNode::default() - }, - name: "int".to_string(), - } - }), - })), - constraints: vec![], - }, - ) + ), + }, + ), + constraints: [], + } + "#]], + ); } #[test] fn test_parse_type_expression_function_named_params() { - let mut p = Parser::new(r#"(<-A: int) => int"#); - let parsed = p.parse_type_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_type_expression( + r#"(<-A: int) => int"#, + expect![[r#" TypeExpression { base: BaseNode { - location: loc.get(1, 1, 1, 18), - ..BaseNode::default() - }, - monotype: MonoType::Function(Box::new(FunctionType { - base: BaseNode { - location: loc.get(1, 1, 1, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "(<-A: int) => int", }, - parameters: vec![ParameterType::Pipe { + }, + monotype: Function( + FunctionType { base: BaseNode { - location: loc.get(1, 2, 1, 10), - ..BaseNode::default() - }, - name: Some(Identifier { - base: BaseNode { - location: loc.get(1, 4, 1, 5), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "(<-A: int) => int", }, - name: "A".to_string(), - }), - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 7, 1, 10), - ..BaseNode::default() + }, + parameters: [ + Pipe { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 10", + source: "<-A: int", + }, + }, + name: Some( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 5", + source: "A", + }, + }, + name: "A", + }, + ), + monotype: Basic( + NamedType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 10", + source: "int", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 10", + source: "int", + }, + }, + name: "int", + }, + }, + ), }, - name: Identifier { + ], + monotype: Basic( + NamedType { base: BaseNode { - location: loc.get(1, 7, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 18", + source: "int", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 18", + source: "int", + }, + }, + name: "int", }, - name: "int".to_string(), }, - }), - }], - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 15, 1, 18), - ..BaseNode::default() - }, - name: Identifier { - base: BaseNode { - location: loc.get(1, 15, 1, 18), - ..BaseNode::default() - }, - name: "int".to_string(), - } - }), - })), - constraints: vec![], - }, - ) + ), + }, + ), + constraints: [], + } + "#]], + ); } #[test] fn test_parse_type_expression_function_unnamed_params() { - let mut p = Parser::new(r#"(<- : int) => int"#); - let parsed = p.parse_type_expression(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, + test_type_expression( + r#"(<- : int) => int"#, + expect![[r#" TypeExpression { base: BaseNode { - location: loc.get(1, 1, 1, 18), - ..BaseNode::default() - }, - monotype: MonoType::Function(Box::new(FunctionType { - base: BaseNode { - location: loc.get(1, 1, 1, 18), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "(<- : int) => int", }, - parameters: vec![ParameterType::Pipe { + }, + monotype: Function( + FunctionType { base: BaseNode { - location: loc.get(1, 2, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 18", + source: "(<- : int) => int", + }, }, - name: None, - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 7, 1, 10), - ..BaseNode::default() + parameters: [ + Pipe { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 10", + source: "<- : int", + }, + }, + name: None, + monotype: Basic( + NamedType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 10", + source: "int", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 7", + end: "line: 1, column: 10", + source: "int", + }, + }, + name: "int", + }, + }, + ), }, - name: Identifier { + ], + monotype: Basic( + NamedType { base: BaseNode { - location: loc.get(1, 7, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 18", + source: "int", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 15", + end: "line: 1, column: 18", + source: "int", + }, + }, + name: "int", }, - name: "int".to_string(), }, - }), - }], - monotype: MonoType::Basic(NamedType { - base: BaseNode { - location: loc.get(1, 15, 1, 18), - ..BaseNode::default() - }, - name: Identifier { - base: BaseNode { - location: loc.get(1, 15, 1, 18), - ..BaseNode::default() - }, - name: "int".to_string(), - } - }), - })), - constraints: vec![], - }, - ) + ), + }, + ), + constraints: [], + } + "#]], + ); } #[test] fn test_parse_constraint_two_ident() { let mut p = Parser::new(r#"A: Addable + Subtractable"#); let parsed = p.parse_constraints(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - vec![TypeConstraint { - base: BaseNode { - location: loc.get(1, 1, 1, 26), - ..BaseNode::default() - }, - tvar: Identifier { + expect![[r#" + [ + TypeConstraint { base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 26", + source: "A: Addable + Subtractable", + }, }, - name: "A".to_string(), - }, - kinds: vec![ - Identifier { + tvar: Identifier { base: BaseNode { - location: loc.get(1, 4, 1, 11), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "A", + }, }, - name: "Addable".to_string(), + name: "A", }, - Identifier { - base: BaseNode { - location: loc.get(1, 14, 1, 26), - ..BaseNode::default() + kinds: [ + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 11", + source: "Addable", + }, + }, + name: "Addable", + }, + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 14", + end: "line: 1, column: 26", + source: "Subtractable", + }, + }, + name: "Subtractable", }, - name: "Subtractable".to_string(), - } - ] - }], - ) + ], + }, + ] + "#]] + .assert_debug_eq(&parsed); } #[test] fn test_parse_constraint_two_con() { let mut p = Parser::new(r#"A: Addable, B: Subtractable"#); let parsed = p.parse_constraints(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - vec![ + expect![[r#" + [ TypeConstraint { base: BaseNode { - location: loc.get(1, 1, 1, 11), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 11", + source: "A: Addable", + }, }, tvar: Identifier { base: BaseNode { - location: loc.get(1, 1, 1, 2), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 2", + source: "A", + }, }, - name: "A".to_string(), + name: "A", }, - kinds: vec![Identifier { - base: BaseNode { - location: loc.get(1, 4, 1, 11), - ..BaseNode::default() + kinds: [ + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 4", + end: "line: 1, column: 11", + source: "Addable", + }, + }, + name: "Addable", }, - name: "Addable".to_string(), - }] + ], }, TypeConstraint { base: BaseNode { - location: loc.get(1, 13, 1, 28), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 13", + end: "line: 1, column: 28", + source: "B: Subtractable", + }, }, tvar: Identifier { base: BaseNode { - location: loc.get(1, 13, 1, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 13", + end: "line: 1, column: 14", + source: "B", + }, }, - name: "B".to_string(), + name: "B", }, - kinds: vec![Identifier { - base: BaseNode { - location: loc.get(1, 16, 1, 28), - ..BaseNode::default() + kinds: [ + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 16", + end: "line: 1, column: 28", + source: "Subtractable", + }, + }, + name: "Subtractable", }, - name: "Subtractable".to_string(), - }] - } - ], - ) + ], + }, + ] + "#]] + .assert_debug_eq(&parsed); } #[test] fn test_parse_record_type_tvar_properties() { let mut p = Parser::new(r#"{A with a:int, b:uint}"#); let parsed = p.parse_record_type(); - let loc = Locator::new(p.source); - assert_eq!( - parsed, - MonoType::Record(RecordType { - base: BaseNode { - location: loc.get(1, 1, 1, 23), - ..BaseNode::default() - }, - tvar: Some(Identifier { + + expect![[r#" + Record( + RecordType { base: BaseNode { - location: loc.get(1, 2, 1, 3), - ..BaseNode::default() - }, - name: "A".to_string(), - }), - properties: vec![ - PropertyType { - base: BaseNode { - location: loc.get(1, 9, 1, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 1", + end: "line: 1, column: 23", + source: "{A with a:int, b:uint}", }, - name: Identifier { - name: "a".to_string(), + }, + tvar: Some( + Identifier { base: BaseNode { - location: loc.get(1, 9, 1, 10), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 2", + end: "line: 1, column: 3", + source: "A", + }, }, - } - .into(), - monotype: MonoType::Basic(NamedType { + name: "A", + }, + ), + properties: [ + PropertyType { base: BaseNode { - location: loc.get(1, 11, 1, 14), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 14", + source: "a:int", + }, }, - name: Identifier { - name: "int".to_string(), - base: BaseNode { - location: loc.get(1, 11, 1, 14), - ..BaseNode::default() + name: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 9", + end: "line: 1, column: 10", + source: "a", + }, + }, + name: "a", }, - } - }) - }, - PropertyType { - base: BaseNode { - location: loc.get(1, 16, 1, 22), - ..BaseNode::default() + ), + monotype: Basic( + NamedType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 14", + source: "int", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 11", + end: "line: 1, column: 14", + source: "int", + }, + }, + name: "int", + }, + }, + ), }, - name: Identifier { - name: "b".to_string(), - base: BaseNode { - location: loc.get(1, 16, 1, 17), - ..BaseNode::default() - }, - } - .into(), - monotype: MonoType::Basic(NamedType { + PropertyType { base: BaseNode { - location: loc.get(1, 18, 1, 22), - ..BaseNode::default() + location: SourceLocation { + start: "line: 1, column: 16", + end: "line: 1, column: 22", + source: "b:uint", + }, }, - name: Identifier { - name: "uint".to_string(), - base: BaseNode { - location: loc.get(1, 18, 1, 22), - ..BaseNode::default() - }, - } - }) - } - ] - },) - ) + name: Identifier( + Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 16", + end: "line: 1, column: 17", + source: "b", + }, + }, + name: "b", + }, + ), + monotype: Basic( + NamedType { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 18", + end: "line: 1, column: 22", + source: "uint", + }, + }, + name: Identifier { + base: BaseNode { + location: SourceLocation { + start: "line: 1, column: 18", + end: "line: 1, column: 22", + source: "uint", + }, + }, + name: "uint", + }, + }, + ), + }, + ], + }, + ) + "#]] + .assert_debug_eq(&parsed); } #[test] diff --git a/libflux/go/libflux/buildinfo.gen.go b/libflux/go/libflux/buildinfo.gen.go index 2b1887265d..6020af8b7e 100644 --- a/libflux/go/libflux/buildinfo.gen.go +++ b/libflux/go/libflux/buildinfo.gen.go @@ -17,7 +17,7 @@ var sourceHashes = map[string]string{ "libflux/Cargo.toml": "91ac4e8b467440c6e8a9438011de0e7b78c2732403bb067d4dd31539ac8a90c1", "libflux/flux-core/Cargo.toml": "75dcc5858ab7c9f8c28e2b6d072ceceaaea7cc12d7913003ac93c2e93800b24a", "libflux/flux-core/src/ast/check/mod.rs": "14ceca38c9c57c2a3fd56a8eca23616128badcc79708238cef17788c729bd825", - "libflux/flux-core/src/ast/mod.rs": "78b485774e015a2c73419fb91c750b58295c71027e722e80239d43827aed6a4b", + "libflux/flux-core/src/ast/mod.rs": "53a22049c37450669757b7bdd1dca3a030df1fc1f0db44d303ce642452d5a33c", "libflux/flux-core/src/ast/walk/mod.rs": "76b93aa401766a680474141c280fab35af096efb0686f9560d54ffd66187b37d", "libflux/flux-core/src/bin/README.md": "c1245a4938c923d065647b4dc4f7e19486e85c93d868ef2f7f47ddff62ec81df", "libflux/flux-core/src/bin/analyze_query_log.rs": "8fb616be4c9473e8347d34ceb4051695c1922590caa60958c7318d8e52cddc58",