diff options
| author | Laurenz <laurmaedje@gmail.com> | 2023-01-15 12:00:13 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2023-01-15 12:40:27 +0100 |
| commit | 40561e57fbbc68becac07acd54a34f94f591f277 (patch) | |
| tree | 9e3401f987f1b19ef30162ac00395b7bbba871c6 /src/syntax/ast.rs | |
| parent | 15f0434d1fdd03bc84cacaf6a39ac294a0c75789 (diff) | |
Remove most fields from `SyntaxKind` enum
Diffstat (limited to 'src/syntax/ast.rs')
| -rw-r--r-- | src/syntax/ast.rs | 441 |
1 files changed, 269 insertions, 172 deletions
diff --git a/src/syntax/ast.rs b/src/syntax/ast.rs index 3b3186e4..bf4b37bc 100644 --- a/src/syntax/ast.rs +++ b/src/syntax/ast.rs @@ -5,7 +5,12 @@ use std::num::NonZeroUsize; use std::ops::Deref; -use super::{RawFields, Span, SyntaxKind, SyntaxNode, Unit}; +use unscanny::Scanner; + +use super::{ + is_id_continue, is_id_start, is_newline, split_newlines, Span, SyntaxKind, SyntaxNode, +}; +use crate::geom::{AbsUnit, AngleUnit}; use crate::util::EcoString; /// A typed AST node. @@ -117,7 +122,7 @@ pub enum Expr { Script(Script), /// A fraction in a math formula: `x/2`. Frac(Frac), - /// An alignment point in a math formula: `&`, `&&`. + /// An alignment point in a math formula: `&`. AlignPoint(AlignPoint), /// An identifier: `left`. Ident(Ident), @@ -194,34 +199,34 @@ impl AstNode for Expr { fn from_untyped(node: &SyntaxNode) -> Option<Self> { match node.kind() { SyntaxKind::Linebreak => node.cast().map(Self::Linebreak), - SyntaxKind::Text(_) => node.cast().map(Self::Text), - SyntaxKind::Escape(_) => node.cast().map(Self::Escape), - SyntaxKind::Shorthand(_) => node.cast().map(Self::Shorthand), - SyntaxKind::Symbol(_) => node.cast().map(Self::Symbol), + SyntaxKind::Text => node.cast().map(Self::Text), + SyntaxKind::Escape => node.cast().map(Self::Escape), + SyntaxKind::Shorthand => node.cast().map(Self::Shorthand), + SyntaxKind::Symbol => node.cast().map(Self::Symbol), SyntaxKind::SmartQuote { .. } => node.cast().map(Self::SmartQuote), SyntaxKind::Strong => node.cast().map(Self::Strong), SyntaxKind::Emph => node.cast().map(Self::Emph), - SyntaxKind::Raw(_) => node.cast().map(Self::Raw), - SyntaxKind::Link(_) => node.cast().map(Self::Link), - SyntaxKind::Label(_) => node.cast().map(Self::Label), - SyntaxKind::Ref(_) => node.cast().map(Self::Ref), + SyntaxKind::Raw { .. } => node.cast().map(Self::Raw), + SyntaxKind::Link => node.cast().map(Self::Link), + SyntaxKind::Label => node.cast().map(Self::Label), + SyntaxKind::Ref => node.cast().map(Self::Ref), SyntaxKind::Heading => node.cast().map(Self::Heading), SyntaxKind::ListItem => node.cast().map(Self::List), SyntaxKind::EnumItem => node.cast().map(Self::Enum), SyntaxKind::TermItem => node.cast().map(Self::Term), SyntaxKind::Math => node.cast().map(Self::Math), - SyntaxKind::Atom(_) => node.cast().map(Self::Atom), + SyntaxKind::Atom => node.cast().map(Self::Atom), SyntaxKind::Script => node.cast().map(Self::Script), SyntaxKind::Frac => node.cast().map(Self::Frac), SyntaxKind::AlignPoint => node.cast().map(Self::AlignPoint), - SyntaxKind::Ident(_) => node.cast().map(Self::Ident), + SyntaxKind::Ident => node.cast().map(Self::Ident), SyntaxKind::None => node.cast().map(Self::None), SyntaxKind::Auto => node.cast().map(Self::Auto), - SyntaxKind::Bool(_) => node.cast().map(Self::Bool), - SyntaxKind::Int(_) => node.cast().map(Self::Int), - SyntaxKind::Float(_) => node.cast().map(Self::Float), - SyntaxKind::Numeric(_, _) => node.cast().map(Self::Numeric), - SyntaxKind::Str(_) => node.cast().map(Self::Str), + SyntaxKind::Bool => node.cast().map(Self::Bool), + SyntaxKind::Int => node.cast().map(Self::Int), + SyntaxKind::Float => node.cast().map(Self::Float), + SyntaxKind::Numeric => node.cast().map(Self::Numeric), + SyntaxKind::Str => node.cast().map(Self::Str), SyntaxKind::CodeBlock => node.cast().map(Self::Code), SyntaxKind::ContentBlock => node.cast().map(Self::Content), SyntaxKind::Parenthesized => node.cast().map(Self::Parenthesized), @@ -315,7 +320,7 @@ impl Space { /// Get the number of newlines. pub fn newlines(&self) -> usize { match self.0.kind() { - &SyntaxKind::Space { newlines } => newlines, + SyntaxKind::Space { newlines } => newlines, _ => panic!("space is of wrong kind"), } } @@ -334,10 +339,7 @@ node! { impl Text { /// Get the text. pub fn get(&self) -> &EcoString { - match self.0.kind() { - SyntaxKind::Text(v) => v, - _ => panic!("text is of wrong kind"), - } + self.0.text() } } @@ -349,15 +351,22 @@ node! { impl Escape { /// Get the escaped character. pub fn get(&self) -> char { - match self.0.kind() { - &SyntaxKind::Escape(v) => v, - _ => panic!("escape is of wrong kind"), + let mut s = Scanner::new(self.0.text()); + s.expect('\\'); + if s.eat_if("u{") { + let hex = s.eat_while(char::is_ascii_hexdigit); + u32::from_str_radix(hex, 16) + .ok() + .and_then(std::char::from_u32) + .expect("unicode escape is invalid") + } else { + s.eat().expect("escape is missing escaped character") } } } node! { - /// A shorthand for a unicode codepoint. For example, `~` for non-breaking + /// A shorthand for a unicode codepoint. For example, `~` for a non-breaking /// space or `-?` for a soft hyphen. Shorthand } @@ -365,9 +374,26 @@ node! { impl Shorthand { /// Get the shorthanded character. pub fn get(&self) -> char { - match self.0.kind() { - &SyntaxKind::Shorthand(v) => v, - _ => panic!("shorthand is of wrong kind"), + match self.0.text().as_str() { + "~" => '\u{00A0}', + "..." => '\u{2026}', + "--" => '\u{2013}', + "---" => '\u{2014}', + "-?" => '\u{00AD}', + "!=" => '≠', + "<=" => '≤', + ">=" => '≥', + "<-" => '←', + "->" => '→', + "=>" => '⇒', + ":=" => '≔', + "[|" => '⟦', + "|]" => '⟧', + "||" => '‖', + "|->" => '↦', + "<->" => '↔', + "<=>" => '⇔', + _ => panic!("shorthand is invalid"), } } } @@ -379,11 +405,8 @@ node! { impl Symbol { /// Get the symbol's notation. - pub fn get(&self) -> &EcoString { - match self.0.kind() { - SyntaxKind::Symbol(v) => v, - _ => panic!("symbol is of wrong kind"), - } + pub fn get(&self) -> &str { + self.0.text().trim_matches(':') } } @@ -395,10 +418,7 @@ node! { impl SmartQuote { /// Whether this is a double quote. pub fn double(&self) -> bool { - match self.0.kind() { - &SyntaxKind::SmartQuote { double } => double, - _ => panic!("smart quote is of wrong kind"), - } + self.0.text() == "\"" } } @@ -410,7 +430,7 @@ node! { impl Strong { /// The contents of the strong node. pub fn body(&self) -> Markup { - self.0.cast_first_child().expect("strong node is missing markup body") + self.0.cast_first_match().expect("strong emphasis is missing body") } } @@ -422,9 +442,7 @@ node! { impl Emph { /// The contents of the emphasis node. pub fn body(&self) -> Markup { - self.0 - .cast_first_child() - .expect("emphasis node is missing markup body") + self.0.cast_first_match().expect("emphasis is missing body") } } @@ -434,27 +452,75 @@ node! { } impl Raw { - /// The raw text. - pub fn text(&self) -> &EcoString { - &self.get().text + /// The trimmed raw text. + pub fn text(&self) -> EcoString { + let SyntaxKind::Raw { column } = self.0.kind() else { + panic!("raw node is of wrong kind"); + }; + + let mut text = self.0.text().as_str(); + let blocky = text.starts_with("```"); + text = text.trim_matches('`'); + + // Trim tag, one space at the start, and one space at the end if the + // last non-whitespace char is a backtick. + if blocky { + let mut s = Scanner::new(text); + if s.eat_if(is_id_start) { + s.eat_while(is_id_continue); + } + text = s.after(); + text = text.strip_prefix(' ').unwrap_or(text); + if text.trim_end().ends_with('`') { + text = text.strip_suffix(' ').unwrap_or(text); + } + } + + // Split into lines. + let mut lines = split_newlines(text); + + if blocky { + // Dedent based on column, but not for the first line. + for line in lines.iter_mut().skip(1) { + let offset = line + .chars() + .take(column) + .take_while(|c| c.is_whitespace()) + .map(char::len_utf8) + .sum(); + *line = &line[offset..]; + } + + let is_whitespace = |line: &&str| line.chars().all(char::is_whitespace); + + // Trims a sequence of whitespace followed by a newline at the start. + if lines.first().map_or(false, is_whitespace) { + lines.remove(0); + } + + // Trims a newline followed by a sequence of whitespace at the end. + if lines.last().map_or(false, is_whitespace) { + lines.pop(); + } + } + + lines.join("\n").into() } /// An optional identifier specifying the language to syntax-highlight in. - pub fn lang(&self) -> Option<&EcoString> { - self.get().lang.as_ref() + pub fn lang(&self) -> Option<&str> { + let inner = self.0.text().trim_start_matches('`'); + let mut s = Scanner::new(inner); + s.eat_if(is_id_start).then(|| { + s.eat_while(is_id_continue); + s.before() + }) } /// Whether the raw text should be displayed in a separate block. pub fn block(&self) -> bool { - self.get().block - } - - /// The raw fields. - fn get(&self) -> &RawFields { - match self.0.kind() { - SyntaxKind::Raw(v) => v.as_ref(), - _ => panic!("raw is of wrong kind"), - } + let text = self.0.text(); + text.starts_with("```") && text.chars().any(is_newline) } } @@ -466,10 +532,7 @@ node! { impl Link { /// Get the URL. pub fn url(&self) -> &EcoString { - match self.0.kind() { - SyntaxKind::Link(url) => url, - _ => panic!("link is of wrong kind"), - } + self.0.text() } } @@ -480,11 +543,8 @@ node! { impl Label { /// Get the label's text. - pub fn get(&self) -> &EcoString { - match self.0.kind() { - SyntaxKind::Label(v) => v, - _ => panic!("label is of wrong kind"), - } + pub fn get(&self) -> &str { + self.0.text().trim_start_matches('<').trim_end_matches('>') } } @@ -495,11 +555,8 @@ node! { impl Ref { /// Get the target. - pub fn get(&self) -> &EcoString { - match self.0.kind() { - SyntaxKind::Ref(v) => v, - _ => panic!("reference is of wrong kind"), - } + pub fn get(&self) -> &str { + self.0.text().trim_start_matches('@') } } @@ -511,14 +568,14 @@ node! { impl Heading { /// The contents of the heading. pub fn body(&self) -> Markup { - self.0.cast_first_child().expect("heading is missing markup body") + self.0.cast_first_match().expect("heading is missing markup body") } /// The section depth (numer of equals signs). pub fn level(&self) -> NonZeroUsize { self.0 .children() - .filter(|n| n.kind() == &SyntaxKind::Eq) + .filter(|n| n.kind() == SyntaxKind::Eq) .count() .try_into() .expect("heading is missing equals sign") @@ -533,7 +590,7 @@ node! { impl ListItem { /// The contents of the list item. pub fn body(&self) -> Markup { - self.0.cast_first_child().expect("list item is missing body") + self.0.cast_first_match().expect("list item is missing body") } } @@ -546,14 +603,14 @@ impl EnumItem { /// The explicit numbering, if any: `23.`. pub fn number(&self) -> Option<NonZeroUsize> { self.0.children().find_map(|node| match node.kind() { - SyntaxKind::EnumNumbering(num) => Some(*num), + SyntaxKind::EnumNumbering => node.text().trim_end_matches('.').parse().ok(), _ => Option::None, }) } /// The contents of the list item. pub fn body(&self) -> Markup { - self.0.cast_first_child().expect("enum item is missing body") + self.0.cast_first_match().expect("enum item is missing body") } } @@ -565,13 +622,13 @@ node! { impl TermItem { /// The term described by the item. pub fn term(&self) -> Markup { - self.0.cast_first_child().expect("term list item is missing term") + self.0.cast_first_match().expect("term list item is missing term") } /// The description of the term. pub fn description(&self) -> Markup { self.0 - .cast_last_child() + .cast_last_match() .expect("term list item is missing description") } } @@ -602,10 +659,7 @@ node! { impl Atom { /// Get the atom's text. pub fn get(&self) -> &EcoString { - match self.0.kind() { - SyntaxKind::Atom(v) => v, - _ => panic!("atom is of wrong kind"), - } + self.0.text() } } @@ -617,7 +671,7 @@ node! { impl Script { /// The base of the script. pub fn base(&self) -> Expr { - self.0.cast_first_child().expect("script node is missing base") + self.0.cast_first_match().expect("script node is missing base") } /// The subscript. @@ -647,32 +701,20 @@ node! { impl Frac { /// The numerator. pub fn num(&self) -> Expr { - self.0.cast_first_child().expect("fraction is missing numerator") + self.0.cast_first_match().expect("fraction is missing numerator") } /// The denominator. pub fn denom(&self) -> Expr { - self.0.cast_last_child().expect("fraction is missing denominator") + self.0.cast_last_match().expect("fraction is missing denominator") } } node! { - /// An alignment point in a formula: `&`, `&&`. + /// An alignment point in a formula: `&`. AlignPoint } -impl AlignPoint { - /// The number of ampersands. - pub fn count(&self) -> NonZeroUsize { - self.0 - .children() - .filter(|n| n.kind() == &SyntaxKind::Amp) - .count() - .try_into() - .expect("alignment point is missing ampersand sign") - } -} - node! { /// An identifier: `it`. Ident @@ -680,18 +722,16 @@ node! { impl Ident { /// Get the identifier. - pub fn get(&self) -> &EcoString { - match self.0.kind() { - SyntaxKind::Ident(id) => id, - _ => panic!("identifier is of wrong kind"), - } + pub fn get(&self) -> &str { + self.0.text().trim_start_matches('#') } /// Take out the container identifier. pub fn take(self) -> EcoString { - match self.0.take() { - SyntaxKind::Ident(id) => id, - _ => panic!("identifier is of wrong kind"), + let text = self.0.into_text(); + match text.strip_prefix('#') { + Some(text) => text.into(), + Option::None => text, } } @@ -727,10 +767,7 @@ node! { impl Bool { /// Get the value. pub fn get(&self) -> bool { - match self.0.kind() { - SyntaxKind::Bool(v) => *v, - _ => panic!("boolean is of wrong kind"), - } + self.0.text() == "true" } } @@ -742,10 +779,7 @@ node! { impl Int { /// Get the value. pub fn get(&self) -> i64 { - match self.0.kind() { - SyntaxKind::Int(v) => *v, - _ => panic!("integer is of wrong kind"), - } + self.0.text().parse().expect("integer is invalid") } } @@ -757,10 +791,7 @@ node! { impl Float { /// Get the value. pub fn get(&self) -> f64 { - match self.0.kind() { - SyntaxKind::Float(v) => *v, - _ => panic!("float is of wrong kind"), - } + self.0.text().parse().expect("float is invalid") } } @@ -772,13 +803,47 @@ node! { impl Numeric { /// Get the value and unit. pub fn get(&self) -> (f64, Unit) { - match self.0.kind() { - SyntaxKind::Numeric(v, unit) => (*v, *unit), - _ => panic!("numeric is of wrong kind"), - } + let text = self.0.text(); + let count = text + .chars() + .rev() + .take_while(|c| matches!(c, 'a'..='z' | '%')) + .count(); + + let split = text.len() - count; + let value = text[..split].parse().expect("number is invalid"); + let unit = match &text[split..] { + "pt" => Unit::Length(AbsUnit::Pt), + "mm" => Unit::Length(AbsUnit::Mm), + "cm" => Unit::Length(AbsUnit::Cm), + "in" => Unit::Length(AbsUnit::In), + "deg" => Unit::Angle(AngleUnit::Deg), + "rad" => Unit::Angle(AngleUnit::Rad), + "em" => Unit::Em, + "fr" => Unit::Fr, + "%" => Unit::Percent, + _ => panic!("number has invalid suffix"), + }; + + (value, unit) } } +/// Unit of a numeric value. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub enum Unit { + /// An absolute length unit. + Length(AbsUnit), + /// An angular unit. + Angle(AngleUnit), + /// Font-relative: `1em` is the same as the font size. + Em, + /// Fractions: `fr`. + Fr, + /// Percentage: `%`. + Percent, +} + node! { /// A quoted string: `"..."`. Str @@ -786,11 +851,46 @@ node! { impl Str { /// Get the value. - pub fn get(&self) -> &EcoString { - match self.0.kind() { - SyntaxKind::Str(v) => v, - _ => panic!("string is of wrong kind"), + pub fn get(&self) -> EcoString { + let text = self.0.text(); + let unquoted = &text[1..text.len() - 1]; + if !unquoted.contains('\\') { + return unquoted.into(); } + + let mut out = EcoString::with_capacity(unquoted.len()); + let mut s = Scanner::new(unquoted); + + while let Some(c) = s.eat() { + if c != '\\' { + out.push(c); + continue; + } + + let start = s.locate(-1); + match s.eat() { + Some('\\') => out.push('\\'), + Some('"') => out.push('"'), + Some('n') => out.push('\n'), + Some('r') => out.push('\r'), + Some('t') => out.push('\t'), + Some('u') if s.eat_if('{') => { + let sequence = s.eat_while(char::is_ascii_hexdigit); + s.eat_if('}'); + + match u32::from_str_radix(sequence, 16) + .ok() + .and_then(std::char::from_u32) + { + Some(c) => out.push(c), + Option::None => out.push_str(s.from(start)), + } + } + _ => out.push_str(s.from(start)), + } + } + + out } } @@ -814,7 +914,7 @@ node! { impl ContentBlock { /// The contained markup. pub fn body(&self) -> Markup { - self.0.cast_first_child().expect("content block is missing body") + self.0.cast_first_match().expect("content block is missing body") } } @@ -827,7 +927,7 @@ impl Parenthesized { /// The wrapped expression. pub fn expr(&self) -> Expr { self.0 - .cast_first_child() + .cast_first_match() .expect("parenthesized expression is missing expression") } } @@ -856,7 +956,7 @@ pub enum ArrayItem { impl AstNode for ArrayItem { fn from_untyped(node: &SyntaxNode) -> Option<Self> { match node.kind() { - SyntaxKind::Spread => node.cast_first_child().map(Self::Spread), + SyntaxKind::Spread => node.cast_first_match().map(Self::Spread), _ => node.cast().map(Self::Pos), } } @@ -897,7 +997,7 @@ impl AstNode for DictItem { match node.kind() { SyntaxKind::Named => node.cast().map(Self::Named), SyntaxKind::Keyed => node.cast().map(Self::Keyed), - SyntaxKind::Spread => node.cast_first_child().map(Self::Spread), + SyntaxKind::Spread => node.cast_first_match().map(Self::Spread), _ => Option::None, } } @@ -919,12 +1019,12 @@ node! { impl Named { /// The name: `thickness`. pub fn name(&self) -> Ident { - self.0.cast_first_child().expect("named pair is missing name") + self.0.cast_first_match().expect("named pair is missing name") } /// The right-hand side of the pair: `3pt`. pub fn expr(&self) -> Expr { - self.0.cast_last_child().expect("named pair is missing expression") + self.0.cast_last_match().expect("named pair is missing expression") } } @@ -935,19 +1035,16 @@ node! { impl Keyed { /// The key: `"spacy key"`. - pub fn key(&self) -> EcoString { + pub fn key(&self) -> Str { self.0 .children() - .find_map(|node| match node.kind() { - SyntaxKind::Str(key) => Some(key.clone()), - _ => Option::None, - }) + .find_map(|node| node.cast::<Str>()) .expect("keyed pair is missing key") } /// The right-hand side of the pair: `true`. pub fn expr(&self) -> Expr { - self.0.cast_last_child().expect("keyed pair is missing expression") + self.0.cast_last_match().expect("keyed pair is missing expression") } } @@ -967,7 +1064,7 @@ impl Unary { /// The expression to operate on: `x`. pub fn expr(&self) -> Expr { - self.0.cast_last_child().expect("unary operation is missing child") + self.0.cast_last_match().expect("unary operation is missing child") } } @@ -984,7 +1081,7 @@ pub enum UnOp { impl UnOp { /// Try to convert the token into a unary operation. - pub fn from_token(token: &SyntaxKind) -> Option<Self> { + pub fn from_token(token: SyntaxKind) -> Option<Self> { Some(match token { SyntaxKind::Plus => Self::Pos, SyntaxKind::Minus => Self::Neg, @@ -1036,14 +1133,14 @@ impl Binary { /// The left-hand side of the operation: `a`. pub fn lhs(&self) -> Expr { self.0 - .cast_first_child() + .cast_first_match() .expect("binary operation is missing left-hand side") } /// The right-hand side of the operation: `b`. pub fn rhs(&self) -> Expr { self.0 - .cast_last_child() + .cast_last_match() .expect("binary operation is missing right-hand side") } } @@ -1093,7 +1190,7 @@ pub enum BinOp { impl BinOp { /// Try to convert the token into a binary operation. - pub fn from_token(token: &SyntaxKind) -> Option<Self> { + pub fn from_token(token: SyntaxKind) -> Option<Self> { Some(match token { SyntaxKind::Plus => Self::Add, SyntaxKind::Minus => Self::Sub, @@ -1210,12 +1307,12 @@ node! { impl FieldAccess { /// The expression to access the field on. pub fn target(&self) -> Expr { - self.0.cast_first_child().expect("field access is missing object") + self.0.cast_first_match().expect("field access is missing object") } /// The name of the field. pub fn field(&self) -> Ident { - self.0.cast_last_child().expect("field access is missing name") + self.0.cast_last_match().expect("field access is missing name") } } @@ -1227,13 +1324,13 @@ node! { impl FuncCall { /// The function to call. pub fn callee(&self) -> Expr { - self.0.cast_first_child().expect("function call is missing callee") + self.0.cast_first_match().expect("function call is missing callee") } /// The arguments to the function. pub fn args(&self) -> Args { self.0 - .cast_last_child() + .cast_last_match() .expect("function call is missing argument list") } } @@ -1246,18 +1343,18 @@ node! { impl MethodCall { /// The expression to call the method on. pub fn target(&self) -> Expr { - self.0.cast_first_child().expect("method call is missing target") + self.0.cast_first_match().expect("method call is missing target") } /// The name of the method. pub fn method(&self) -> Ident { - self.0.cast_last_child().expect("method call is missing name") + self.0.cast_last_match().expect("method call is missing name") } /// The arguments to the method. pub fn args(&self) -> Args { self.0 - .cast_last_child() + .cast_last_match() .expect("method call is missing argument list") } } @@ -1289,7 +1386,7 @@ impl AstNode for Arg { fn from_untyped(node: &SyntaxNode) -> Option<Self> { match node.kind() { SyntaxKind::Named => node.cast().map(Self::Named), - SyntaxKind::Spread => node.cast_first_child().map(Self::Spread), + SyntaxKind::Spread => node.cast_first_match().map(Self::Spread), _ => node.cast().map(Self::Pos), } } @@ -1320,7 +1417,7 @@ impl Closure { pub fn params(&self) -> impl DoubleEndedIterator<Item = Param> + '_ { self.0 .children() - .find(|x| x.kind() == &SyntaxKind::Params) + .find(|x| x.kind() == SyntaxKind::Params) .expect("closure is missing parameter list") .children() .filter_map(SyntaxNode::cast) @@ -1328,7 +1425,7 @@ impl Closure { /// The body of the closure. pub fn body(&self) -> Expr { - self.0.cast_last_child().expect("closure is missing body") + self.0.cast_last_match().expect("closure is missing body") } } @@ -1346,9 +1443,9 @@ pub enum Param { impl AstNode for Param { fn from_untyped(node: &SyntaxNode) -> Option<Self> { match node.kind() { - SyntaxKind::Ident(_) => node.cast().map(Self::Pos), + SyntaxKind::Ident => node.cast().map(Self::Pos), SyntaxKind::Named => node.cast().map(Self::Named), - SyntaxKind::Spread => node.cast_first_child().map(Self::Sink), + SyntaxKind::Spread => node.cast_first_match().map(Self::Sink), _ => Option::None, } } @@ -1370,7 +1467,7 @@ node! { impl LetBinding { /// The binding to assign to. pub fn binding(&self) -> Ident { - match self.0.cast_first_child() { + match self.0.cast_first_match() { Some(Expr::Ident(binding)) => binding, Some(Expr::Closure(closure)) => { closure.name().expect("let-bound closure is missing name") @@ -1381,12 +1478,12 @@ impl LetBinding { /// The expression the binding is initialized with. pub fn init(&self) -> Option<Expr> { - if self.0.cast_first_child::<Ident>().is_some() { + if self.0.cast_first_match::<Ident>().is_some() { // This is a normal binding like `let x = 1`. self.0.children().filter_map(SyntaxNode::cast).nth(1) } else { // This is a closure binding like `let f(x) = 1`. - self.0.cast_first_child() + self.0.cast_first_match() } } } @@ -1399,19 +1496,19 @@ node! { impl SetRule { /// The function to set style properties for. pub fn target(&self) -> Ident { - self.0.cast_first_child().expect("set rule is missing target") + self.0.cast_first_match().expect("set rule is missing target") } /// The style properties to set. pub fn args(&self) -> Args { - self.0.cast_last_child().expect("set rule is missing argument list") + self.0.cast_last_match().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() != &SyntaxKind::If) + .skip_while(|child| child.kind() != SyntaxKind::If) .find_map(SyntaxNode::cast) } } @@ -1427,13 +1524,13 @@ impl ShowRule { self.0 .children() .rev() - .skip_while(|child| child.kind() != &SyntaxKind::Colon) + .skip_while(|child| child.kind() != SyntaxKind::Colon) .find_map(SyntaxNode::cast) } /// The transformation recipe. pub fn transform(&self) -> Expr { - self.0.cast_last_child().expect("show rule is missing transform") + self.0.cast_last_match().expect("show rule is missing transform") } } @@ -1445,7 +1542,7 @@ node! { impl Conditional { /// The condition which selects the body to evaluate. pub fn condition(&self) -> Expr { - self.0.cast_first_child().expect("conditional is missing condition") + self.0.cast_first_match().expect("conditional is missing condition") } /// The expression to evaluate if the condition is true. @@ -1471,12 +1568,12 @@ node! { impl WhileLoop { /// The condition which selects whether to evaluate the body. pub fn condition(&self) -> Expr { - self.0.cast_first_child().expect("while loop is missing condition") + self.0.cast_first_match().expect("while loop is missing condition") } /// The expression to evaluate while the condition is true. pub fn body(&self) -> Expr { - self.0.cast_last_child().expect("while loop is missing body") + self.0.cast_last_match().expect("while loop is missing body") } } @@ -1488,17 +1585,17 @@ node! { impl ForLoop { /// The pattern to assign to. pub fn pattern(&self) -> ForPattern { - self.0.cast_first_child().expect("for loop is missing pattern") + self.0.cast_first_match().expect("for loop is missing pattern") } /// The expression to iterate over. pub fn iter(&self) -> Expr { - self.0.cast_first_child().expect("for loop is missing iterable") + self.0.cast_first_match().expect("for loop is missing iterable") } /// The expression to evaluate for each iteration. pub fn body(&self) -> Expr { - self.0.cast_last_child().expect("for loop is missing body") + self.0.cast_last_match().expect("for loop is missing body") } } @@ -1521,7 +1618,7 @@ impl ForPattern { /// The value part of the pattern. pub fn value(&self) -> Ident { - self.0.cast_last_child().expect("for loop pattern is missing value") + self.0.cast_last_match().expect("for loop pattern is missing value") } } @@ -1533,7 +1630,7 @@ node! { impl ModuleImport { /// The module or path from which the items should be imported. pub fn source(&self) -> Expr { - self.0.cast_last_child().expect("module import is missing source") + self.0.cast_last_match().expect("module import is missing source") } /// The items to be imported. @@ -1566,7 +1663,7 @@ node! { impl ModuleInclude { /// The module or path from which the content should be included. pub fn source(&self) -> Expr { - self.0.cast_last_child().expect("module include is missing path") + self.0.cast_last_match().expect("module include is missing path") } } @@ -1588,6 +1685,6 @@ node! { impl FuncReturn { /// The expression to return. pub fn body(&self) -> Option<Expr> { - self.0.cast_last_child() + self.0.cast_last_match() } } |
