summaryrefslogtreecommitdiff
path: root/src/parse
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-12-15 20:27:41 +0100
committerLaurenz <laurmaedje@gmail.com>2021-12-15 20:27:41 +0100
commit2a3d0f4b390457174ed09347dd29e97ff9a783e4 (patch)
tree0e0634bff6b7f64131267f4cbe05651c1c91d900 /src/parse
parent244ad386ec271ff86a2101eb4cc38d37a55552b9 (diff)
Set Rules Episode VII: The Set Awakens
Diffstat (limited to 'src/parse')
-rw-r--r--src/parse/mod.rs65
-rw-r--r--src/parse/parser.rs3
-rw-r--r--src/parse/tokens.rs1
3 files changed, 37 insertions, 32 deletions
diff --git a/src/parse/mod.rs b/src/parse/mod.rs
index dbec0a5e..0a2f73f5 100644
--- a/src/parse/mod.rs
+++ b/src/parse/mod.rs
@@ -110,12 +110,13 @@ fn markup_node(p: &mut Parser, at_start: &mut bool) {
// Hashtag + keyword / identifier.
NodeKind::Ident(_)
| NodeKind::Let
+ | NodeKind::Set
| NodeKind::If
| NodeKind::While
| NodeKind::For
| NodeKind::Import
| NodeKind::Include => {
- let stmt = matches!(token, NodeKind::Let | NodeKind::Import);
+ let stmt = matches!(token, NodeKind::Let | NodeKind::Set | NodeKind::Import);
let group = if stmt { Group::Stmt } else { Group::Expr };
p.start_group(group);
@@ -265,6 +266,7 @@ fn primary(p: &mut Parser, atomic: bool) -> ParseResult {
// Keywords.
Some(NodeKind::Let) => let_expr(p),
+ Some(NodeKind::Set) => set_expr(p),
Some(NodeKind::If) => if_expr(p),
Some(NodeKind::While) => while_expr(p),
Some(NodeKind::For) => for_expr(p),
@@ -507,45 +509,40 @@ fn block(p: &mut Parser) {
/// Parse a function call.
fn call(p: &mut Parser, callee: Marker) -> ParseResult {
- callee.perform(p, NodeKind::Call, |p| match p.peek_direct() {
- Some(NodeKind::LeftParen | NodeKind::LeftBracket) => {
- args(p, true);
- Ok(())
- }
- _ => {
- p.expected_at("argument list");
- Err(())
- }
- })
+ callee.perform(p, NodeKind::Call, |p| args(p, true, true))
}
/// Parse the arguments to a function call.
-fn args(p: &mut Parser, allow_template: bool) {
+fn args(p: &mut Parser, direct: bool, brackets: bool) -> ParseResult {
+ match if direct { p.peek_direct() } else { p.peek() } {
+ Some(NodeKind::LeftParen) => {}
+ Some(NodeKind::LeftBracket) if brackets => {}
+ _ => {
+ p.expected("argument list");
+ return Err(());
+ }
+ }
+
p.perform(NodeKind::CallArgs, |p| {
- if !allow_template || p.peek_direct() == Some(&NodeKind::LeftParen) {
+ if p.at(&NodeKind::LeftParen) {
p.start_group(Group::Paren);
collection(p);
p.end_group();
}
- while allow_template && p.peek_direct() == Some(&NodeKind::LeftBracket) {
+ while brackets && p.peek_direct() == Some(&NodeKind::LeftBracket) {
template(p);
}
- })
+ });
+
+ Ok(())
}
/// Parse a with expression.
fn with_expr(p: &mut Parser, marker: Marker) -> ParseResult {
marker.perform(p, NodeKind::WithExpr, |p| {
p.eat_assert(&NodeKind::With);
-
- if p.at(&NodeKind::LeftParen) {
- args(p, false);
- Ok(())
- } else {
- p.expected("argument list");
- Err(())
- }
+ args(p, false, false)
})
}
@@ -587,6 +584,15 @@ fn let_expr(p: &mut Parser) -> ParseResult {
})
}
+/// Parse a set expression.
+fn set_expr(p: &mut Parser) -> ParseResult {
+ p.perform(NodeKind::SetExpr, |p| {
+ p.eat_assert(&NodeKind::Set);
+ ident(p)?;
+ args(p, true, false)
+ })
+}
+
/// Parse an if expresion.
fn if_expr(p: &mut Parser) -> ParseResult {
p.perform(NodeKind::IfExpr, |p| {
@@ -612,8 +618,7 @@ fn while_expr(p: &mut Parser) -> ParseResult {
p.perform(NodeKind::WhileExpr, |p| {
p.eat_assert(&NodeKind::While);
expr(p)?;
- body(p)?;
- Ok(())
+ body(p)
})
}
@@ -624,8 +629,7 @@ fn for_expr(p: &mut Parser) -> ParseResult {
for_pattern(p)?;
p.eat_expect(&NodeKind::In)?;
expr(p)?;
- body(p)?;
- Ok(())
+ body(p)
})
}
@@ -664,9 +668,7 @@ fn import_expr(p: &mut Parser) -> ParseResult {
};
p.eat_expect(&NodeKind::From)?;
- expr(p)?;
-
- Ok(())
+ expr(p)
})
}
@@ -674,8 +676,7 @@ fn import_expr(p: &mut Parser) -> ParseResult {
fn include_expr(p: &mut Parser) -> ParseResult {
p.perform(NodeKind::IncludeExpr, |p| {
p.eat_assert(&NodeKind::Include);
- expr(p)?;
- Ok(())
+ expr(p)
})
}
diff --git a/src/parse/parser.rs b/src/parse/parser.rs
index 6598b1f2..503158a9 100644
--- a/src/parse/parser.rs
+++ b/src/parse/parser.rs
@@ -125,6 +125,7 @@ impl<'s> Parser<'s> {
}
/// Eat, debug-asserting that the token is the given one.
+ #[track_caller]
pub fn eat_assert(&mut self, t: &NodeKind) {
debug_assert_eq!(self.peek(), Some(t));
self.eat();
@@ -199,6 +200,7 @@ impl<'s> Parser<'s> {
/// to `end_group`.
///
/// This panics if the current token does not start the given group.
+ #[track_caller]
pub fn start_group(&mut self, kind: Group) {
self.groups.push(GroupEntry { kind, prev_mode: self.tokens.mode() });
self.tokens.set_mode(match kind {
@@ -220,6 +222,7 @@ impl<'s> Parser<'s> {
/// End the parsing of a group.
///
/// This panics if no group was started.
+ #[track_caller]
pub fn end_group(&mut self) {
let group_mode = self.tokens.mode();
let group = self.groups.pop().expect("no started group");
diff --git a/src/parse/tokens.rs b/src/parse/tokens.rs
index 07a6fe12..27ec046d 100644
--- a/src/parse/tokens.rs
+++ b/src/parse/tokens.rs
@@ -527,6 +527,7 @@ fn keyword(ident: &str) -> Option<NodeKind> {
"or" => NodeKind::Or,
"with" => NodeKind::With,
"let" => NodeKind::Let,
+ "set" => NodeKind::Set,
"if" => NodeKind::If,
"else" => NodeKind::Else,
"for" => NodeKind::For,