diff options
Diffstat (limited to 'src/syntax')
| -rw-r--r-- | src/syntax/ast.rs | 135 | ||||
| -rw-r--r-- | src/syntax/highlight.rs | 12 | ||||
| -rw-r--r-- | src/syntax/kind.rs | 70 | ||||
| -rw-r--r-- | src/syntax/parsing.rs | 145 | ||||
| -rw-r--r-- | src/syntax/tokens.rs | 2 |
5 files changed, 133 insertions, 231 deletions
diff --git a/src/syntax/ast.rs b/src/syntax/ast.rs index 61b8f0e6..1b0e8985 100644 --- a/src/syntax/ast.rs +++ b/src/syntax/ast.rs @@ -63,11 +63,11 @@ impl Markup { /// A single piece of markup. #[derive(Debug, Clone, PartialEq)] pub enum MarkupNode { - /// Whitespace containing less than two newlines. + /// Whitespace. Space(Space), - /// A forced line break. + /// A forced line break: `\`. Linebreak(Linebreak), - /// Plain text. + /// Plain text without markup. Text(Text), /// An escape sequence: `\#`, `\u{1F5FA}`. Escape(Escape), @@ -76,9 +76,9 @@ pub enum MarkupNode { Shorthand(Shorthand), /// A smart quote: `'` or `"`. SmartQuote(SmartQuote), - /// Strong markup: `*Strong*`. + /// Strong content: `*Strong*`. Strong(Strong), - /// Emphasized markup: `_Emphasized_`. + /// Emphasized content: `_Emphasized_`. Emph(Emph), /// A raw block with optional syntax highlighting: `` `...` ``. Raw(Raw), @@ -171,7 +171,7 @@ node! { } node! { - /// Plain text. + /// Plain text without markup. Text } @@ -367,12 +367,12 @@ impl ListItem { } node! { - /// An item in an enumeration (ordered list): `1. ...`. + /// An item in an enumeration (ordered list): `+ ...` or `1. ...`. EnumItem } impl EnumItem { - /// The number, if any. + /// The explicit numbering, if any: `23.`. pub fn number(&self) -> Option<usize> { self.0.children().find_map(|node| match node.kind() { NodeKind::EnumNumbering(num) => Some(*num), @@ -434,9 +434,9 @@ pub enum MathNode { Linebreak(Linebreak), /// An escape sequence: `\#`, `\u{1F5FA}`. Escape(Escape), - /// A atom: `x`, `+`, `12`. + /// An atom: `x`, `+`, `12`. Atom(Atom), - /// A base with an optional sub- and superscript: `a_1^2`. + /// A base with optional sub- and superscripts: `a_1^2`. Script(Script), /// A fraction: `x/2`. Frac(Frac), @@ -565,9 +565,9 @@ pub enum Expr { Content(ContentBlock), /// A grouped expression: `(1 + 2)`. Parenthesized(Parenthesized), - /// An array expression: `(1, "hi", 12cm)`. + /// An array: `(1, "hi", 12cm)`. Array(Array), - /// A dictionary expression: `(thickness: 3pt, pattern: dashed)`. + /// A dictionary: `(thickness: 3pt, pattern: dashed)`. Dict(Dict), /// A unary operation: `-x`. Unary(Unary), @@ -579,16 +579,14 @@ pub enum Expr { FuncCall(FuncCall), /// An invocation of a method: `array.push(v)`. MethodCall(MethodCall), - /// A closure expression: `(x, y) => z`. + /// A closure: `(x, y) => z`. Closure(Closure), /// A let binding: `let x = 1`. Let(LetBinding), /// A set rule: `set text(...)`. Set(SetRule), - /// A show rule: `show node: heading as [*{nody.body}*]`. + /// A show rule: `show heading: it => [*{it.body}*]`. Show(ShowRule), - /// A wrap rule: `wrap body in columns(2, body)`. - Wrap(WrapRule), /// An if-else conditional: `if x { y } else { z }`. Conditional(Conditional), /// A while loop: `while x { y }`. @@ -599,12 +597,12 @@ pub enum Expr { Import(ModuleImport), /// A module include: `include "chapter1.typ"`. Include(ModuleInclude), - /// A break statement: `break`. - Break(BreakStmt), - /// A continue statement: `continue`. - Continue(ContinueStmt), - /// A return statement: `return`, `return x + 1`. - Return(ReturnStmt), + /// A break from a loop: `break`. + Break(LoopBreak), + /// A continue in a loop: `continue`. + Continue(LoopContinue), + /// A return from a function: `return`, `return x + 1`. + Return(FuncReturn), } impl TypedNode for Expr { @@ -625,15 +623,14 @@ impl TypedNode for Expr { NodeKind::LetBinding => node.cast().map(Self::Let), NodeKind::SetRule => node.cast().map(Self::Set), NodeKind::ShowRule => node.cast().map(Self::Show), - NodeKind::WrapRule => node.cast().map(Self::Wrap), NodeKind::Conditional => node.cast().map(Self::Conditional), NodeKind::WhileLoop => node.cast().map(Self::While), NodeKind::ForLoop => node.cast().map(Self::For), NodeKind::ModuleImport => node.cast().map(Self::Import), NodeKind::ModuleInclude => node.cast().map(Self::Include), - NodeKind::BreakStmt => node.cast().map(Self::Break), - NodeKind::ContinueStmt => node.cast().map(Self::Continue), - NodeKind::ReturnStmt => node.cast().map(Self::Return), + NodeKind::LoopBreak => node.cast().map(Self::Break), + NodeKind::LoopContinue => node.cast().map(Self::Continue), + NodeKind::FuncReturn => node.cast().map(Self::Return), _ => node.cast().map(Self::Lit), } } @@ -656,7 +653,6 @@ impl TypedNode for Expr { Self::Let(v) => v.as_untyped(), Self::Set(v) => v.as_untyped(), Self::Show(v) => v.as_untyped(), - Self::Wrap(v) => v.as_untyped(), Self::Conditional(v) => v.as_untyped(), Self::While(v) => v.as_untyped(), Self::For(v) => v.as_untyped(), @@ -679,7 +675,6 @@ impl Expr { | Self::Let(_) | Self::Set(_) | Self::Show(_) - | Self::Wrap(_) | Self::Conditional(_) | Self::While(_) | Self::For(_) @@ -723,15 +718,15 @@ pub enum LitKind { None, /// The auto literal: `auto`. Auto, - /// A boolean literal: `true`, `false`. + /// A boolean: `true`, `false`. Bool(bool), - /// An integer literal: `120`. + /// An integer: `120`. Int(i64), - /// A floating-point literal: `1.2`, `10e-4`. + /// A floating-point number: `1.2`, `10e-4`. Float(f64), - /// A numeric literal with a unit: `12pt`, `3cm`, `2em`, `90deg`, `50%`. + /// A numeric value with a unit: `12pt`, `3cm`, `2em`, `90deg`, `50%`. Numeric(f64, Unit), - /// A string literal: `"hello!"`. + /// A quoted string: `"..."`. Str(EcoString), } @@ -760,7 +755,7 @@ impl ContentBlock { } node! { - /// A parenthesized expression: `(1 + 2)`. + /// A grouped expression: `(1 + 2)`. Parenthesized } @@ -853,7 +848,7 @@ impl TypedNode for DictItem { } node! { - /// A pair of a name and an expression: `thickness: 3pt`. + /// A named pair: `thickness: 3pt`. Named } @@ -870,7 +865,7 @@ impl Named { } node! { - /// A pair of a string key and an expression: `"spacy key": true`. + /// A keyed pair: `"spacy key": true`. Keyed } @@ -1204,7 +1199,7 @@ impl MethodCall { } node! { - /// The arguments to a function: `12, draw: false`. + /// A function call's argument list: `(12pt, y)`. Args } @@ -1245,7 +1240,7 @@ impl TypedNode for Arg { } node! { - /// A closure expression: `(x, y) => z`. + /// A closure: `(x, y) => z`. Closure } @@ -1347,52 +1342,34 @@ impl SetRule { pub fn args(&self) -> Args { self.0.cast_last_child().expect("set rule is missing argument list") } + + /// A condition under which the set rule applies. + pub fn condition(&self) -> Option<Expr> { + self.0 + .children() + .skip_while(|child| child.kind() != &NodeKind::If) + .find_map(SyntaxNode::cast) + } } node! { - /// A show rule: `show node: heading as [*{nody.body}*]`. + /// A show rule: `show heading: it => [*{it.body}*]`. ShowRule } impl ShowRule { - /// The binding to assign to. - pub fn binding(&self) -> Option<Ident> { - let mut children = self.0.children(); - children - .find_map(SyntaxNode::cast) - .filter(|_| children.any(|child| child.kind() == &NodeKind::Colon)) - } - /// The pattern that this rule matches. - pub fn pattern(&self) -> Expr { + pub fn pattern(&self) -> Option<Expr> { self.0 .children() .rev() - .skip_while(|child| child.kind() != &NodeKind::As) + .skip_while(|child| child.kind() != &NodeKind::Colon) .find_map(SyntaxNode::cast) - .expect("show rule is missing pattern") } - /// The expression that realizes the node. - pub fn body(&self) -> Expr { - self.0.cast_last_child().expect("show rule is missing body") - } -} - -node! { - /// A wrap rule: `wrap body in columns(2, body)`. - WrapRule -} - -impl WrapRule { - /// The binding to assign the remaining markup to. - pub fn binding(&self) -> Ident { - self.0.cast_first_child().expect("wrap rule is missing binding") - } - - /// The expression to evaluate. - pub fn body(&self) -> Expr { - self.0.cast_last_child().expect("wrap rule is missing body") + /// The transformation recipe. + pub fn transform(&self) -> Expr { + self.0.cast_last_child().expect("show rule is missing transform") } } @@ -1462,7 +1439,7 @@ impl ForLoop { } node! { - /// A for-in loop: `for x in y { z }`. + /// A for loop's destructuring pattern: `x` or `x, y`. ForPattern } @@ -1533,21 +1510,21 @@ impl ModuleInclude { } node! { - /// A break expression: `break`. - BreakStmt + /// A break from a loop: `break`. + LoopBreak } node! { - /// A continue expression: `continue`. - ContinueStmt + /// A continue in a loop: `continue`. + LoopContinue } node! { - /// A return expression: `return`, `return x + 1`. - ReturnStmt + /// A return from a function: `return`, `return x + 1`. + FuncReturn } -impl ReturnStmt { +impl FuncReturn { /// The expression to return. pub fn body(&self) -> Option<Expr> { self.0.cast_last_child() @@ -1555,7 +1532,7 @@ impl ReturnStmt { } node! { - /// An identifier. + /// An identifier: `it`. Ident } diff --git a/src/syntax/highlight.rs b/src/syntax/highlight.rs index d5345fab..34cce4c0 100644 --- a/src/syntax/highlight.rs +++ b/src/syntax/highlight.rs @@ -257,7 +257,6 @@ impl Category { NodeKind::Let => Some(Category::Keyword), NodeKind::Set => Some(Category::Keyword), NodeKind::Show => Some(Category::Keyword), - NodeKind::Wrap => Some(Category::Keyword), NodeKind::If => Some(Category::Keyword), NodeKind::Else => Some(Category::Keyword), NodeKind::For => Some(Category::Keyword), @@ -269,7 +268,6 @@ impl Category { NodeKind::Import => Some(Category::Keyword), NodeKind::Include => Some(Category::Keyword), NodeKind::From => Some(Category::Keyword), - NodeKind::As => Some(Category::Keyword), NodeKind::Markup { .. } => match parent.kind() { NodeKind::DescItem @@ -316,8 +314,7 @@ impl Category { if parent .children() .rev() - .skip_while(|child| child.kind() != &NodeKind::As) - .take_while(|child| child.kind() != &NodeKind::Colon) + .skip_while(|child| child.kind() != &NodeKind::Colon) .find(|c| matches!(c.kind(), NodeKind::Ident(_))) .map_or(false, |ident| std::ptr::eq(ident, child)) => { @@ -349,7 +346,6 @@ impl Category { NodeKind::LetBinding => None, NodeKind::SetRule => None, NodeKind::ShowRule => None, - NodeKind::WrapRule => None, NodeKind::Conditional => None, NodeKind::WhileLoop => None, NodeKind::ForLoop => None, @@ -357,9 +353,9 @@ impl Category { NodeKind::ModuleImport => None, NodeKind::ImportItems => None, NodeKind::ModuleInclude => None, - NodeKind::BreakStmt => None, - NodeKind::ContinueStmt => None, - NodeKind::ReturnStmt => None, + NodeKind::LoopBreak => None, + NodeKind::LoopContinue => None, + NodeKind::FuncReturn => None, NodeKind::Error(_, _) => Some(Category::Error), } diff --git a/src/syntax/kind.rs b/src/syntax/kind.rs index 1568693b..1282b592 100644 --- a/src/syntax/kind.rs +++ b/src/syntax/kind.rs @@ -106,8 +106,6 @@ pub enum NodeKind { Set, /// The `show` keyword. Show, - /// The `wrap` keyword. - Wrap, /// The `if` keyword. If, /// The `else` keyword. @@ -130,8 +128,6 @@ pub enum NodeKind { Include, /// The `from` keyword. From, - /// The `as` keyword. - As, /// Markup of which all lines must have a minimal indentation. /// @@ -139,7 +135,7 @@ pub enum NodeKind { /// started, but to the right of which column all markup elements must be, /// so it is zero except inside indent-aware constructs like lists. Markup { min_indent: usize }, - /// Consecutive text without markup. + /// Plain text without markup. Text(EcoString), /// A forced line break: `\`. Linebreak, @@ -150,9 +146,9 @@ pub enum NodeKind { Shorthand(char), /// A smart quote: `'` or `"`. SmartQuote { double: bool }, - /// Strong markup: `*Strong*`. + /// Strong content: `*Strong*`. Strong, - /// Emphasized markup: `_Emphasized_`. + /// Emphasized content: `_Emphasized_`. Emph, /// A raw block with optional syntax highlighting: `` `...` ``. Raw(Arc<RawKind>), @@ -164,26 +160,26 @@ pub enum NodeKind { Ref(EcoString), /// A section heading: `= Introduction`. Heading, - /// An item of an unordered list: `- ...`. + /// An item in an unordered list: `- ...`. ListItem, - /// An item of an enumeration (ordered list): `+ ...` or `1. ...`. + /// An item in an enumeration (ordered list): `+ ...` or `1. ...`. EnumItem, /// An explicit enumeration numbering: `23.`. EnumNumbering(usize), - /// An item of a description list: `/ Term: Details. + /// An item in a description list: `/ Term: Details`. DescItem, - /// A math formula: `$x$`, `$ x^2 $`. + /// A mathematical formula: `$x$`, `$ x^2 $`. Math, - /// An atom in a math formula: `x`, `+`, `12`. + /// An atom in a formula: `x`, `+`, `12`. Atom(EcoString), - /// A base with optional sub- and superscript in a math formula: `a_1^2`. + /// A base with optional sub- and superscripts in a formula: `a_1^2`. Script, - /// A fraction in a math formula: `x/2`. + /// A fraction in a formula: `x/2`. Frac, - /// An alignment indicator in a math formula: `&`, `&&`. + /// An alignment indicator in a formula: `&`, `&&`. Align, - /// An identifier: `center`. + /// An identifier: `it`. Ident(EcoString), /// A boolean: `true`, `false`. Bool(bool), @@ -219,9 +215,9 @@ pub enum NodeKind { FuncCall, /// An invocation of a method: `array.push(v)`. MethodCall, - /// A function call's argument list: `(x, y)`. + /// A function call's argument list: `(12pt, y)`. Args, - /// Spreaded arguments or a argument sink: `..x`. + /// Spreaded arguments or an argument sink: `..x`. Spread, /// A closure: `(x, y) => z`. Closure, @@ -231,15 +227,13 @@ pub enum NodeKind { LetBinding, /// A set rule: `set text(...)`. SetRule, - /// A show rule: `show node: heading as [*{nody.body}*]`. + /// A show rule: `show heading: it => [*{it.body}*]`. ShowRule, - /// A wrap rule: `wrap body in columns(2, body)`. - WrapRule, /// An if-else conditional: `if x { y } else { z }`. Conditional, - /// A while loop: `while x { ... }`. + /// A while loop: `while x { y }`. WhileLoop, - /// A for loop: `for x in y { ... }`. + /// A for loop: `for x in y { z }`. ForLoop, /// A for loop's destructuring pattern: `x` or `x, y`. ForPattern, @@ -249,12 +243,12 @@ pub enum NodeKind { ImportItems, /// A module include: `include "chapter1.typ"`. ModuleInclude, - /// A break statement: `break`. - BreakStmt, - /// A continue statement: `continue`. - ContinueStmt, - /// A return statement: `return x + 1`. - ReturnStmt, + /// A break from a loop: `break`. + LoopBreak, + /// A continue in a loop: `continue`. + LoopContinue, + /// A return from a function: `return`, `return x + 1`. + FuncReturn, /// An invalid sequence of characters. Error(ErrorPos, EcoString), @@ -367,7 +361,6 @@ impl NodeKind { Self::Let => "keyword `let`", Self::Set => "keyword `set`", Self::Show => "keyword `show`", - Self::Wrap => "keyword `wrap`", Self::If => "keyword `if`", Self::Else => "keyword `else`", Self::For => "keyword `for`", @@ -379,7 +372,6 @@ impl NodeKind { Self::Import => "keyword `import`", Self::Include => "keyword `include`", Self::From => "keyword `from`", - Self::As => "keyword `as`", Self::Markup { .. } => "markup", Self::Text(_) => "text", Self::Linebreak => "linebreak", @@ -426,7 +418,6 @@ impl NodeKind { Self::LetBinding => "`let` expression", Self::SetRule => "`set` expression", Self::ShowRule => "`show` expression", - Self::WrapRule => "`wrap` expression", Self::Conditional => "`if` expression", Self::WhileLoop => "while-loop expression", Self::ForLoop => "for-loop expression", @@ -434,9 +425,9 @@ impl NodeKind { Self::ModuleImport => "`import` expression", Self::ImportItems => "import items", Self::ModuleInclude => "`include` expression", - Self::BreakStmt => "`break` expression", - Self::ContinueStmt => "`continue` expression", - Self::ReturnStmt => "`return` expression", + Self::LoopBreak => "`break` expression", + Self::LoopContinue => "`continue` expression", + Self::FuncReturn => "`return` expression", Self::Error(_, _) => "syntax error", } } @@ -488,7 +479,6 @@ impl Hash for NodeKind { Self::Let => {} Self::Set => {} Self::Show => {} - Self::Wrap => {} Self::If => {} Self::Else => {} Self::For => {} @@ -500,7 +490,6 @@ impl Hash for NodeKind { Self::Import => {} Self::Include => {} Self::From => {} - Self::As => {} Self::Markup { min_indent } => min_indent.hash(state), Self::Text(s) => s.hash(state), Self::Linebreak => {} @@ -548,7 +537,6 @@ impl Hash for NodeKind { Self::LetBinding => {} Self::SetRule => {} Self::ShowRule => {} - Self::WrapRule => {} Self::Conditional => {} Self::WhileLoop => {} Self::ForLoop => {} @@ -556,9 +544,9 @@ impl Hash for NodeKind { Self::ModuleImport => {} Self::ImportItems => {} Self::ModuleInclude => {} - Self::BreakStmt => {} - Self::ContinueStmt => {} - Self::ReturnStmt => {} + Self::LoopBreak => {} + Self::LoopContinue => {} + Self::FuncReturn => {} Self::Error(pos, msg) => (pos, msg).hash(state), } } diff --git a/src/syntax/parsing.rs b/src/syntax/parsing.rs index fecc527c..acf76b7e 100644 --- a/src/syntax/parsing.rs +++ b/src/syntax/parsing.rs @@ -208,7 +208,6 @@ where }); } -/// Parse a markup node. fn markup_node(p: &mut Parser, at_start: &mut bool) { let Some(token) = p.peek() else { return }; match token { @@ -245,10 +244,10 @@ fn markup_node(p: &mut Parser, at_start: &mut bool) { NodeKind::Eq => heading(p, *at_start), // Lists. - NodeKind::Minus => list_node(p, *at_start), - NodeKind::Plus | NodeKind::EnumNumbering(_) => enum_node(p, *at_start), + NodeKind::Minus => list_item(p, *at_start), + NodeKind::Plus | NodeKind::EnumNumbering(_) => enum_item(p, *at_start), NodeKind::Slash => { - desc_node(p, *at_start).ok(); + desc_item(p, *at_start).ok(); } NodeKind::Colon => { let marker = p.marker(); @@ -261,7 +260,6 @@ fn markup_node(p: &mut Parser, at_start: &mut bool) { | NodeKind::Let | NodeKind::Set | NodeKind::Show - | NodeKind::Wrap | NodeKind::If | NodeKind::While | NodeKind::For @@ -282,7 +280,6 @@ fn markup_node(p: &mut Parser, at_start: &mut bool) { *at_start = false; } -/// Parse strong content. fn strong(p: &mut Parser) { p.perform(NodeKind::Strong, |p| { p.start_group(Group::Strong); @@ -291,7 +288,6 @@ fn strong(p: &mut Parser) { }) } -/// Parse emphasized content. fn emph(p: &mut Parser) { p.perform(NodeKind::Emph, |p| { p.start_group(Group::Emph); @@ -300,7 +296,6 @@ fn emph(p: &mut Parser) { }) } -/// Parse a heading. fn heading(p: &mut Parser, at_start: bool) { let marker = p.marker(); let current_start = p.current_start(); @@ -317,8 +312,7 @@ fn heading(p: &mut Parser, at_start: bool) { } } -/// Parse a single list item. -fn list_node(p: &mut Parser, at_start: bool) { +fn list_item(p: &mut Parser, at_start: bool) { let marker = p.marker(); let text: EcoString = p.peek_src().into(); p.assert(NodeKind::Minus); @@ -332,8 +326,7 @@ fn list_node(p: &mut Parser, at_start: bool) { } } -/// Parse a single enum item. -fn enum_node(p: &mut Parser, at_start: bool) { +fn enum_item(p: &mut Parser, at_start: bool) { let marker = p.marker(); let text: EcoString = p.peek_src().into(); p.eat(); @@ -347,8 +340,7 @@ fn enum_node(p: &mut Parser, at_start: bool) { } } -/// Parse a single description list item. -fn desc_node(p: &mut Parser, at_start: bool) -> ParseResult { +fn desc_item(p: &mut Parser, at_start: bool) -> ParseResult { let marker = p.marker(); let text: EcoString = p.peek_src().into(); p.eat(); @@ -366,7 +358,6 @@ fn desc_node(p: &mut Parser, at_start: bool) -> ParseResult { Ok(()) } -/// Parse an expression within a markup mode. fn markup_expr(p: &mut Parser) { // Does the expression need termination or can content follow directly? let stmt = matches!( @@ -375,7 +366,6 @@ fn markup_expr(p: &mut Parser) { NodeKind::Let | NodeKind::Set | NodeKind::Show - | NodeKind::Wrap | NodeKind::Import | NodeKind::Include ) @@ -389,7 +379,6 @@ fn markup_expr(p: &mut Parser) { p.end_group(); } -/// Parse math. fn math(p: &mut Parser) { p.perform(NodeKind::Math, |p| { p.start_group(Group::Math); @@ -400,12 +389,10 @@ fn math(p: &mut Parser) { }); } -/// Parse a math node. fn math_node(p: &mut Parser) { math_node_prec(p, 0, None) } -/// Parse a math node with operators having at least the minimum precedence. fn math_node_prec(p: &mut Parser, min_prec: usize, stop: Option<NodeKind>) { let marker = p.marker(); math_primary(p); @@ -457,19 +444,18 @@ fn math_primary(p: &mut Parser) { | NodeKind::Ident(_) => p.eat(), // Groups. - NodeKind::LeftParen => group(p, Group::Paren, '(', ')'), - NodeKind::LeftBracket => group(p, Group::Bracket, '[', ']'), - NodeKind::LeftBrace => group(p, Group::Brace, '{', '}'), + NodeKind::LeftParen => math_group(p, Group::Paren, '(', ')'), + NodeKind::LeftBracket => math_group(p, Group::Bracket, '[', ']'), + NodeKind::LeftBrace => math_group(p, Group::Brace, '{', '}'), // Alignment indactor. - NodeKind::Amp => align(p), + NodeKind::Amp => math_align(p), _ => p.unexpected(), } } -/// Parse grouped math. -fn group(p: &mut Parser, group: Group, l: char, r: char) { +fn math_group(p: &mut Parser, group: Group, l: char, r: char) { p.perform(NodeKind::Math, |p| { let marker = p.marker(); p.start_group(group); @@ -483,15 +469,13 @@ fn group(p: &mut Parser, group: Group, l: char, r: char) { }) } -/// Parse an alignment indicator. -fn align(p: &mut Parser) { +fn math_align(p: &mut Parser) { p.perform(NodeKind::Align, |p| { p.assert(NodeKind::Amp); while p.eat_if(NodeKind::Amp) {} }) } -/// Parse an expression. fn expr(p: &mut Parser) -> ParseResult { expr_prec(p, false, 0) } @@ -571,7 +555,6 @@ fn expr_prec(p: &mut Parser, atomic: bool, min_prec: usize) -> ParseResult { Ok(()) } -/// Parse a primary expression. fn primary(p: &mut Parser, atomic: bool) -> ParseResult { if literal(p) { return Ok(()); @@ -599,18 +582,17 @@ fn primary(p: &mut Parser, atomic: bool) -> ParseResult { Some(NodeKind::LeftBracket) => Ok(content_block(p)), // Keywords. - Some(NodeKind::Let) => let_expr(p), - Some(NodeKind::Set) => set_expr(p), - Some(NodeKind::Show) => show_expr(p), - Some(NodeKind::Wrap) => wrap_expr(p), - Some(NodeKind::If) => if_expr(p), - Some(NodeKind::While) => while_expr(p), - Some(NodeKind::For) => for_expr(p), - Some(NodeKind::Import) => import_expr(p), - Some(NodeKind::Include) => include_expr(p), - Some(NodeKind::Break) => break_expr(p), - Some(NodeKind::Continue) => continue_expr(p), - Some(NodeKind::Return) => return_expr(p), + Some(NodeKind::Let) => let_binding(p), + Some(NodeKind::Set) => set_rule(p), + Some(NodeKind::Show) => show_rule(p), + Some(NodeKind::If) => conditional(p), + Some(NodeKind::While) => while_loop(p), + Some(NodeKind::For) => for_loop(p), + Some(NodeKind::Import) => module_import(p), + Some(NodeKind::Include) => module_include(p), + Some(NodeKind::Break) => break_stmt(p), + Some(NodeKind::Continue) => continue_stmt(p), + Some(NodeKind::Return) => return_stmt(p), Some(NodeKind::Error(_, _)) => { p.eat(); @@ -625,10 +607,8 @@ fn primary(p: &mut Parser, atomic: bool) -> ParseResult { } } -/// Parse a literal. fn literal(p: &mut Parser) -> bool { match p.peek() { - // Basic values. Some( NodeKind::None | NodeKind::Auto @@ -645,7 +625,6 @@ fn literal(p: &mut Parser) -> bool { } } -/// Parse an identifier. fn ident(p: &mut Parser) -> ParseResult { match p.peek() { Some(NodeKind::Ident(_)) => { @@ -762,8 +741,6 @@ fn collection(p: &mut Parser, keyed: bool) -> (CollectionKind, usize) { (kind, items) } -/// Parse an expression or a named pair, returning whether it's a spread or a -/// named pair. fn item(p: &mut Parser, keyed: bool) -> ParseResult<NodeKind> { let marker = p.marker(); if p.eat_if(NodeKind::Dots) { @@ -806,8 +783,6 @@ fn item(p: &mut Parser, keyed: bool) -> ParseResult<NodeKind> { } } -/// Convert a collection into an array, producing errors for anything other than -/// expressions. fn array(p: &mut Parser, marker: Marker) { marker.filter_children(p, |x| match x.kind() { NodeKind::Named | NodeKind::Keyed => Err("expected expression"), @@ -816,8 +791,6 @@ fn array(p: &mut Parser, marker: Marker) { marker.end(p, NodeKind::Array); } -/// Convert a collection into a dictionary, producing errors for anything other -/// than named and keyed pairs. fn dict(p: &mut Parser, marker: Marker) { let mut used = HashSet::new(); marker.filter_children(p, |x| match x.kind() { @@ -838,8 +811,6 @@ fn dict(p: &mut Parser, marker: Marker) { marker.end(p, NodeKind::Dict); } -/// Convert a collection into a list of parameters, producing errors for -/// anything other than identifiers, spread operations and named pairs. fn params(p: &mut Parser, marker: Marker) { marker.filter_children(p, |x| match x.kind() { kind if kind.is_paren() => Ok(()), @@ -866,7 +837,6 @@ fn code_block(p: &mut Parser) { }); } -/// Parse expressions. fn code(p: &mut Parser) { while !p.eof() { p.start_group(Group::Expr); @@ -880,7 +850,6 @@ fn code(p: &mut Parser) { } } -/// Parse a content block: `[...]`. fn content_block(p: &mut Parser) { p.perform(NodeKind::ContentBlock, |p| { p.start_group(Group::Bracket); @@ -889,7 +858,6 @@ fn content_block(p: &mut Parser) { }); } -/// Parse the arguments to a function call. fn args(p: &mut Parser) -> ParseResult { match p.peek_direct() { Some(NodeKind::LeftParen) => {} @@ -931,8 +899,7 @@ fn args(p: &mut Parser) -> ParseResult { Ok(()) } -/// Parse a let expression. -fn let_expr(p: &mut Parser) -> ParseResult { +fn let_binding(p: &mut Parser) -> ParseResult { p.perform(NodeKind::LetBinding, |p| { p.assert(NodeKind::Let); @@ -965,45 +932,30 @@ fn let_expr(p: &mut Parser) -> ParseResult { }) } -/// Parse a set expression. -fn set_expr(p: &mut Parser) -> ParseResult { +fn set_rule(p: &mut Parser) -> ParseResult { p.perform(NodeKind::SetRule, |p| { p.assert(NodeKind::Set); ident(p)?; - args(p) + args(p)?; + if p.eat_if(NodeKind::If) { + expr(p)?; + } + Ok(()) }) } -/// Parse a show expression. -fn show_expr(p: &mut Parser) -> ParseResult { +fn show_rule(p: &mut Parser) -> ParseResult { p.perform(NodeKind::ShowRule, |p| { p.assert(NodeKind::Show); - let marker = p.marker(); expr(p)?; if p.eat_if(NodeKind::Colon) { - marker.filter_children(p, |child| match child.kind() { - NodeKind::Ident(_) | NodeKind::Colon => Ok(()), - _ => Err("expected identifier"), - }); expr(p)?; } - p.expect(NodeKind::As)?; - expr(p) - }) -} - -/// Parse a wrap expression. -fn wrap_expr(p: &mut Parser) -> ParseResult { - p.perform(NodeKind::WrapRule, |p| { - p.assert(NodeKind::Wrap); - ident(p)?; - p.expect(NodeKind::In)?; - expr(p) + Ok(()) }) } -/// Parse an if-else expresion. -fn if_expr(p: &mut Parser) -> ParseResult { +fn conditional(p: &mut Parser) -> ParseResult { p.perform(NodeKind::Conditional, |p| { p.assert(NodeKind::If); @@ -1012,7 +964,7 @@ fn if_expr(p: &mut Parser) -> ParseResult { if p.eat_if(NodeKind::Else) { if p.at(NodeKind::If) { - if_expr(p)?; + conditional(p)?; } else { body(p)?; } @@ -1022,8 +974,7 @@ fn if_expr(p: &mut Parser) -> ParseResult { }) } -/// Parse a while expresion. -fn while_expr(p: &mut Parser) -> ParseResult { +fn while_loop(p: &mut Parser) -> ParseResult { p.perform(NodeKind::WhileLoop, |p| { p.assert(NodeKind::While); expr(p)?; @@ -1031,8 +982,7 @@ fn while_expr(p: &mut Parser) -> ParseResult { }) } -/// Parse a for-in expression. -fn for_expr(p: &mut Parser) -> ParseResult { +fn for_loop(p: &mut Parser) -> ParseResult { p.perform(NodeKind::ForLoop, |p| { p.assert(NodeKind::For); for_pattern(p)?; @@ -1042,7 +992,6 @@ fn for_expr(p: &mut Parser) -> ParseResult { }) } -/// Parse a for loop pattern. fn for_pattern(p: &mut Parser) -> ParseResult { p.perform(NodeKind::ForPattern, |p| { ident(p)?; @@ -1053,8 +1002,7 @@ fn for_pattern(p: &mut Parser) -> ParseResult { }) } -/// Parse an import expression. -fn import_expr(p: &mut Parser) -> ParseResult { +fn module_import(p: &mut Parser) -> ParseResult { p.perform(NodeKind::ModuleImport, |p| { p.assert(NodeKind::Import); @@ -1081,33 +1029,29 @@ fn import_expr(p: &mut Parser) -> ParseResult { }) } -/// Parse an include expression. -fn include_expr(p: &mut Parser) -> ParseResult { +fn module_include(p: &mut Parser) -> ParseResult { p.perform(NodeKind::ModuleInclude, |p| { p.assert(NodeKind::Include); expr(p) }) } -/// Parse a break expression. -fn break_expr(p: &mut Parser) -> ParseResult { - p.perform(NodeKind::BreakStmt, |p| { +fn break_stmt(p: &mut Parser) -> ParseResult { + p.perform(NodeKind::LoopBreak, |p| { p.assert(NodeKind::Break); Ok(()) }) } -/// Parse a continue expression. -fn continue_expr(p: &mut Parser) -> ParseResult { - p.perform(NodeKind::ContinueStmt, |p| { +fn continue_stmt(p: &mut Parser) -> ParseResult { + p.perform(NodeKind::LoopContinue, |p| { p.assert(NodeKind::Continue); Ok(()) }) } -/// Parse a return expression. -fn return_expr(p: &mut Parser) -> ParseResult { - p.perform(NodeKind::ReturnStmt, |p| { +fn return_stmt(p: &mut Parser) -> ParseResult { + p.perform(NodeKind::FuncReturn, |p| { p.assert(NodeKind::Return); if !p.at(NodeKind::Comma) && !p.eof() { expr(p)?; @@ -1116,7 +1060,6 @@ fn return_expr(p: &mut Parser) -> ParseResult { }) } -/// Parse a control flow body. fn body(p: &mut Parser) -> ParseResult { match p.peek() { Some(NodeKind::LeftBracket) => Ok(content_block(p)), diff --git a/src/syntax/tokens.rs b/src/syntax/tokens.rs index f18bb780..b27832c5 100644 --- a/src/syntax/tokens.rs +++ b/src/syntax/tokens.rs @@ -613,12 +613,10 @@ fn keyword(ident: &str) -> Option<NodeKind> { "let" => NodeKind::Let, "set" => NodeKind::Set, "show" => NodeKind::Show, - "wrap" => NodeKind::Wrap, "if" => NodeKind::If, "else" => NodeKind::Else, "for" => NodeKind::For, "in" => NodeKind::In, - "as" => NodeKind::As, "while" => NodeKind::While, "break" => NodeKind::Break, "continue" => NodeKind::Continue, |
