Skip to content

Commit

Permalink
feat: function call argument parser with newline and indentation (#1328)
Browse files Browse the repository at this point in the history
feat: function call argument parser with newline and identation

Signed-off-by: peefy <xpf6677@163.com>
  • Loading branch information
Peefy authored May 17, 2024
1 parent f5903e7 commit fa685fa
Show file tree
Hide file tree
Showing 17 changed files with 569 additions and 309 deletions.
50 changes: 44 additions & 6 deletions kclvm/parser/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use kclvm_ast::token::{BinOpToken, DelimToken, TokenKind, VALID_SPACES_LENGTH};
use kclvm_span::symbol::kw;

/// Parser implementation of expressions, which consists of sub-expressions,
/// operand and tokens. Like the general LL1 paser, parser constantly looking for
/// operand and tokens. Like the general LL1 parser, parser constantly looking for
/// left-side derivation, priority is specified by matching code explicitly.
/// The entrances of expression parsing are `parse_exprlist` and `parse_expr`.
/// TODO: operand design is quite complex, can be simplified later.
Expand Down Expand Up @@ -427,11 +427,28 @@ impl<'a> Parser<'a> {
),
}

let has_newline = if self.token.kind == TokenKind::Newline {
self.skip_newlines();
self.clean_all_indentations();
if self.token.kind == TokenKind::CloseDelim(DelimToken::Paren) {
// bump bracket close delim token `)`
self.bump();
return CallExpr {
func,
args: vec![],
keywords: vec![],
};
}
true
} else {
false
};

// arguments or empty
let (args, keywords) = if self.token.kind == TokenKind::CloseDelim(DelimToken::Paren) {
(Vec::new(), Vec::new())
} else {
self.parse_arguments_expr()
self.parse_arguments_expr(has_newline)
};

// [COMMA]
Expand Down Expand Up @@ -2011,17 +2028,36 @@ impl<'a> Parser<'a> {

/// Syntax:
/// arguments: argument (COMMA argument)*
fn parse_arguments_expr(&mut self) -> (Vec<NodeRef<Expr>>, Vec<NodeRef<Keyword>>) {
fn parse_arguments_expr(
&mut self,
has_newline: bool,
) -> (Vec<NodeRef<Expr>>, Vec<NodeRef<Keyword>>) {
let mut args: Vec<NodeRef<Expr>> = Vec::new();
let mut keywords: Vec<NodeRef<Keyword>> = Vec::new();
let mut has_keyword = false;
let is_terminator = |token: &kclvm_ast::token::Token| match &token.kind {
TokenKind::CloseDelim(DelimToken::Paren) | TokenKind::Eof => true,
TokenKind::Newline if !has_newline => true,
_ => token.is_keyword(kw::For),
};

loop {
let marker = self.mark();
self.clean_all_indentations();
if is_terminator(&self.token) {
break;
}
// Record the argument expression start token.
let token = self.token;
match self.parse_argument_expr() {
Either::Left(expr) => {
args.push(Box::new(expr));
if matches!(expr.node, Expr::Missing(_)) {
self.sess
.struct_token_error(&[TokenKind::Comma.into()], self.token);
self.bump();
} else {
args.push(Box::new(expr));
}
if has_keyword {
self.sess.struct_span_error(
"positional argument follows keyword argument",
Expand All @@ -2037,9 +2073,11 @@ impl<'a> Parser<'a> {

if self.token.kind == TokenKind::Comma {
self.bump();
} else {
break;
}
if has_newline {
self.skip_newlines();
}
self.drop(marker);
}

(args, keywords)
Expand Down
25 changes: 25 additions & 0 deletions kclvm/parser/src/tests/error_recovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,31 @@ parse_expr_snapshot! { call_recovery_4, r#"a(a.ba=1,2)"# }
parse_expr_snapshot! { call_recovery_5, r#"a(a.b+a=1,2)"# }
parse_expr_snapshot! { call_recovery_6, r#"a(a-1.b=1)"# }
parse_expr_snapshot! { call_recovery_7, r#"a(type="list", "key")"# }
parse_expr_snapshot! { call_recovery_8, r#"a(
1,2
)"# }
parse_expr_snapshot! { call_recovery_9, r#"a(1,2
)"# }
parse_expr_snapshot! { call_recovery_10, r#"a(
1,
2
)"# }
parse_expr_snapshot! { call_recovery_11, r#"a(
1,
2,
)"# }
parse_expr_snapshot! { call_recovery_12, r#"a(
1,
2,
)"# }
parse_expr_snapshot! { call_recovery_13, r#"a(
1,,
2,
)"# }
parse_expr_snapshot! { call_recovery_14, r#"a(
1,
2,
]"# }
parse_expr_snapshot! { schema_recovery_0, r#"s {"# }
parse_expr_snapshot! { schema_recovery_1, r#"s {a=1"# }
parse_expr_snapshot! { schema_recovery_2, r#"s.0 {a=1}"# }
Expand Down
2 changes: 0 additions & 2 deletions kclvm/parser/src/tests/snapshots/Makefile

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,7 @@ Node {
end_line: 1,
end_column: 1,
},
args: [
Node {
node: Missing(
MissingExpr,
),
filename: "",
line: 1,
column: 2,
end_line: 1,
end_column: 2,
},
],
args: [],
keywords: [],
},
),
Expand All @@ -49,4 +38,3 @@ Node {
end_line: 1,
end_column: 2,
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
source: parser/src/tests/error_recovery.rs
expression: "crate::tests::parsing_expr_string(r#\"a(\n 1,\n 2\n)\"#)"
---
Node {
node: Call(
CallExpr {
func: Node {
node: Identifier(
Identifier {
names: [
Node {
node: "a",
filename: "",
line: 1,
column: 0,
end_line: 1,
end_column: 1,
},
],
pkgpath: "",
ctx: Load,
},
),
filename: "",
line: 1,
column: 0,
end_line: 1,
end_column: 1,
},
args: [
Node {
node: NumberLit(
NumberLit {
binary_suffix: None,
value: Int(
1,
),
},
),
filename: "",
line: 2,
column: 4,
end_line: 2,
end_column: 5,
},
Node {
node: NumberLit(
NumberLit {
binary_suffix: None,
value: Int(
2,
),
},
),
filename: "",
line: 3,
column: 4,
end_line: 3,
end_column: 5,
},
],
keywords: [],
},
),
filename: "",
line: 1,
column: 0,
end_line: 4,
end_column: 1,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
source: parser/src/tests/error_recovery.rs
expression: "crate::tests::parsing_expr_string(r#\"a(\n 1,\n2,\n)\"#)"
---
Node {
node: Call(
CallExpr {
func: Node {
node: Identifier(
Identifier {
names: [
Node {
node: "a",
filename: "",
line: 1,
column: 0,
end_line: 1,
end_column: 1,
},
],
pkgpath: "",
ctx: Load,
},
),
filename: "",
line: 1,
column: 0,
end_line: 1,
end_column: 1,
},
args: [
Node {
node: NumberLit(
NumberLit {
binary_suffix: None,
value: Int(
1,
),
},
),
filename: "",
line: 2,
column: 4,
end_line: 2,
end_column: 5,
},
Node {
node: NumberLit(
NumberLit {
binary_suffix: None,
value: Int(
2,
),
},
),
filename: "",
line: 3,
column: 0,
end_line: 3,
end_column: 1,
},
],
keywords: [],
},
),
filename: "",
line: 1,
column: 0,
end_line: 4,
end_column: 1,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
source: parser/src/tests/error_recovery.rs
expression: "crate::tests::parsing_expr_string(r#\"a(\n 1,\n2,\n)\"#)"
---
Node {
node: Call(
CallExpr {
func: Node {
node: Identifier(
Identifier {
names: [
Node {
node: "a",
filename: "",
line: 1,
column: 0,
end_line: 1,
end_column: 1,
},
],
pkgpath: "",
ctx: Load,
},
),
filename: "",
line: 1,
column: 0,
end_line: 1,
end_column: 1,
},
args: [
Node {
node: NumberLit(
NumberLit {
binary_suffix: None,
value: Int(
1,
),
},
),
filename: "",
line: 2,
column: 4,
end_line: 2,
end_column: 5,
},
Node {
node: NumberLit(
NumberLit {
binary_suffix: None,
value: Int(
2,
),
},
),
filename: "",
line: 3,
column: 0,
end_line: 3,
end_column: 1,
},
],
keywords: [],
},
),
filename: "",
line: 1,
column: 0,
end_line: 4,
end_column: 1,
}
Loading

0 comments on commit fa685fa

Please sign in to comment.