difftreelog
refactor parser and grammar compatibility
in: master
46 files changed
cmds/jrsonnet-fmt/Cargo.tomldiffbeforeafterboth--- /dev/null
+++ b/cmds/jrsonnet-fmt/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "jrsonnet-fmt"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+dprint-core = "0.58.2"
+jrsonnet-rowan-parser = { path = "../../crates/jrsonnet-rowan-parser" }
cmds/jrsonnet-fmt/src/main.rsdiffbeforeafterboth--- /dev/null
+++ b/cmds/jrsonnet-fmt/src/main.rs
@@ -0,0 +1,513 @@
+use std::any::type_name;
+
+use dprint_core::formatting::{PrintItems, PrintOptions, Signal};
+use jrsonnet_rowan_parser::{
+ nodes::{
+ ArgsDesc, Assertion, BinaryOperator, Bind, CompSpec, Destruct, DestructArrayPart,
+ DestructRest, Expr, Field, FieldName, ForSpec, IfSpec, ImportKind, LhsExpr, Literal,
+ Member, Name, Number, ObjBody, ObjLocal, ParamsDesc, SliceDesc, SourceFile, String,
+ UnaryOperator,
+ },
+ AstToken, SyntaxToken,
+};
+
+pub trait Printable {
+ fn print(&self) -> PrintItems;
+}
+
+macro_rules! pi {
+ (@i; $($t:tt)*) => {{
+ #[allow(unused_mut)]
+ let mut o = PrintItems::new();
+ pi!(@s; o: $($t)*);
+ o
+ }};
+ (@s; $o:ident: str($e:expr $(,)?) $($t:tt)*) => {{
+ $o.push_str($e);
+ pi!(@s; $o: $($t)*);
+ }};
+ (@s; $o:ident: nl $($t:tt)*) => {{
+ $o.push_signal(Signal::NewLine);
+ pi!(@s; $o: $($t)*);
+ }};
+ (@s; $o:ident: >i $($t:tt)*) => {{
+ $o.push_signal(Signal::StartIndent);
+ pi!(@s; $o: $($t)*);
+ }};
+ (@s; $o:ident: <i $($t:tt)*) => {{
+ $o.push_signal(Signal::FinishIndent);
+ pi!(@s; $o: $($t)*);
+ }};
+ (@s; $o:ident: {$expr:expr} $($t:tt)*) => {{
+ $o.extend($expr.print());
+ pi!(@s; $o: $($t)*);
+ }};
+ (@s; $o:ident: if ($e:expr)($($then:tt)*) $($t:tt)*) => {{
+ if $e {
+ pi!(@s; $o: $($then)*);
+ }
+ pi!(@s; $o: $($t)*);
+ }};
+ (@s; $o:ident: ifelse ($e:expr)($($then:tt)*)($($else:tt)*) $($t:tt)*) => {{
+ if $e {
+ pi!(@s; $o: $($then)*);
+ } else {
+ pi!(@s; $o: $($else)*);
+ }
+ pi!(@s; $o: $($t)*);
+ }};
+ (@s; $i:ident:) => {}
+}
+macro_rules! p {
+ (new: $($t:tt)*) => {
+ pi!(@i; $($t)*)
+ };
+ ($o:ident: $($t:tt)*) => {
+ pi!(@s; $o: $($t)*)
+ };
+}
+
+impl<P> Printable for Option<P>
+where
+ P: Printable,
+{
+ fn print(&self) -> PrintItems {
+ if let Some(v) = self {
+ v.print()
+ } else {
+ p!(new: str(
+ &format!(
+ "/*missing {}*/",
+ type_name::<P>().replace("jrsonnet_rowan_parser::generated::nodes::", "")
+ ),
+ ))
+ }
+ }
+}
+
+impl Printable for SyntaxToken {
+ fn print(&self) -> PrintItems {
+ p!(new: str(&self.to_string()))
+ }
+}
+
+impl Printable for String {
+ fn print(&self) -> PrintItems {
+ p!(new: str(&format!("{}", self)))
+ }
+}
+impl Printable for Number {
+ fn print(&self) -> PrintItems {
+ p!(new: str(&format!("{}", self)))
+ }
+}
+
+impl Printable for Name {
+ fn print(&self) -> PrintItems {
+ p!(new: {self.ident_lit()})
+ }
+}
+
+impl Printable for DestructRest {
+ fn print(&self) -> PrintItems {
+ let mut pi = p!(new: str("..."));
+ if let Some(name) = self.into() {
+ p!(pi: {name});
+ }
+ pi
+ }
+}
+
+impl Printable for Destruct {
+ fn print(&self) -> PrintItems {
+ let mut pi = p!(new:);
+ match self {
+ Destruct::DestructFull(f) => {
+ p!(pi: {f.name()})
+ }
+ Destruct::DestructSkip(_) => p!(pi: str("?")),
+ Destruct::DestructArray(a) => {
+ p!(pi: str("[") >i nl);
+ for el in a.destruct_array_parts() {
+ match el {
+ DestructArrayPart::DestructArrayElement(e) => {
+ p!(pi: {e.destruct()} str(",") nl)
+ }
+ DestructArrayPart::DestructRest(d) => {
+ p!(pi: {d} str(",") nl)
+ }
+ }
+ }
+ p!(pi: <i str("]"));
+ }
+ Destruct::DestructObject(o) => {
+ p!(pi: str("{") >i nl);
+ for item in o.destruct_object_fields() {
+ p!(pi: {item.field()});
+ if let Some(des) = item.destruct() {
+ p!(pi: str(": ") {des})
+ }
+ if let Some(def) = item.expr() {
+ p!(pi: str(" = ") {def});
+ }
+ p!(pi: str(",") nl);
+ }
+ if let Some(rest) = o.destruct_rest() {
+ p!(pi: {rest} nl)
+ }
+ p!(pi: <i str("}"));
+ }
+ }
+ pi
+ }
+}
+
+impl Printable for FieldName {
+ fn print(&self) -> PrintItems {
+ match self {
+ FieldName::FieldNameFixed(f) => {
+ if let Some(id) = f.id() {
+ p!(new: {id})
+ } else if let Some(str) = f.string() {
+ p!(new: {str})
+ } else {
+ p!(new: str("/*missing FieldName*/"))
+ }
+ }
+ FieldName::FieldNameDynamic(d) => {
+ p!(new: str("[") {d.expr()} str("]"))
+ }
+ }
+ }
+}
+impl Printable for Field {
+ fn print(&self) -> PrintItems {
+ let mut pi = p!(new:);
+ match self {
+ Field::FieldNormal(n) => {
+ p!(pi: {n.field_name()});
+ if n.plus_token().is_some() {
+ p!(pi: str("+"));
+ }
+ p!(pi: str(": ") {n.expr()});
+ }
+ Field::FieldMethod(m) => {
+ p!(pi: {m.field_name()} {m.params_desc()} str(": ") {m.expr()});
+ }
+ }
+ pi
+ }
+}
+
+impl Printable for ObjLocal {
+ fn print(&self) -> PrintItems {
+ p!(new: str("local ") {self.bind()})
+ }
+}
+
+impl Printable for Assertion {
+ fn print(&self) -> PrintItems {
+ let mut pi = p!(new: str("assert ") {self.condition()});
+ if self.colon_token().is_some() || self.message().is_some() {
+ p!(pi: str(": ") {self.message()})
+ }
+ pi
+ }
+}
+
+impl Printable for ParamsDesc {
+ fn print(&self) -> PrintItems {
+ let mut pi = p!(new: str("(") >i nl);
+ for param in self.params() {
+ p!(pi: {param.destruct()});
+ if param.assign_token().is_some() || param.expr().is_some() {
+ p!(pi: str(" = ") {param.expr()})
+ }
+ p!(pi: str(",") nl)
+ }
+ p!(pi: <i str(")"));
+ pi
+ }
+}
+impl Printable for ArgsDesc {
+ fn print(&self) -> PrintItems {
+ let mut pi = p!(new: str("(") >i nl);
+ for arg in self.args() {
+ if arg.name().is_some() || arg.assign_token().is_some() {
+ p!(pi: {arg.name()} str(" = "));
+ }
+ p!(pi: {arg.expr()} str(",") nl)
+ }
+ p!(pi: <i str(")"));
+ pi
+ }
+}
+impl Printable for SliceDesc {
+ fn print(&self) -> PrintItems {
+ let mut pi = p!(new: str("["));
+ if self.from().is_some() {
+ p!(pi: {self.from()});
+ }
+ p!(pi: str(":"));
+ if self.end().is_some() {
+ p!(pi: {self.end().map(|e|e.expr())})
+ }
+ // Keep only one : in case if we don't need step
+ if self.step().is_some() {
+ p!(pi: str(":") {self.step().map(|e|e.expr())});
+ }
+ p!(pi: str("]"));
+ pi
+ }
+}
+
+impl Printable for ObjBody {
+ fn print(&self) -> PrintItems {
+ match self {
+ ObjBody::ObjBodyComp(_) => todo!(),
+ ObjBody::ObjBodyMemberList(l) => {
+ let mut pi = p!(new:);
+ for mem in l.members() {
+ match mem {
+ Member::MemberBindStmt(b) => {
+ p!(pi: {b.obj_local()})
+ }
+ Member::MemberAssertStmt(ass) => {
+ p!(pi: {ass.assertion()})
+ }
+ Member::MemberField(f) => {
+ p!(pi: {f.field()})
+ }
+ }
+ p!(pi: str(",") nl)
+ }
+ pi
+ }
+ }
+ }
+}
+impl Printable for UnaryOperator {
+ fn print(&self) -> PrintItems {
+ p!(new: str(self.text()))
+ }
+}
+impl Printable for BinaryOperator {
+ fn print(&self) -> PrintItems {
+ p!(new: str(self.text()))
+ }
+}
+impl Printable for Bind {
+ fn print(&self) -> PrintItems {
+ match self {
+ Bind::BindDestruct(d) => {
+ p!(new: {d.into()} str(" = ") {d.value()})
+ }
+ Bind::BindFunction(f) => {
+ p!(new: str("function") {f.params()} str(" = ") {f.value()})
+ }
+ }
+ }
+}
+impl Printable for Literal {
+ fn print(&self) -> PrintItems {
+ p!(new: str(&self.syntax().to_string()))
+ }
+}
+impl Printable for ImportKind {
+ fn print(&self) -> PrintItems {
+ p!(new: str(&self.syntax().to_string()))
+ }
+}
+impl Printable for LhsExpr {
+ fn print(&self) -> PrintItems {
+ p!(new: {self.expr()})
+ }
+}
+impl Printable for ForSpec {
+ fn print(&self) -> PrintItems {
+ p!(new: str("for ") {self.bind()} str(" in ") {self.expr()})
+ }
+}
+impl Printable for IfSpec {
+ fn print(&self) -> PrintItems {
+ p!(new: str("if ") {self.expr()})
+ }
+}
+impl Printable for CompSpec {
+ fn print(&self) -> PrintItems {
+ match self {
+ CompSpec::ForSpec(f) => f.print(),
+ CompSpec::IfSpec(i) => i.print(),
+ }
+ }
+}
+impl Printable for Expr {
+ fn print(&self) -> PrintItems {
+ match self {
+ Expr::ExprBinary(b) => {
+ p!(new: {b.lhs()} str(" ") {b.binary_operator()} str(" ") {b.rhs()})
+ }
+ Expr::ExprUnary(u) => p!(new: {u.unary_operator()} {u.rhs()}),
+ Expr::ExprSlice(s) => {
+ p!(new: {s.expr()} {s.slice_desc()})
+ }
+ Expr::ExprIndex(i) => {
+ p!(new: {i.expr()} str(".") {i.index()})
+ }
+ Expr::ExprIndexExpr(i) => p!(new: {i.base()} str("[") {i.index()} str("]")),
+ Expr::ExprApply(a) => {
+ let mut pi = p!(new: {a.expr()} {a.args_desc()});
+ if a.tailstrict_kw_token().is_some() {
+ p!(pi: str(" tailstrict"));
+ }
+ pi
+ }
+ Expr::ExprObjExtend(ex) => {
+ p!(new: {ex.lhs_expr()} str(" ") {ex.expr()})
+ }
+ Expr::ExprParened(p) => {
+ p!(new: str("(") {p.expr()} str(")"))
+ }
+ Expr::ExprIntrinsicThisFile(_) => p!(new: str("$intrinsicThisFile")),
+ Expr::ExprIntrinsicId(_) => p!(new: str("$intrinsicId")),
+ Expr::ExprIntrinsic(i) => p!(new: str("$intrinsic(") {i.name()} str(")")),
+ Expr::ExprString(s) => p!(new: {s.string()}),
+ Expr::ExprNumber(n) => p!(new: {n.number()}),
+ Expr::ExprArray(a) => {
+ let mut pi = p!(new: str("[") >i nl);
+ for el in a.exprs() {
+ p!(pi: {el} str(",") nl);
+ }
+ p!(pi: <i str("]"));
+ pi
+ }
+ Expr::ExprObject(o) => {
+ p!(new: str("{") >i nl {o.obj_body()} <i str("}"))
+ }
+ Expr::ExprArrayComp(arr) => {
+ let mut pi = p!(new: str("[") {arr.expr()});
+ for spec in arr.comp_specs() {
+ p!(pi: str(" ") {spec});
+ }
+ p!(pi: str("]"));
+ pi
+ }
+ Expr::ExprImport(v) => {
+ p!(new: {v.import_kind()} str(" ") {v.string()})
+ }
+ Expr::ExprVar(n) => p!(new: {n.name()}),
+ Expr::ExprLocal(l) => {
+ let mut pi = p!(new: str("local") >i nl);
+ for bind in l.binds() {
+ p!(pi: {bind} str(",") nl);
+ }
+ p!(pi: <i str(";") nl {l.expr()});
+ pi
+ }
+ Expr::ExprIfThenElse(ite) => {
+ let mut pi =
+ p!(new: str("if ") {ite.cond()} str(" then ") {ite.then().map(|t| t.expr())});
+ if ite.else_kw_token().is_some() || ite.else_().is_some() {
+ p!(pi: str(" else ") {ite.else_().map(|t| t.expr())})
+ }
+ pi
+ }
+ Expr::ExprFunction(f) => p!(new: str("function") {f.params_desc()} str(" ") {f.expr()}),
+ Expr::ExprAssert(a) => p!(new: {a.assertion()} str("; ") {a.expr()}),
+ Expr::ExprError(e) => p!(new: str("error ") {e.expr()}),
+ Expr::ExprLiteral(l) => {
+ p!(new: {l.literal()})
+ }
+ }
+ }
+}
+
+impl Printable for SourceFile {
+ fn print(&self) -> PrintItems {
+ assert!(self.expr().is_some());
+ self.expr().print()
+ }
+}
+
+fn main() {
+ let (parsed, _errors) = jrsonnet_rowan_parser::parse(
+ r#"
+
+
+ # Edit me!
+ local b = import "b.libsonnet"; # comment
+ local a = import "a.libsonnet";
+
+ local f(x,y)=x+y;
+
+ local {a: [b, ..., c], d, ...e} = null;
+
+ local ass = assert false : false; false;
+
+ local fn = function(a, b, c = 3) 4;
+
+ local comp = [a for b in c if d == e];
+ local ocomp = {[k]: 1 for k in v};
+
+ local ? = skip;
+
+ local intr = $intrinsic(test);
+ local intrId = $intrinsicId;
+ local intrThisFile = $intrinsicThisFile;
+
+ local ie = a[expr];
+
+ local unary = !a;
+
+ local Template = {z: "foo"};
+
+ {
+ local
+
+ h = 3,
+ assert self.a == 1
+
+ : "error",
+ "f": ((((((3)))))) ,
+ "g g":
+ f(4,2),
+ arr: [[
+ 1, 2,
+ ],
+ 3,
+ {
+ b: {
+ c: {
+ k: [16]
+ }
+ }
+ }
+ ],
+ m: a[1::],
+ m: b[::],
+ k: if a == b then
+
+
+ 2
+
+ else Template {}
+ } + Template
+
+
+"#,
+ );
+
+ // dbg!(errors);
+ dbg!(&parsed);
+
+ let o = dprint_core::formatting::format(
+ || parsed.print(),
+ PrintOptions {
+ indent_width: 2,
+ max_width: 100,
+ use_tabs: false,
+ new_line_text: "\n",
+ },
+ );
+ println!("{}", o);
+}
crates/jrsonnet-rowan-parser/Cargo.tomldiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/Cargo.toml
+++ b/crates/jrsonnet-rowan-parser/Cargo.toml
@@ -19,3 +19,4 @@
indoc = "1.0.3"
insta = "1.10.0"
anyhow = "1.0.57"
+jrsonnet-stdlib = { path = "../jrsonnet-stdlib" }
crates/jrsonnet-rowan-parser/jsonnet.ungramdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/jsonnet.ungram
+++ b/crates/jrsonnet-rowan-parser/jsonnet.ungram
@@ -1,7 +1,12 @@
+// This file describes structure of jsonnet source code
+// It is also used to generate files in src/generated
+
+// Token names ending with `!` are considered meta, and handled specifically
+
SourceFile = Expr
ExprBinary =
- lhs:Expr
+ lhs:LhsExpr
BinaryOperator
rhs:Expr
ExprUnary =
@@ -9,29 +14,23 @@
rhs:Expr
ExprSlice =
Expr
- '['
SliceDesc
- ']'
ExprIndex =
Expr
'.'
index:Name
ExprIndexExpr =
- base:Expr
+ base:LhsExpr
'['
index:Expr
']'
ExprApply =
Expr
- '('
ArgsDesc
- ')'
'tailstrict'?
ExprObjExtend =
+ LhsExpr
Expr
- '{'
- ObjBody
- '}'
ExprParened =
'('
Expr
@@ -64,13 +63,16 @@
'['
Expr
','?
- ForSpec
CompSpec*
']'
+
ExprImport =
- 'importstr' String
-| 'importbin' String
-| 'import' String
+ ImportKind String
+
+ImportKind =
+ 'importstr'
+| 'importbin'
+| 'import'
ExprVar =
name:Name
@@ -78,12 +80,15 @@
'local'
(Bind (',' Bind)* ','?)
';'
+ Expr
+
ExprIfThenElse =
'if'
cond:Expr
'then'
- then:Expr
- ('else' else_:Expr)?
+ then:TrueExpr
+ ('else' else_:FalseExpr)?
+
ExprFunction =
'function'
'('
@@ -112,6 +117,7 @@
| ExprIntrinsic
| ExprString
| ExprNumber
+| ExprLiteral
| ExprArray
| ExprObject
| ExprArrayComp
@@ -130,42 +136,48 @@
| '<<' | '>>'
| '+' | '-'
| '*' | '/' | '%'
+| 'ERROR_NO_OPERATOR!'
UnaryOperator =
'-' | '!' | '~'
+SliceDescEnd=Expr
+SliceDescStep=Expr
SliceDesc =
+ '['
from:Expr?
':'
(
- end:Expr?
+ end:SliceDescEnd?
(
':'
- step:Expr?
+ step:SliceDescStep?
)?
)?
+ ']'
Name =
- 'ident'
+ 'LIT_IDENT!'
ArgsDesc =
+ '('
(Arg (',' Arg)* ','?)?
+ ')'
Arg =
(name:Name '=')? Expr
ObjBodyComp =
pre:ObjLocalPostComma*
'['
- key:Expr
+ key:LhsExpr
']'
'+'?
':'
value:Expr
post:ObjLocalPreComma*
- ForSpec
CompSpec*
ObjBodyMemberList =
- (Member (',' Member) ','?)?
+ (Member (',' Member)* ','?)?
ObjBody =
ObjBodyComp
| ObjBodyMemberList
@@ -196,9 +208,7 @@
Expr
FieldMethod =
FieldName
- '('
ParamsDesc
- ')'
Visibility
Expr
Field =
@@ -230,14 +240,15 @@
| 'super'
String =
- 'string_double'
-| 'string_single'
-| 'string_double_verbatim'
-| 'string_single_verbatim'
-| 'string_block'
+ 'LIT_STRING_DOUBLE!'
+| 'LIT_STRING_SINGLE!'
+| 'LIT_STRING_DOUBLE_VERBATIM!'
+| 'LIT_STRING_SINGLE_VERBATIM!'
+| 'LIT_STRING_BLOCK!'
Number =
- 'number'
+ 'LIT_FLOAT!'
+| 'META_FORCE_ENUM!'
ForSpec =
'for'
@@ -257,9 +268,7 @@
value:Expr
BindFunction =
name:Name
- '('
params:ParamsDesc
- ')'
'='
value:Expr
Bind =
@@ -267,7 +276,9 @@
| BindFunction
ParamsDesc =
+ '('
(Param (',' Param)* ','?)?
+ ')'
Param =
Destruct
(
@@ -277,30 +288,23 @@
Assertion =
'assert'
- condition:Expr
+ condition:LhsExpr
(
':'
- Expr
+ message:Expr
)?
DestructFull =
- into:Name
+ Name
DestructSkip =
'?'
DestructArray =
'['
- start:(
- Destruct
- (',' Destruct)*
+ (
+ DestructArrayPart
+ (',' DestructArrayPart)*
','?
)?
- DestructRest?
- ','?
- end:(
- Destruct
- (',' Destruct)*
- ','?
- )
']'
DestructObject =
'{'
@@ -314,10 +318,16 @@
'}'
Destruct =
DestructFull
- DestructSkip
- DestructArray
- DestructObject
+| DestructSkip
+| DestructArray
+| DestructObject
+DestructArrayElement =
+ Destruct
+DestructArrayPart =
+ DestructArrayElement
+| DestructRest
+
DestructRest =
'...'
into:Name?
@@ -332,3 +342,8 @@
'='
Expr
)?
+
+// Aliases used to resolve node type conflicts
+TrueExpr=Expr
+FalseExpr=Expr
+LhsExpr=Expr
crates/jrsonnet-rowan-parser/src/ast.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/ast.rs
+++ b/crates/jrsonnet-rowan-parser/src/ast.rs
@@ -1 +1,95 @@
-pub trait AstToken {}
+use std::marker::PhantomData;
+
+use crate::{SyntaxKind, SyntaxNode, SyntaxNodeChildren, SyntaxToken};
+
+/// The main trait to go from untyped `SyntaxNode` to a typed ast. The
+/// conversion itself has zero runtime cost: ast and syntax nodes have exactly
+/// the same representation: a pointer to the tree root and a pointer to the
+/// node itself.
+pub trait AstNode {
+ fn can_cast(kind: SyntaxKind) -> bool
+ where
+ Self: Sized;
+
+ fn cast(syntax: SyntaxNode) -> Option<Self>
+ where
+ Self: Sized;
+
+ fn syntax(&self) -> &SyntaxNode;
+ fn clone_for_update(&self) -> Self
+ where
+ Self: Sized,
+ {
+ Self::cast(self.syntax().clone_for_update()).unwrap()
+ }
+ fn clone_subtree(&self) -> Self
+ where
+ Self: Sized,
+ {
+ Self::cast(self.syntax().clone_subtree()).unwrap()
+ }
+}
+
+/// Like `AstNode`, but wraps tokens rather than interior nodes.
+pub trait AstToken {
+ fn can_cast(token: SyntaxKind) -> bool
+ where
+ Self: Sized;
+
+ fn cast(syntax: SyntaxToken) -> Option<Self>
+ where
+ Self: Sized;
+
+ fn syntax(&self) -> &SyntaxToken;
+
+ fn text(&self) -> &str {
+ self.syntax().text()
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct AstChildren<N> {
+ inner: SyntaxNodeChildren,
+ ph: PhantomData<N>,
+}
+
+impl<N> AstChildren<N> {
+ fn new(parent: &SyntaxNode) -> Self {
+ AstChildren {
+ inner: parent.children(),
+ ph: PhantomData,
+ }
+ }
+}
+
+impl<N: AstNode> Iterator for AstChildren<N> {
+ type Item = N;
+ fn next(&mut self) -> Option<N> {
+ self.inner.find_map(N::cast)
+ }
+}
+
+pub mod support {
+ use super::{AstChildren, AstNode, AstToken, SyntaxKind, SyntaxNode, SyntaxToken};
+
+ pub fn child<N: AstNode>(parent: &SyntaxNode) -> Option<N> {
+ parent.children().find_map(N::cast)
+ }
+ pub fn token_child<N: AstToken>(parent: &SyntaxNode) -> Option<N> {
+ parent.children_with_tokens().find_map(|n| match n {
+ rowan::NodeOrToken::Node(_) => None,
+ rowan::NodeOrToken::Token(t) => N::cast(t),
+ })
+ }
+
+ pub fn children<N: AstNode>(parent: &SyntaxNode) -> AstChildren<N> {
+ AstChildren::new(parent)
+ }
+
+ pub fn token(parent: &SyntaxNode, kind: SyntaxKind) -> Option<SyntaxToken> {
+ parent
+ .children_with_tokens()
+ .filter_map(|it| it.into_token())
+ .find(|it| it.kind() == kind)
+ }
+}
crates/jrsonnet-rowan-parser/src/binary.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/binary.rs
+++ b/crates/jrsonnet-rowan-parser/src/binary.rs
@@ -20,6 +20,7 @@
Or,
In,
ObjectApply,
+ #[allow(dead_code)]
Invalid,
}
crates/jrsonnet-rowan-parser/src/classify.rsdiffbeforeafterboth--- /dev/null
+++ b/crates/jrsonnet-rowan-parser/src/classify.rs
@@ -0,0 +1,51 @@
+use crate::SyntaxKind;
+
+impl SyntaxKind {
+ pub fn is_trivia(self) -> bool {
+ matches!(
+ self,
+ Self::WHITESPACE
+ | Self::MULTI_LINE_COMMENT
+ | Self::ERROR_COMMENT_TOO_SHORT
+ | Self::ERROR_COMMENT_UNTERMINATED
+ | Self::SINGLE_LINE_HASH_COMMENT
+ | Self::SINGLE_LINE_SLASH_COMMENT
+ )
+ }
+ pub fn is_string(self) -> bool {
+ matches!(
+ self,
+ Self::STRING_SINGLE
+ | Self::ERROR_STRING_SINGLE_UNTERMINATED
+ | Self::STRING_DOUBLE
+ | Self::ERROR_STRING_DOUBLE_UNTERMINATED
+ | Self::STRING_SINGLE_VERBATIM
+ | Self::ERROR_STRING_SINGLE_VERBATIM_UNTERMINATED
+ | Self::STRING_DOUBLE_VERBATIM
+ | Self::ERROR_STRING_DOUBLE_VERBATIM_UNTERMINATED
+ | Self::STRING_BLOCK
+ | Self::ERROR_STRING_BLOCK_UNEXPECTED_END
+ | Self::ERROR_STRING_BLOCK_MISSING_NEW_LINE
+ | Self::ERROR_STRING_BLOCK_MISSING_TERMINATION
+ | Self::ERROR_STRING_BLOCK_MISSING_INDENT
+ )
+ }
+ pub fn is_number(self) -> bool {
+ matches!(
+ self,
+ Self::FLOAT
+ | Self::ERROR_FLOAT_JUNK_AFTER_POINT
+ | Self::ERROR_FLOAT_JUNK_AFTER_EXPONENT
+ | Self::ERROR_FLOAT_JUNK_AFTER_EXPONENT_SIGN
+ )
+ }
+ pub fn is_literal(self) -> bool {
+ matches!(
+ self,
+ Self::NULL_KW
+ | Self::TRUE_KW | Self::FALSE_KW
+ | Self::SELF_KW | Self::DOLLAR
+ | Self::SUPER_KW
+ )
+ }
+}
crates/jrsonnet-rowan-parser/src/event.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/event.rs
+++ b/crates/jrsonnet-rowan-parser/src/event.rs
@@ -1,6 +1,6 @@
use std::mem;
-use rowan::{GreenNode, GreenNodeBuilder, Language};
+use rowan::{GreenNodeBuilder, Language};
use crate::{
lex::Lexeme,
@@ -10,14 +10,27 @@
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Event {
+ /// Used for unfinished markers
+ Pending,
+ /// After marker is completed, Pending event is replaced with Start
Start {
kind: SyntaxKind,
+ /// If marker is preceded or wrapped - instead of reordering events, we
+ /// insert start event in the end of events Vec instead, and store relative offset to this event here
forward_parent: Option<usize>,
},
- Token,
- Finish,
- Placeholder,
+ /// Eat token
+ Token {
+ kind: SyntaxKind,
+ },
+ /// Position of finished node
+ Finish {
+ /// Same as forward_parent of Start, but for wrapping
+ wrapper: Option<usize>,
+ },
Error(SyntaxError),
+ /// Used for dropped markers and other things
+ Noop,
}
pub(super) struct Sink<'i> {
@@ -40,12 +53,17 @@
}
pub(super) fn finish(mut self) -> Parse {
+ let mut eat_start_whitespace = false;
+ let mut depth = 0;
for idx in 0..self.events.len() {
- match mem::replace(&mut self.events[idx], Event::Placeholder) {
+ match mem::replace(&mut self.events[idx], Event::Noop) {
Event::Start {
kind,
forward_parent,
} => {
+ if depth != 0 {
+ self.skip_whitespace();
+ }
let mut kinds = vec![kind];
let mut idx = idx;
@@ -60,7 +78,7 @@
forward_parent = if let Event::Start {
kind,
forward_parent,
- } = mem::replace(&mut self.events[idx], Event::Placeholder)
+ } = mem::replace(&mut self.events[idx], Event::Noop)
{
kinds.push(kind);
forward_parent
@@ -71,18 +89,46 @@
for kind in kinds.into_iter().rev() {
self.builder.start_node(JsonnetLanguage::kind_to_raw(kind));
+ depth += 1;
+ if depth == 1 {
+ self.skip_whitespace();
+ }
+ }
+
+ eat_start_whitespace = false;
+ }
+ Event::Token { kind } => {
+ if eat_start_whitespace {
+ self.skip_whitespace();
}
+ self.token(kind);
+ eat_start_whitespace = true;
}
- Event::Token => self.token(),
- Event::Finish => {
+ Event::Finish { wrapper } => {
self.builder.finish_node();
+ depth -= 1;
+ let mut idx = idx;
+ let mut wrapper = wrapper;
+ while let Some(w) = wrapper {
+ idx += w;
+ wrapper = if let Event::Finish { wrapper } =
+ mem::replace(&mut self.events[idx], Event::Noop)
+ {
+ self.builder.finish_node();
+ depth -= 1;
+ wrapper
+ } else {
+ unreachable!()
+ }
+ }
+ eat_start_whitespace = true;
}
- Event::Placeholder => {}
+ Event::Pending => panic!("placeholder should not end in events"),
+ Event::Noop => {}
Event::Error(e) => {
self.errors.push(e);
}
}
- self.skip_whitespace();
}
Parse {
@@ -90,10 +136,10 @@
errors: self.errors,
}
}
- fn token(&mut self) {
+ fn token(&mut self, kind: SyntaxKind) {
let lexeme = self.lexemes[self.offset];
self.builder
- .token(JsonnetLanguage::kind_to_raw(lexeme.kind), lexeme.text);
+ .token(JsonnetLanguage::kind_to_raw(kind), lexeme.text);
self.offset += 1;
}
fn skip_whitespace(&mut self) {
@@ -102,7 +148,7 @@
break;
}
- self.token();
+ self.token(lexeme.kind);
}
}
}
crates/jrsonnet-rowan-parser/src/generated/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/generated/mod.rs
+++ b/crates/jrsonnet-rowan-parser/src/generated/mod.rs
@@ -1,3 +1,2 @@
-// mod tokens;
-// mod nodes;
+pub mod nodes;
pub mod syntax_kinds;
crates/jrsonnet-rowan-parser/src/generated/nodes.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/generated/nodes.rs
+++ b/crates/jrsonnet-rowan-parser/src/generated/nodes.rs
@@ -1,9 +1,9 @@
//! This is a generated file, please do not edit manually. Changes can be
//! made in codegeneration that lives in `xtask` top-level dir.
-#![allow(non_snake_case)]
+#![allow(non_snake_case, clippy::match_like_matches_macro)]
use crate::{
- ast::{self, support, AstChildren, AstNode},
+ ast::{support, AstChildren, AstNode, AstToken},
SyntaxKind::{self, *},
SyntaxNode, SyntaxToken, T,
};
@@ -13,7 +13,9 @@
pub(crate) syntax: SyntaxNode,
}
impl SourceFile {
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -21,35 +23,25 @@
pub(crate) syntax: SyntaxNode,
}
impl ExprBinary {
- pub fn lhs(&self) -> Option<Expr> { support::child(&self.syntax) }
- pub fn binary_operator(&self) -> Option<BinaryOperator> { support::child(&self.syntax) }
- pub fn rhs(&self) -> Option<Expr> { support::child(&self.syntax) }
+ pub fn lhs(&self) -> Option<LhsExpr> {
+ support::child(&self.syntax)
+ }
+ pub fn binary_operator(&self) -> Option<BinaryOperator> {
+ support::token_child(&self.syntax)
+ }
+ pub fn rhs(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct BinaryOperator {
+pub struct LhsExpr {
pub(crate) syntax: SyntaxNode,
}
-impl BinaryOperator {
- pub fn or_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![||]) }
- pub fn and_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&&]) }
- pub fn bit_or_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![|]) }
- pub fn bit_xor_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![^]) }
- pub fn bit_and_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
- pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![==]) }
- pub fn ne_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!=]) }
- pub fn lt_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
- pub fn gt_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
- pub fn le_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<=]) }
- pub fn ge_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>=]) }
- pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) }
- pub fn lhs_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<<]) }
- pub fn rhs_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>>]) }
- pub fn plus_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![+]) }
- pub fn minus_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![-]) }
- pub fn mul_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) }
- pub fn div_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![/]) }
- pub fn modulo_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![%]) }
+impl LhsExpr {
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -57,29 +49,25 @@
pub(crate) syntax: SyntaxNode,
}
impl ExprUnary {
- pub fn unary_operator(&self) -> Option<UnaryOperator> { support::child(&self.syntax) }
- pub fn rhs(&self) -> Option<Expr> { support::child(&self.syntax) }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct UnaryOperator {
- pub(crate) syntax: SyntaxNode,
+ pub fn unary_operator(&self) -> Option<UnaryOperator> {
+ support::token_child(&self.syntax)
+ }
+ pub fn rhs(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
}
-impl UnaryOperator {
- pub fn minus_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![-]) }
- pub fn not_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
- pub fn bit_not_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![~]) }
-}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ExprSlice {
pub(crate) syntax: SyntaxNode,
}
impl ExprSlice {
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
- pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
- pub fn slice_desc(&self) -> Option<SliceDesc> { support::child(&self.syntax) }
- pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
+ pub fn slice_desc(&self) -> Option<SliceDesc> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -87,10 +75,24 @@
pub(crate) syntax: SyntaxNode,
}
impl SliceDesc {
- pub fn from(&self) -> Option<Expr> { support::child(&self.syntax) }
- pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
- pub fn end(&self) -> Option<Expr> { support::child(&self.syntax) }
- pub fn step(&self) -> Option<Expr> { support::child(&self.syntax) }
+ pub fn l_brack_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T!['['])
+ }
+ pub fn from(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
+ pub fn colon_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![:])
+ }
+ pub fn end(&self) -> Option<SliceDescEnd> {
+ support::child(&self.syntax)
+ }
+ pub fn step(&self) -> Option<SliceDescStep> {
+ support::child(&self.syntax)
+ }
+ pub fn r_brack_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![']'])
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -98,9 +100,15 @@
pub(crate) syntax: SyntaxNode,
}
impl ExprIndex {
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
- pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
- pub fn index(&self) -> Option<Name> { support::child(&self.syntax) }
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
+ pub fn dot_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![.])
+ }
+ pub fn index(&self) -> Option<Name> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -108,7 +116,9 @@
pub(crate) syntax: SyntaxNode,
}
impl Name {
- pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) }
+ pub fn ident_lit(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, IDENT)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -116,10 +126,18 @@
pub(crate) syntax: SyntaxNode,
}
impl ExprIndexExpr {
- pub fn base(&self) -> Option<Expr> { support::child(&self.syntax) }
- pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
- pub fn index(&self) -> Option<Expr> { support::child(&self.syntax) }
- pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+ pub fn base(&self) -> Option<LhsExpr> {
+ support::child(&self.syntax)
+ }
+ pub fn l_brack_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T!['['])
+ }
+ pub fn index(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
+ pub fn r_brack_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![']'])
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -127,11 +145,13 @@
pub(crate) syntax: SyntaxNode,
}
impl ExprApply {
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
- pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
- pub fn args_desc(&self) -> Option<ArgsDesc> { support::child(&self.syntax) }
- pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
- pub fn tailstrict_token(&self) -> Option<SyntaxToken> {
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
+ pub fn args_desc(&self) -> Option<ArgsDesc> {
+ support::child(&self.syntax)
+ }
+ pub fn tailstrict_kw_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, T![tailstrict])
}
}
@@ -141,7 +161,15 @@
pub(crate) syntax: SyntaxNode,
}
impl ArgsDesc {
- pub fn args(&self) -> AstChildren<Arg> { support::children(&self.syntax) }
+ pub fn l_paren_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T!['('])
+ }
+ pub fn args(&self) -> AstChildren<Arg> {
+ support::children(&self.syntax)
+ }
+ pub fn r_paren_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![')'])
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -149,10 +177,12 @@
pub(crate) syntax: SyntaxNode,
}
impl ExprObjExtend {
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
- pub fn l_brace_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
- pub fn obj_body(&self) -> Option<ObjBody> { support::child(&self.syntax) }
- pub fn r_brace_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+ pub fn lhs_expr(&self) -> Option<LhsExpr> {
+ support::child(&self.syntax)
+ }
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -160,9 +190,15 @@
pub(crate) syntax: SyntaxNode,
}
impl ExprParened {
- pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
- pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+ pub fn l_paren_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T!['('])
+ }
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
+ pub fn r_paren_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![')'])
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -170,20 +206,9 @@
pub(crate) syntax: SyntaxNode,
}
impl ExprLiteral {
- pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Literal {
- pub(crate) syntax: SyntaxNode,
-}
-impl Literal {
- pub fn null_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![null]) }
- pub fn true_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![true]) }
- pub fn false_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![false]) }
- pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
- pub fn dollar_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['$']) }
- pub fn super_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![super]) }
+ pub fn literal(&self) -> Option<Literal> {
+ support::token_child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -214,9 +239,15 @@
pub fn intrinsic_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, T!["$intrinsic"])
}
- pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
- pub fn name(&self) -> Option<Name> { support::child(&self.syntax) }
- pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+ pub fn l_paren_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T!['('])
+ }
+ pub fn name(&self) -> Option<Name> {
+ support::child(&self.syntax)
+ }
+ pub fn r_paren_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![')'])
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -224,28 +255,8 @@
pub(crate) syntax: SyntaxNode,
}
impl ExprString {
- pub fn string(&self) -> Option<String> { support::child(&self.syntax) }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct String {
- pub(crate) syntax: SyntaxNode,
-}
-impl String {
- pub fn string_double_token(&self) -> Option<SyntaxToken> {
- support::token(&self.syntax, T![string_double])
- }
- pub fn string_single_token(&self) -> Option<SyntaxToken> {
- support::token(&self.syntax, T![string_single])
- }
- pub fn string_double_verbatim_token(&self) -> Option<SyntaxToken> {
- support::token(&self.syntax, T![string_double_verbatim])
- }
- pub fn string_single_verbatim_token(&self) -> Option<SyntaxToken> {
- support::token(&self.syntax, T![string_single_verbatim])
- }
- pub fn string_block_token(&self) -> Option<SyntaxToken> {
- support::token(&self.syntax, T![string_block])
+ pub fn string(&self) -> Option<String> {
+ support::token_child(&self.syntax)
}
}
@@ -254,25 +265,25 @@
pub(crate) syntax: SyntaxNode,
}
impl ExprNumber {
- pub fn number(&self) -> Option<Number> { support::child(&self.syntax) }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Number {
- pub(crate) syntax: SyntaxNode,
+ pub fn number(&self) -> Option<Number> {
+ support::token_child(&self.syntax)
+ }
}
-impl Number {
- pub fn number_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![number]) }
-}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ExprArray {
pub(crate) syntax: SyntaxNode,
}
impl ExprArray {
- pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
- pub fn exprs(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
- pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+ pub fn l_brack_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T!['['])
+ }
+ pub fn exprs(&self) -> AstChildren<Expr> {
+ support::children(&self.syntax)
+ }
+ pub fn r_brack_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![']'])
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -280,9 +291,15 @@
pub(crate) syntax: SyntaxNode,
}
impl ExprObject {
- pub fn l_brace_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
- pub fn obj_body(&self) -> Option<ObjBody> { support::child(&self.syntax) }
- pub fn r_brace_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+ pub fn l_brace_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T!['{'])
+ }
+ pub fn obj_body(&self) -> Option<ObjBody> {
+ support::child(&self.syntax)
+ }
+ pub fn r_brace_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T!['}'])
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -290,38 +307,34 @@
pub(crate) syntax: SyntaxNode,
}
impl ExprArrayComp {
- pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
- pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
- pub fn for_spec(&self) -> Option<ForSpec> { support::child(&self.syntax) }
- pub fn comp_specs(&self) -> AstChildren<CompSpec> { support::children(&self.syntax) }
- pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ForSpec {
- pub(crate) syntax: SyntaxNode,
+ pub fn l_brack_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T!['['])
+ }
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
+ pub fn comma_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![,])
+ }
+ pub fn comp_specs(&self) -> AstChildren<CompSpec> {
+ support::children(&self.syntax)
+ }
+ pub fn r_brack_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![']'])
+ }
}
-impl ForSpec {
- pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
- pub fn bind(&self) -> Option<Name> { support::child(&self.syntax) }
- pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) }
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
-}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ExprImport {
pub(crate) syntax: SyntaxNode,
}
impl ExprImport {
- pub fn importstr_token(&self) -> Option<SyntaxToken> {
- support::token(&self.syntax, T![importstr])
+ pub fn import_kind(&self) -> Option<ImportKind> {
+ support::token_child(&self.syntax)
}
- pub fn string(&self) -> Option<String> { support::child(&self.syntax) }
- pub fn importbin_token(&self) -> Option<SyntaxToken> {
- support::token(&self.syntax, T![importbin])
+ pub fn string(&self) -> Option<String> {
+ support::token_child(&self.syntax)
}
- pub fn import_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![import]) }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -329,7 +342,9 @@
pub(crate) syntax: SyntaxNode,
}
impl ExprVar {
- pub fn name(&self) -> Option<Name> { support::child(&self.syntax) }
+ pub fn name(&self) -> Option<Name> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -337,9 +352,18 @@
pub(crate) syntax: SyntaxNode,
}
impl ExprLocal {
- pub fn local_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![local]) }
- pub fn binds(&self) -> AstChildren<Bind> { support::children(&self.syntax) }
- pub fn semi_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+ pub fn local_kw_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![local])
+ }
+ pub fn binds(&self) -> AstChildren<Bind> {
+ support::children(&self.syntax)
+ }
+ pub fn semi_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![;])
+ }
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -347,12 +371,44 @@
pub(crate) syntax: SyntaxNode,
}
impl ExprIfThenElse {
- pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) }
- pub fn cond(&self) -> Option<Expr> { support::child(&self.syntax) }
- pub fn then_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![then]) }
- pub fn then(&self) -> Option<Expr> { support::child(&self.syntax) }
- pub fn else_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![else]) }
- pub fn else_(&self) -> Option<Expr> { support::child(&self.syntax) }
+ pub fn if_kw_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![if])
+ }
+ pub fn cond(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
+ pub fn then_kw_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![then])
+ }
+ pub fn then(&self) -> Option<TrueExpr> {
+ support::child(&self.syntax)
+ }
+ pub fn else_kw_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![else])
+ }
+ pub fn else_(&self) -> Option<FalseExpr> {
+ support::child(&self.syntax)
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct TrueExpr {
+ pub(crate) syntax: SyntaxNode,
+}
+impl TrueExpr {
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct FalseExpr {
+ pub(crate) syntax: SyntaxNode,
+}
+impl FalseExpr {
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -360,13 +416,21 @@
pub(crate) syntax: SyntaxNode,
}
impl ExprFunction {
- pub fn function_token(&self) -> Option<SyntaxToken> {
+ pub fn function_kw_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, T![function])
}
- pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
- pub fn params_desc(&self) -> Option<ParamsDesc> { support::child(&self.syntax) }
- pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+ pub fn l_paren_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T!['('])
+ }
+ pub fn params_desc(&self) -> Option<ParamsDesc> {
+ support::child(&self.syntax)
+ }
+ pub fn r_paren_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![')'])
+ }
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -374,7 +438,15 @@
pub(crate) syntax: SyntaxNode,
}
impl ParamsDesc {
- pub fn params(&self) -> AstChildren<Param> { support::children(&self.syntax) }
+ pub fn l_paren_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T!['('])
+ }
+ pub fn params(&self) -> AstChildren<Param> {
+ support::children(&self.syntax)
+ }
+ pub fn r_paren_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![')'])
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -382,9 +454,15 @@
pub(crate) syntax: SyntaxNode,
}
impl ExprAssert {
- pub fn assertion(&self) -> Option<Assertion> { support::child(&self.syntax) }
- pub fn semi_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+ pub fn assertion(&self) -> Option<Assertion> {
+ support::child(&self.syntax)
+ }
+ pub fn semi_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![;])
+ }
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -392,10 +470,18 @@
pub(crate) syntax: SyntaxNode,
}
impl Assertion {
- pub fn assert_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![assert]) }
- pub fn condition(&self) -> Option<Expr> { support::child(&self.syntax) }
- pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+ pub fn assert_kw_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![assert])
+ }
+ pub fn condition(&self) -> Option<LhsExpr> {
+ support::child(&self.syntax)
+ }
+ pub fn colon_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![:])
+ }
+ pub fn message(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -403,18 +489,48 @@
pub(crate) syntax: SyntaxNode,
}
impl ExprError {
- pub fn error_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![error]) }
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+ pub fn error_kw_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![error])
+ }
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct SliceDescEnd {
+ pub(crate) syntax: SyntaxNode,
+}
+impl SliceDescEnd {
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct SliceDescStep {
+ pub(crate) syntax: SyntaxNode,
+}
+impl SliceDescStep {
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Arg {
pub(crate) syntax: SyntaxNode,
}
impl Arg {
- pub fn name(&self) -> Option<Name> { support::child(&self.syntax) }
- pub fn assign_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+ pub fn name(&self) -> Option<Name> {
+ support::child(&self.syntax)
+ }
+ pub fn assign_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![=])
+ }
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -422,16 +538,33 @@
pub(crate) syntax: SyntaxNode,
}
impl ObjBodyComp {
- pub fn pre(&self) -> AstChildren<ObjLocalPostComma> { support::children(&self.syntax) }
- pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
- pub fn key(&self) -> Option<Expr> { support::child(&self.syntax) }
- pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
- pub fn plus_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![+]) }
- pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
- pub fn value(&self) -> Option<Expr> { support::child(&self.syntax) }
- pub fn post(&self) -> AstChildren<ObjLocalPreComma> { support::children(&self.syntax) }
- pub fn for_spec(&self) -> Option<ForSpec> { support::child(&self.syntax) }
- pub fn comp_specs(&self) -> AstChildren<CompSpec> { support::children(&self.syntax) }
+ pub fn pre(&self) -> AstChildren<ObjLocalPostComma> {
+ support::children(&self.syntax)
+ }
+ pub fn l_brack_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T!['['])
+ }
+ pub fn key(&self) -> Option<LhsExpr> {
+ support::child(&self.syntax)
+ }
+ pub fn r_brack_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![']'])
+ }
+ pub fn plus_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![+])
+ }
+ pub fn colon_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![:])
+ }
+ pub fn value(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
+ pub fn post(&self) -> AstChildren<ObjLocalPreComma> {
+ support::children(&self.syntax)
+ }
+ pub fn comp_specs(&self) -> AstChildren<CompSpec> {
+ support::children(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -439,8 +572,12 @@
pub(crate) syntax: SyntaxNode,
}
impl ObjLocalPostComma {
- pub fn obj_local(&self) -> Option<ObjLocal> { support::child(&self.syntax) }
- pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
+ pub fn obj_local(&self) -> Option<ObjLocal> {
+ support::child(&self.syntax)
+ }
+ pub fn comma_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![,])
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -448,8 +585,12 @@
pub(crate) syntax: SyntaxNode,
}
impl ObjLocalPreComma {
- pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
- pub fn obj_local(&self) -> Option<ObjLocal> { support::child(&self.syntax) }
+ pub fn comma_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![,])
+ }
+ pub fn obj_local(&self) -> Option<ObjLocal> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -457,8 +598,9 @@
pub(crate) syntax: SyntaxNode,
}
impl ObjBodyMemberList {
- pub fn member(&self) -> Option<Member> { support::child(&self.syntax) }
- pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
+ pub fn members(&self) -> AstChildren<Member> {
+ support::children(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -466,8 +608,12 @@
pub(crate) syntax: SyntaxNode,
}
impl ObjLocal {
- pub fn local_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![local]) }
- pub fn bind(&self) -> Option<Bind> { support::child(&self.syntax) }
+ pub fn local_kw_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![local])
+ }
+ pub fn bind(&self) -> Option<Bind> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -475,7 +621,9 @@
pub(crate) syntax: SyntaxNode,
}
impl MemberBindStmt {
- pub fn obj_local(&self) -> Option<ObjLocal> { support::child(&self.syntax) }
+ pub fn obj_local(&self) -> Option<ObjLocal> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -483,7 +631,9 @@
pub(crate) syntax: SyntaxNode,
}
impl MemberAssertStmt {
- pub fn assertion(&self) -> Option<Assertion> { support::child(&self.syntax) }
+ pub fn assertion(&self) -> Option<Assertion> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -491,7 +641,9 @@
pub(crate) syntax: SyntaxNode,
}
impl MemberField {
- pub fn field(&self) -> Option<Field> { support::child(&self.syntax) }
+ pub fn field(&self) -> Option<Field> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -499,22 +651,18 @@
pub(crate) syntax: SyntaxNode,
}
impl FieldNormal {
- pub fn field_name(&self) -> Option<FieldName> { support::child(&self.syntax) }
- pub fn plus_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![+]) }
- pub fn visibility(&self) -> Option<Visibility> { support::child(&self.syntax) }
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Visibility {
- pub(crate) syntax: SyntaxNode,
-}
-impl Visibility {
- pub fn coloncoloncolon_token(&self) -> Option<SyntaxToken> {
- support::token(&self.syntax, T![:::])
+ pub fn field_name(&self) -> Option<FieldName> {
+ support::child(&self.syntax)
+ }
+ pub fn plus_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![+])
+ }
+ pub fn visibility(&self) -> Option<Visibility> {
+ support::token_child(&self.syntax)
+ }
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
}
- pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
- pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -522,12 +670,18 @@
pub(crate) syntax: SyntaxNode,
}
impl FieldMethod {
- pub fn field_name(&self) -> Option<FieldName> { support::child(&self.syntax) }
- pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
- pub fn params_desc(&self) -> Option<ParamsDesc> { support::child(&self.syntax) }
- pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
- pub fn visibility(&self) -> Option<Visibility> { support::child(&self.syntax) }
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+ pub fn field_name(&self) -> Option<FieldName> {
+ support::child(&self.syntax)
+ }
+ pub fn params_desc(&self) -> Option<ParamsDesc> {
+ support::child(&self.syntax)
+ }
+ pub fn visibility(&self) -> Option<Visibility> {
+ support::token_child(&self.syntax)
+ }
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -535,8 +689,12 @@
pub(crate) syntax: SyntaxNode,
}
impl FieldNameFixed {
- pub fn id(&self) -> Option<Name> { support::child(&self.syntax) }
- pub fn string(&self) -> Option<String> { support::child(&self.syntax) }
+ pub fn id(&self) -> Option<Name> {
+ support::child(&self.syntax)
+ }
+ pub fn string(&self) -> Option<String> {
+ support::token_child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -544,39 +702,63 @@
pub(crate) syntax: SyntaxNode,
}
impl FieldNameDynamic {
- pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
- pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+ pub fn l_brack_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T!['['])
+ }
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
+ pub fn r_brack_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![']'])
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct IfSpec {
+pub struct ForSpec {
pub(crate) syntax: SyntaxNode,
}
-impl IfSpec {
- pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) }
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+impl ForSpec {
+ pub fn for_kw_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![for])
+ }
+ pub fn bind(&self) -> Option<Name> {
+ support::child(&self.syntax)
+ }
+ pub fn in_kw_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![in])
+ }
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct BindDestruct {
+pub struct IfSpec {
pub(crate) syntax: SyntaxNode,
}
-impl BindDestruct {
- pub fn into(&self) -> Option<Destruct> { support::child(&self.syntax) }
- pub fn assign_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
- pub fn value(&self) -> Option<Expr> { support::child(&self.syntax) }
+impl IfSpec {
+ pub fn if_kw_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![if])
+ }
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Destruct {
+pub struct BindDestruct {
pub(crate) syntax: SyntaxNode,
}
-impl Destruct {
- pub fn destruct_full(&self) -> Option<DestructFull> { support::child(&self.syntax) }
- pub fn destruct_skip(&self) -> Option<DestructSkip> { support::child(&self.syntax) }
- pub fn destruct_array(&self) -> Option<DestructArray> { support::child(&self.syntax) }
- pub fn destruct_object(&self) -> Option<DestructObject> { support::child(&self.syntax) }
+impl BindDestruct {
+ pub fn into(&self) -> Option<Destruct> {
+ support::child(&self.syntax)
+ }
+ pub fn assign_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![=])
+ }
+ pub fn value(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -584,12 +766,18 @@
pub(crate) syntax: SyntaxNode,
}
impl BindFunction {
- pub fn name(&self) -> Option<Name> { support::child(&self.syntax) }
- pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
- pub fn params(&self) -> Option<ParamsDesc> { support::child(&self.syntax) }
- pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
- pub fn assign_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
- pub fn value(&self) -> Option<Expr> { support::child(&self.syntax) }
+ pub fn name(&self) -> Option<Name> {
+ support::child(&self.syntax)
+ }
+ pub fn params(&self) -> Option<ParamsDesc> {
+ support::child(&self.syntax)
+ }
+ pub fn assign_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![=])
+ }
+ pub fn value(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -597,9 +785,15 @@
pub(crate) syntax: SyntaxNode,
}
impl Param {
- pub fn destruct(&self) -> Option<Destruct> { support::child(&self.syntax) }
- pub fn assign_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+ pub fn destruct(&self) -> Option<Destruct> {
+ support::child(&self.syntax)
+ }
+ pub fn assign_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![=])
+ }
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -607,7 +801,9 @@
pub(crate) syntax: SyntaxNode,
}
impl DestructFull {
- pub fn into(&self) -> Option<Name> { support::child(&self.syntax) }
+ pub fn name(&self) -> Option<Name> {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -615,7 +811,9 @@
pub(crate) syntax: SyntaxNode,
}
impl DestructSkip {
- pub fn question_mark_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![?]) }
+ pub fn question_mark_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![?])
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -623,21 +821,15 @@
pub(crate) syntax: SyntaxNode,
}
impl DestructArray {
- pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
- pub fn start(&self) -> AstChildren<Destruct> { support::children(&self.syntax) }
- pub fn destruct_rest(&self) -> Option<DestructRest> { support::child(&self.syntax) }
- pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
- pub fn end(&self) -> AstChildren<Destruct> { support::children(&self.syntax) }
- pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct DestructRest {
- pub(crate) syntax: SyntaxNode,
-}
-impl DestructRest {
- pub fn dotdotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![...]) }
- pub fn into(&self) -> Option<Name> { support::child(&self.syntax) }
+ pub fn l_brack_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T!['['])
+ }
+ pub fn destruct_array_parts(&self) -> AstChildren<DestructArrayPart> {
+ support::children(&self.syntax)
+ }
+ pub fn r_brack_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![']'])
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -645,13 +837,21 @@
pub(crate) syntax: SyntaxNode,
}
impl DestructObject {
- pub fn l_brace_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+ pub fn l_brace_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T!['{'])
+ }
pub fn destruct_object_fields(&self) -> AstChildren<DestructObjectField> {
support::children(&self.syntax)
}
- pub fn destruct_rest(&self) -> Option<DestructRest> { support::child(&self.syntax) }
- pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
- pub fn r_brace_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+ pub fn destruct_rest(&self) -> Option<DestructRest> {
+ support::child(&self.syntax)
+ }
+ pub fn comma_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![,])
+ }
+ pub fn r_brace_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T!['}'])
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -659,12 +859,45 @@
pub(crate) syntax: SyntaxNode,
}
impl DestructObjectField {
- pub fn field(&self) -> Option<Name> { support::child(&self.syntax) }
- pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
- pub fn destruct(&self) -> Option<Destruct> { support::child(&self.syntax) }
- pub fn assign_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+ pub fn field(&self) -> Option<Name> {
+ support::child(&self.syntax)
+ }
+ pub fn colon_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![:])
+ }
+ pub fn destruct(&self) -> Option<Destruct> {
+ support::child(&self.syntax)
+ }
+ pub fn assign_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![=])
+ }
+ pub fn expr(&self) -> Option<Expr> {
+ support::child(&self.syntax)
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct DestructRest {
+ pub(crate) syntax: SyntaxNode,
+}
+impl DestructRest {
+ pub fn dotdotdot_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![...])
+ }
+ pub fn into(&self) -> Option<Name> {
+ support::child(&self.syntax)
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct DestructArrayElement {
+ pub(crate) syntax: SyntaxNode,
}
+impl DestructArrayElement {
+ pub fn destruct(&self) -> Option<Destruct> {
+ support::child(&self.syntax)
+ }
+}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Expr {
@@ -681,6 +914,7 @@
ExprIntrinsic(ExprIntrinsic),
ExprString(ExprString),
ExprNumber(ExprNumber),
+ ExprLiteral(ExprLiteral),
ExprArray(ExprArray),
ExprObject(ExprObject),
ExprArrayComp(ExprArrayComp),
@@ -729,8 +963,136 @@
FieldNameFixed(FieldNameFixed),
FieldNameDynamic(FieldNameDynamic),
}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum Destruct {
+ DestructFull(DestructFull),
+ DestructSkip(DestructSkip),
+ DestructArray(DestructArray),
+ DestructObject(DestructObject),
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum DestructArrayPart {
+ DestructArrayElement(DestructArrayElement),
+ DestructRest(DestructRest),
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct BinaryOperator {
+ syntax: SyntaxToken,
+ kind: BinaryOperatorKind,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum BinaryOperatorKind {
+ Or,
+ And,
+ BitOr,
+ BitXor,
+ BitAnd,
+ Eq,
+ Ne,
+ Lt,
+ Gt,
+ Le,
+ Ge,
+ InKw,
+ Lhs,
+ Rhs,
+ Plus,
+ Minus,
+ Mul,
+ Div,
+ Modulo,
+ ErrorNoOperator,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct UnaryOperator {
+ syntax: SyntaxToken,
+ kind: UnaryOperatorKind,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum UnaryOperatorKind {
+ Minus,
+ Not,
+ BitNot,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Literal {
+ syntax: SyntaxToken,
+ kind: LiteralKind,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum LiteralKind {
+ NullKw,
+ TrueKw,
+ FalseKw,
+ SelfKw,
+ Dollar,
+ SuperKw,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct String {
+ syntax: SyntaxToken,
+ kind: StringKind,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum StringKind {
+ StringDouble,
+ StringSingle,
+ StringDoubleVerbatim,
+ StringSingleVerbatim,
+ StringBlock,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Number {
+ syntax: SyntaxToken,
+ kind: NumberKind,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum NumberKind {
+ Float,
+ MetaForceEnum,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ImportKind {
+ syntax: SyntaxToken,
+ kind: ImportKindKind,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum ImportKindKind {
+ ImportstrKw,
+ ImportbinKw,
+ ImportKw,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Visibility {
+ syntax: SyntaxToken,
+ kind: VisibilityKind,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum VisibilityKind {
+ Coloncoloncolon,
+ Coloncolon,
+ Colon,
+}
impl AstNode for SourceFile {
- fn can_cast(kind: SyntaxKind) -> bool { kind == SOURCE_FILE }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == SOURCE_FILE
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -738,10 +1100,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for ExprBinary {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_BINARY }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_BINARY
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -749,10 +1115,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for BinaryOperator {
- fn can_cast(kind: SyntaxKind) -> bool { kind == BINARY_OPERATOR }
+impl AstNode for LhsExpr {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == LHS_EXPR
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -760,10 +1130,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for ExprUnary {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_UNARY }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_UNARY
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -771,21 +1145,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
-}
-impl AstNode for UnaryOperator {
- fn can_cast(kind: SyntaxKind) -> bool { kind == UNARY_OPERATOR }
- fn cast(syntax: SyntaxNode) -> Option<Self> {
- if Self::can_cast(syntax.kind()) {
- Some(Self { syntax })
- } else {
- None
- }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl AstNode for ExprSlice {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_SLICE }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_SLICE
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -793,10 +1160,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for SliceDesc {
- fn can_cast(kind: SyntaxKind) -> bool { kind == SLICE_DESC }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == SLICE_DESC
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -804,10 +1175,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for ExprIndex {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_INDEX }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_INDEX
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -815,10 +1190,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for Name {
- fn can_cast(kind: SyntaxKind) -> bool { kind == NAME }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == NAME
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -826,10 +1205,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for ExprIndexExpr {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_INDEX_EXPR }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_INDEX_EXPR
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -837,10 +1220,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for ExprApply {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_APPLY }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_APPLY
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -848,10 +1235,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for ArgsDesc {
- fn can_cast(kind: SyntaxKind) -> bool { kind == ARGS_DESC }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == ARGS_DESC
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -859,10 +1250,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for ExprObjExtend {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_OBJ_EXTEND }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_OBJ_EXTEND
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -870,10 +1265,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for ExprParened {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_PARENED }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_PARENED
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -881,10 +1280,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for ExprLiteral {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_LITERAL }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_LITERAL
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -892,10 +1295,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for Literal {
- fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL }
+impl AstNode for ExprIntrinsicThisFile {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_INTRINSIC_THIS_FILE
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -903,10 +1310,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for ExprIntrinsicThisFile {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_INTRINSIC_THIS_FILE }
+impl AstNode for ExprIntrinsicId {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_INTRINSIC_ID
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -914,10 +1325,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for ExprIntrinsicId {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_INTRINSIC_ID }
+impl AstNode for ExprIntrinsic {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_INTRINSIC
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -925,10 +1340,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for ExprIntrinsic {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_INTRINSIC }
+impl AstNode for ExprString {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_STRING
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -936,10 +1355,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for ExprString {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_STRING }
+impl AstNode for ExprNumber {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_NUMBER
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -947,10 +1370,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for String {
- fn can_cast(kind: SyntaxKind) -> bool { kind == STRING }
+impl AstNode for ExprArray {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_ARRAY
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -958,10 +1385,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for ExprNumber {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_NUMBER }
+impl AstNode for ExprObject {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_OBJECT
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -969,10 +1400,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for Number {
- fn can_cast(kind: SyntaxKind) -> bool { kind == NUMBER }
+impl AstNode for ExprArrayComp {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_ARRAY_COMP
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -980,10 +1415,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for ExprArray {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_ARRAY }
+impl AstNode for ExprImport {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_IMPORT
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -991,10 +1430,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for ExprObject {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_OBJECT }
+impl AstNode for ExprVar {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_VAR
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1002,10 +1445,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for ExprArrayComp {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_ARRAY_COMP }
+impl AstNode for ExprLocal {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_LOCAL
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1013,10 +1460,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for ForSpec {
- fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_SPEC }
+impl AstNode for ExprIfThenElse {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_IF_THEN_ELSE
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1024,10 +1475,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for ExprImport {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_IMPORT }
+impl AstNode for TrueExpr {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == TRUE_EXPR
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1035,10 +1490,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for ExprVar {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_VAR }
+impl AstNode for FalseExpr {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == FALSE_EXPR
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1046,10 +1505,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for ExprLocal {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_LOCAL }
+impl AstNode for ExprFunction {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_FUNCTION
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1057,10 +1520,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for ExprIfThenElse {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_IF_THEN_ELSE }
+impl AstNode for ParamsDesc {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == PARAMS_DESC
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1068,10 +1535,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for ExprFunction {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_FUNCTION }
+impl AstNode for ExprAssert {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_ASSERT
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1079,10 +1550,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for ParamsDesc {
- fn can_cast(kind: SyntaxKind) -> bool { kind == PARAMS_DESC }
+impl AstNode for Assertion {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == ASSERTION
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1090,10 +1565,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for ExprAssert {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_ASSERT }
+impl AstNode for ExprError {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == EXPR_ERROR
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1101,10 +1580,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for Assertion {
- fn can_cast(kind: SyntaxKind) -> bool { kind == ASSERTION }
+impl AstNode for SliceDescEnd {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == SLICE_DESC_END
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1112,10 +1595,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for ExprError {
- fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_ERROR }
+impl AstNode for SliceDescStep {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == SLICE_DESC_STEP
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1123,10 +1610,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for Arg {
- fn can_cast(kind: SyntaxKind) -> bool { kind == ARG }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == ARG
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1134,10 +1625,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for ObjBodyComp {
- fn can_cast(kind: SyntaxKind) -> bool { kind == OBJ_BODY_COMP }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == OBJ_BODY_COMP
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1145,10 +1640,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for ObjLocalPostComma {
- fn can_cast(kind: SyntaxKind) -> bool { kind == OBJ_LOCAL_POST_COMMA }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == OBJ_LOCAL_POST_COMMA
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1156,10 +1655,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for ObjLocalPreComma {
- fn can_cast(kind: SyntaxKind) -> bool { kind == OBJ_LOCAL_PRE_COMMA }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == OBJ_LOCAL_PRE_COMMA
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1167,10 +1670,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for ObjBodyMemberList {
- fn can_cast(kind: SyntaxKind) -> bool { kind == OBJ_BODY_MEMBER_LIST }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == OBJ_BODY_MEMBER_LIST
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1178,10 +1685,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for ObjLocal {
- fn can_cast(kind: SyntaxKind) -> bool { kind == OBJ_LOCAL }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == OBJ_LOCAL
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1189,10 +1700,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for MemberBindStmt {
- fn can_cast(kind: SyntaxKind) -> bool { kind == MEMBER_BIND_STMT }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == MEMBER_BIND_STMT
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1200,10 +1715,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for MemberAssertStmt {
- fn can_cast(kind: SyntaxKind) -> bool { kind == MEMBER_ASSERT_STMT }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == MEMBER_ASSERT_STMT
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1211,10 +1730,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for MemberField {
- fn can_cast(kind: SyntaxKind) -> bool { kind == MEMBER_FIELD }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == MEMBER_FIELD
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1222,10 +1745,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for FieldNormal {
- fn can_cast(kind: SyntaxKind) -> bool { kind == FIELD_NORMAL }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == FIELD_NORMAL
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1233,10 +1760,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for Visibility {
- fn can_cast(kind: SyntaxKind) -> bool { kind == VISIBILITY }
+impl AstNode for FieldMethod {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == FIELD_METHOD
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1244,10 +1775,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for FieldMethod {
- fn can_cast(kind: SyntaxKind) -> bool { kind == FIELD_METHOD }
+impl AstNode for FieldNameFixed {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == FIELD_NAME_FIXED
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1255,10 +1790,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for FieldNameFixed {
- fn can_cast(kind: SyntaxKind) -> bool { kind == FIELD_NAME_FIXED }
+impl AstNode for FieldNameDynamic {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == FIELD_NAME_DYNAMIC
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1266,10 +1805,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for FieldNameDynamic {
- fn can_cast(kind: SyntaxKind) -> bool { kind == FIELD_NAME_DYNAMIC }
+impl AstNode for ForSpec {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == FOR_SPEC
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1277,10 +1820,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for IfSpec {
- fn can_cast(kind: SyntaxKind) -> bool { kind == IF_SPEC }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == IF_SPEC
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1288,10 +1835,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl AstNode for BindDestruct {
- fn can_cast(kind: SyntaxKind) -> bool { kind == BIND_DESTRUCT }
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == BIND_DESTRUCT
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1299,10 +1850,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for Destruct {
- fn can_cast(kind: SyntaxKind) -> bool { kind == DESTRUCT }
+impl AstNode for BindFunction {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == BIND_FUNCTION
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1310,10 +1865,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for BindFunction {
- fn can_cast(kind: SyntaxKind) -> bool { kind == BIND_FUNCTION }
+impl AstNode for Param {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == PARAM
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1321,10 +1880,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for Param {
- fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM }
+impl AstNode for DestructFull {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == DESTRUCT_FULL
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1332,10 +1895,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for DestructFull {
- fn can_cast(kind: SyntaxKind) -> bool { kind == DESTRUCT_FULL }
+impl AstNode for DestructSkip {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == DESTRUCT_SKIP
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1343,10 +1910,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for DestructSkip {
- fn can_cast(kind: SyntaxKind) -> bool { kind == DESTRUCT_SKIP }
+impl AstNode for DestructArray {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == DESTRUCT_ARRAY
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1354,10 +1925,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for DestructArray {
- fn can_cast(kind: SyntaxKind) -> bool { kind == DESTRUCT_ARRAY }
+impl AstNode for DestructObject {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == DESTRUCT_OBJECT
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1365,10 +1940,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for DestructRest {
- fn can_cast(kind: SyntaxKind) -> bool { kind == DESTRUCT_REST }
+impl AstNode for DestructObjectField {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == DESTRUCT_OBJECT_FIELD
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1376,10 +1955,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for DestructObject {
- fn can_cast(kind: SyntaxKind) -> bool { kind == DESTRUCT_OBJECT }
+impl AstNode for DestructRest {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == DESTRUCT_REST
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1387,10 +1970,14 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
-impl AstNode for DestructObjectField {
- fn can_cast(kind: SyntaxKind) -> bool { kind == DESTRUCT_OBJECT_FIELD }
+impl AstNode for DestructArrayElement {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ kind == DESTRUCT_ARRAY_ELEMENT
+ }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
@@ -1398,76 +1985,129 @@
None
}
}
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
+ fn syntax(&self) -> &SyntaxNode {
+ &self.syntax
+ }
}
impl From<ExprBinary> for Expr {
- fn from(node: ExprBinary) -> Expr { Expr::ExprBinary(node) }
+ fn from(node: ExprBinary) -> Expr {
+ Expr::ExprBinary(node)
+ }
}
impl From<ExprUnary> for Expr {
- fn from(node: ExprUnary) -> Expr { Expr::ExprUnary(node) }
+ fn from(node: ExprUnary) -> Expr {
+ Expr::ExprUnary(node)
+ }
}
impl From<ExprSlice> for Expr {
- fn from(node: ExprSlice) -> Expr { Expr::ExprSlice(node) }
+ fn from(node: ExprSlice) -> Expr {
+ Expr::ExprSlice(node)
+ }
}
impl From<ExprIndex> for Expr {
- fn from(node: ExprIndex) -> Expr { Expr::ExprIndex(node) }
+ fn from(node: ExprIndex) -> Expr {
+ Expr::ExprIndex(node)
+ }
}
impl From<ExprIndexExpr> for Expr {
- fn from(node: ExprIndexExpr) -> Expr { Expr::ExprIndexExpr(node) }
+ fn from(node: ExprIndexExpr) -> Expr {
+ Expr::ExprIndexExpr(node)
+ }
}
impl From<ExprApply> for Expr {
- fn from(node: ExprApply) -> Expr { Expr::ExprApply(node) }
+ fn from(node: ExprApply) -> Expr {
+ Expr::ExprApply(node)
+ }
}
impl From<ExprObjExtend> for Expr {
- fn from(node: ExprObjExtend) -> Expr { Expr::ExprObjExtend(node) }
+ fn from(node: ExprObjExtend) -> Expr {
+ Expr::ExprObjExtend(node)
+ }
}
impl From<ExprParened> for Expr {
- fn from(node: ExprParened) -> Expr { Expr::ExprParened(node) }
+ fn from(node: ExprParened) -> Expr {
+ Expr::ExprParened(node)
+ }
}
impl From<ExprIntrinsicThisFile> for Expr {
- fn from(node: ExprIntrinsicThisFile) -> Expr { Expr::ExprIntrinsicThisFile(node) }
+ fn from(node: ExprIntrinsicThisFile) -> Expr {
+ Expr::ExprIntrinsicThisFile(node)
+ }
}
impl From<ExprIntrinsicId> for Expr {
- fn from(node: ExprIntrinsicId) -> Expr { Expr::ExprIntrinsicId(node) }
+ fn from(node: ExprIntrinsicId) -> Expr {
+ Expr::ExprIntrinsicId(node)
+ }
}
impl From<ExprIntrinsic> for Expr {
- fn from(node: ExprIntrinsic) -> Expr { Expr::ExprIntrinsic(node) }
+ fn from(node: ExprIntrinsic) -> Expr {
+ Expr::ExprIntrinsic(node)
+ }
}
impl From<ExprString> for Expr {
- fn from(node: ExprString) -> Expr { Expr::ExprString(node) }
+ fn from(node: ExprString) -> Expr {
+ Expr::ExprString(node)
+ }
}
impl From<ExprNumber> for Expr {
- fn from(node: ExprNumber) -> Expr { Expr::ExprNumber(node) }
+ fn from(node: ExprNumber) -> Expr {
+ Expr::ExprNumber(node)
+ }
}
+impl From<ExprLiteral> for Expr {
+ fn from(node: ExprLiteral) -> Expr {
+ Expr::ExprLiteral(node)
+ }
+}
impl From<ExprArray> for Expr {
- fn from(node: ExprArray) -> Expr { Expr::ExprArray(node) }
+ fn from(node: ExprArray) -> Expr {
+ Expr::ExprArray(node)
+ }
}
impl From<ExprObject> for Expr {
- fn from(node: ExprObject) -> Expr { Expr::ExprObject(node) }
+ fn from(node: ExprObject) -> Expr {
+ Expr::ExprObject(node)
+ }
}
impl From<ExprArrayComp> for Expr {
- fn from(node: ExprArrayComp) -> Expr { Expr::ExprArrayComp(node) }
+ fn from(node: ExprArrayComp) -> Expr {
+ Expr::ExprArrayComp(node)
+ }
}
impl From<ExprImport> for Expr {
- fn from(node: ExprImport) -> Expr { Expr::ExprImport(node) }
+ fn from(node: ExprImport) -> Expr {
+ Expr::ExprImport(node)
+ }
}
impl From<ExprVar> for Expr {
- fn from(node: ExprVar) -> Expr { Expr::ExprVar(node) }
+ fn from(node: ExprVar) -> Expr {
+ Expr::ExprVar(node)
+ }
}
impl From<ExprLocal> for Expr {
- fn from(node: ExprLocal) -> Expr { Expr::ExprLocal(node) }
+ fn from(node: ExprLocal) -> Expr {
+ Expr::ExprLocal(node)
+ }
}
impl From<ExprIfThenElse> for Expr {
- fn from(node: ExprIfThenElse) -> Expr { Expr::ExprIfThenElse(node) }
+ fn from(node: ExprIfThenElse) -> Expr {
+ Expr::ExprIfThenElse(node)
+ }
}
impl From<ExprFunction> for Expr {
- fn from(node: ExprFunction) -> Expr { Expr::ExprFunction(node) }
+ fn from(node: ExprFunction) -> Expr {
+ Expr::ExprFunction(node)
+ }
}
impl From<ExprAssert> for Expr {
- fn from(node: ExprAssert) -> Expr { Expr::ExprAssert(node) }
+ fn from(node: ExprAssert) -> Expr {
+ Expr::ExprAssert(node)
+ }
}
impl From<ExprError> for Expr {
- fn from(node: ExprError) -> Expr { Expr::ExprError(node) }
+ fn from(node: ExprError) -> Expr {
+ Expr::ExprError(node)
+ }
}
impl AstNode for Expr {
fn can_cast(kind: SyntaxKind) -> bool {
@@ -1485,6 +2125,7 @@
| EXPR_INTRINSIC
| EXPR_STRING
| EXPR_NUMBER
+ | EXPR_LITERAL
| EXPR_ARRAY
| EXPR_OBJECT
| EXPR_ARRAY_COMP
@@ -1515,6 +2156,7 @@
EXPR_INTRINSIC => Expr::ExprIntrinsic(ExprIntrinsic { syntax }),
EXPR_STRING => Expr::ExprString(ExprString { syntax }),
EXPR_NUMBER => Expr::ExprNumber(ExprNumber { syntax }),
+ EXPR_LITERAL => Expr::ExprLiteral(ExprLiteral { syntax }),
EXPR_ARRAY => Expr::ExprArray(ExprArray { syntax }),
EXPR_OBJECT => Expr::ExprObject(ExprObject { syntax }),
EXPR_ARRAY_COMP => Expr::ExprArrayComp(ExprArrayComp { syntax }),
@@ -1544,6 +2186,7 @@
Expr::ExprIntrinsic(it) => &it.syntax,
Expr::ExprString(it) => &it.syntax,
Expr::ExprNumber(it) => &it.syntax,
+ Expr::ExprLiteral(it) => &it.syntax,
Expr::ExprArray(it) => &it.syntax,
Expr::ExprObject(it) => &it.syntax,
Expr::ExprArrayComp(it) => &it.syntax,
@@ -1558,10 +2201,14 @@
}
}
impl From<ObjBodyComp> for ObjBody {
- fn from(node: ObjBodyComp) -> ObjBody { ObjBody::ObjBodyComp(node) }
+ fn from(node: ObjBodyComp) -> ObjBody {
+ ObjBody::ObjBodyComp(node)
+ }
}
impl From<ObjBodyMemberList> for ObjBody {
- fn from(node: ObjBodyMemberList) -> ObjBody { ObjBody::ObjBodyMemberList(node) }
+ fn from(node: ObjBodyMemberList) -> ObjBody {
+ ObjBody::ObjBodyMemberList(node)
+ }
}
impl AstNode for ObjBody {
fn can_cast(kind: SyntaxKind) -> bool {
@@ -1586,10 +2233,14 @@
}
}
impl From<ForSpec> for CompSpec {
- fn from(node: ForSpec) -> CompSpec { CompSpec::ForSpec(node) }
+ fn from(node: ForSpec) -> CompSpec {
+ CompSpec::ForSpec(node)
+ }
}
impl From<IfSpec> for CompSpec {
- fn from(node: IfSpec) -> CompSpec { CompSpec::IfSpec(node) }
+ fn from(node: IfSpec) -> CompSpec {
+ CompSpec::IfSpec(node)
+ }
}
impl AstNode for CompSpec {
fn can_cast(kind: SyntaxKind) -> bool {
@@ -1614,10 +2265,14 @@
}
}
impl From<BindDestruct> for Bind {
- fn from(node: BindDestruct) -> Bind { Bind::BindDestruct(node) }
+ fn from(node: BindDestruct) -> Bind {
+ Bind::BindDestruct(node)
+ }
}
impl From<BindFunction> for Bind {
- fn from(node: BindFunction) -> Bind { Bind::BindFunction(node) }
+ fn from(node: BindFunction) -> Bind {
+ Bind::BindFunction(node)
+ }
}
impl AstNode for Bind {
fn can_cast(kind: SyntaxKind) -> bool {
@@ -1642,13 +2297,19 @@
}
}
impl From<MemberBindStmt> for Member {
- fn from(node: MemberBindStmt) -> Member { Member::MemberBindStmt(node) }
+ fn from(node: MemberBindStmt) -> Member {
+ Member::MemberBindStmt(node)
+ }
}
impl From<MemberAssertStmt> for Member {
- fn from(node: MemberAssertStmt) -> Member { Member::MemberAssertStmt(node) }
+ fn from(node: MemberAssertStmt) -> Member {
+ Member::MemberAssertStmt(node)
+ }
}
impl From<MemberField> for Member {
- fn from(node: MemberField) -> Member { Member::MemberField(node) }
+ fn from(node: MemberField) -> Member {
+ Member::MemberField(node)
+ }
}
impl AstNode for Member {
fn can_cast(kind: SyntaxKind) -> bool {
@@ -1675,10 +2336,14 @@
}
}
impl From<FieldNormal> for Field {
- fn from(node: FieldNormal) -> Field { Field::FieldNormal(node) }
+ fn from(node: FieldNormal) -> Field {
+ Field::FieldNormal(node)
+ }
}
impl From<FieldMethod> for Field {
- fn from(node: FieldMethod) -> Field { Field::FieldMethod(node) }
+ fn from(node: FieldMethod) -> Field {
+ Field::FieldMethod(node)
+ }
}
impl AstNode for Field {
fn can_cast(kind: SyntaxKind) -> bool {
@@ -1703,10 +2368,14 @@
}
}
impl From<FieldNameFixed> for FieldName {
- fn from(node: FieldNameFixed) -> FieldName { FieldName::FieldNameFixed(node) }
+ fn from(node: FieldNameFixed) -> FieldName {
+ FieldName::FieldNameFixed(node)
+ }
}
impl From<FieldNameDynamic> for FieldName {
- fn from(node: FieldNameDynamic) -> FieldName { FieldName::FieldNameDynamic(node) }
+ fn from(node: FieldNameDynamic) -> FieldName {
+ FieldName::FieldNameDynamic(node)
+ }
}
impl AstNode for FieldName {
fn can_cast(kind: SyntaxKind) -> bool {
@@ -1730,6 +2399,448 @@
}
}
}
+impl From<DestructFull> for Destruct {
+ fn from(node: DestructFull) -> Destruct {
+ Destruct::DestructFull(node)
+ }
+}
+impl From<DestructSkip> for Destruct {
+ fn from(node: DestructSkip) -> Destruct {
+ Destruct::DestructSkip(node)
+ }
+}
+impl From<DestructArray> for Destruct {
+ fn from(node: DestructArray) -> Destruct {
+ Destruct::DestructArray(node)
+ }
+}
+impl From<DestructObject> for Destruct {
+ fn from(node: DestructObject) -> Destruct {
+ Destruct::DestructObject(node)
+ }
+}
+impl AstNode for Destruct {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ match kind {
+ DESTRUCT_FULL | DESTRUCT_SKIP | DESTRUCT_ARRAY | DESTRUCT_OBJECT => true,
+ _ => false,
+ }
+ }
+ fn cast(syntax: SyntaxNode) -> Option<Self> {
+ let res = match syntax.kind() {
+ DESTRUCT_FULL => Destruct::DestructFull(DestructFull { syntax }),
+ DESTRUCT_SKIP => Destruct::DestructSkip(DestructSkip { syntax }),
+ DESTRUCT_ARRAY => Destruct::DestructArray(DestructArray { syntax }),
+ DESTRUCT_OBJECT => Destruct::DestructObject(DestructObject { syntax }),
+ _ => return None,
+ };
+ Some(res)
+ }
+ fn syntax(&self) -> &SyntaxNode {
+ match self {
+ Destruct::DestructFull(it) => &it.syntax,
+ Destruct::DestructSkip(it) => &it.syntax,
+ Destruct::DestructArray(it) => &it.syntax,
+ Destruct::DestructObject(it) => &it.syntax,
+ }
+ }
+}
+impl From<DestructArrayElement> for DestructArrayPart {
+ fn from(node: DestructArrayElement) -> DestructArrayPart {
+ DestructArrayPart::DestructArrayElement(node)
+ }
+}
+impl From<DestructRest> for DestructArrayPart {
+ fn from(node: DestructRest) -> DestructArrayPart {
+ DestructArrayPart::DestructRest(node)
+ }
+}
+impl AstNode for DestructArrayPart {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ match kind {
+ DESTRUCT_ARRAY_ELEMENT | DESTRUCT_REST => true,
+ _ => false,
+ }
+ }
+ fn cast(syntax: SyntaxNode) -> Option<Self> {
+ let res = match syntax.kind() {
+ DESTRUCT_ARRAY_ELEMENT => {
+ DestructArrayPart::DestructArrayElement(DestructArrayElement { syntax })
+ }
+ DESTRUCT_REST => DestructArrayPart::DestructRest(DestructRest { syntax }),
+ _ => return None,
+ };
+ Some(res)
+ }
+ fn syntax(&self) -> &SyntaxNode {
+ match self {
+ DestructArrayPart::DestructArrayElement(it) => &it.syntax,
+ DestructArrayPart::DestructRest(it) => &it.syntax,
+ }
+ }
+}
+impl AstToken for BinaryOperator {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ match kind {
+ OR | AND | BIT_OR | BIT_XOR | BIT_AND | EQ | NE | LT | GT | LE | GE | IN_KW | LHS
+ | RHS | PLUS | MINUS | MUL | DIV | MODULO | ERROR_NO_OPERATOR => true,
+ _ => false,
+ }
+ }
+ fn cast(syntax: SyntaxToken) -> Option<Self> {
+ let res = match syntax.kind() {
+ OR => BinaryOperator {
+ syntax,
+ kind: BinaryOperatorKind::Or,
+ },
+ AND => BinaryOperator {
+ syntax,
+ kind: BinaryOperatorKind::And,
+ },
+ BIT_OR => BinaryOperator {
+ syntax,
+ kind: BinaryOperatorKind::BitOr,
+ },
+ BIT_XOR => BinaryOperator {
+ syntax,
+ kind: BinaryOperatorKind::BitXor,
+ },
+ BIT_AND => BinaryOperator {
+ syntax,
+ kind: BinaryOperatorKind::BitAnd,
+ },
+ EQ => BinaryOperator {
+ syntax,
+ kind: BinaryOperatorKind::Eq,
+ },
+ NE => BinaryOperator {
+ syntax,
+ kind: BinaryOperatorKind::Ne,
+ },
+ LT => BinaryOperator {
+ syntax,
+ kind: BinaryOperatorKind::Lt,
+ },
+ GT => BinaryOperator {
+ syntax,
+ kind: BinaryOperatorKind::Gt,
+ },
+ LE => BinaryOperator {
+ syntax,
+ kind: BinaryOperatorKind::Le,
+ },
+ GE => BinaryOperator {
+ syntax,
+ kind: BinaryOperatorKind::Ge,
+ },
+ IN_KW => BinaryOperator {
+ syntax,
+ kind: BinaryOperatorKind::InKw,
+ },
+ LHS => BinaryOperator {
+ syntax,
+ kind: BinaryOperatorKind::Lhs,
+ },
+ RHS => BinaryOperator {
+ syntax,
+ kind: BinaryOperatorKind::Rhs,
+ },
+ PLUS => BinaryOperator {
+ syntax,
+ kind: BinaryOperatorKind::Plus,
+ },
+ MINUS => BinaryOperator {
+ syntax,
+ kind: BinaryOperatorKind::Minus,
+ },
+ MUL => BinaryOperator {
+ syntax,
+ kind: BinaryOperatorKind::Mul,
+ },
+ DIV => BinaryOperator {
+ syntax,
+ kind: BinaryOperatorKind::Div,
+ },
+ MODULO => BinaryOperator {
+ syntax,
+ kind: BinaryOperatorKind::Modulo,
+ },
+ ERROR_NO_OPERATOR => BinaryOperator {
+ syntax,
+ kind: BinaryOperatorKind::ErrorNoOperator,
+ },
+ _ => return None,
+ };
+ Some(res)
+ }
+ fn syntax(&self) -> &SyntaxToken {
+ &self.syntax
+ }
+}
+impl BinaryOperator {
+ pub fn kind(&self) -> BinaryOperatorKind {
+ self.kind
+ }
+}
+impl std::fmt::Display for BinaryOperator {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
+impl AstToken for UnaryOperator {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ match kind {
+ MINUS | NOT | BIT_NOT => true,
+ _ => false,
+ }
+ }
+ fn cast(syntax: SyntaxToken) -> Option<Self> {
+ let res = match syntax.kind() {
+ MINUS => UnaryOperator {
+ syntax,
+ kind: UnaryOperatorKind::Minus,
+ },
+ NOT => UnaryOperator {
+ syntax,
+ kind: UnaryOperatorKind::Not,
+ },
+ BIT_NOT => UnaryOperator {
+ syntax,
+ kind: UnaryOperatorKind::BitNot,
+ },
+ _ => return None,
+ };
+ Some(res)
+ }
+ fn syntax(&self) -> &SyntaxToken {
+ &self.syntax
+ }
+}
+impl UnaryOperator {
+ pub fn kind(&self) -> UnaryOperatorKind {
+ self.kind
+ }
+}
+impl std::fmt::Display for UnaryOperator {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
+impl AstToken for Literal {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ match kind {
+ NULL_KW | TRUE_KW | FALSE_KW | SELF_KW | DOLLAR | SUPER_KW => true,
+ _ => false,
+ }
+ }
+ fn cast(syntax: SyntaxToken) -> Option<Self> {
+ let res = match syntax.kind() {
+ NULL_KW => Literal {
+ syntax,
+ kind: LiteralKind::NullKw,
+ },
+ TRUE_KW => Literal {
+ syntax,
+ kind: LiteralKind::TrueKw,
+ },
+ FALSE_KW => Literal {
+ syntax,
+ kind: LiteralKind::FalseKw,
+ },
+ SELF_KW => Literal {
+ syntax,
+ kind: LiteralKind::SelfKw,
+ },
+ DOLLAR => Literal {
+ syntax,
+ kind: LiteralKind::Dollar,
+ },
+ SUPER_KW => Literal {
+ syntax,
+ kind: LiteralKind::SuperKw,
+ },
+ _ => return None,
+ };
+ Some(res)
+ }
+ fn syntax(&self) -> &SyntaxToken {
+ &self.syntax
+ }
+}
+impl Literal {
+ pub fn kind(&self) -> LiteralKind {
+ self.kind
+ }
+}
+impl std::fmt::Display for Literal {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
+impl AstToken for String {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ match kind {
+ STRING_DOUBLE
+ | STRING_SINGLE
+ | STRING_DOUBLE_VERBATIM
+ | STRING_SINGLE_VERBATIM
+ | STRING_BLOCK => true,
+ _ => false,
+ }
+ }
+ fn cast(syntax: SyntaxToken) -> Option<Self> {
+ let res = match syntax.kind() {
+ STRING_DOUBLE => String {
+ syntax,
+ kind: StringKind::StringDouble,
+ },
+ STRING_SINGLE => String {
+ syntax,
+ kind: StringKind::StringSingle,
+ },
+ STRING_DOUBLE_VERBATIM => String {
+ syntax,
+ kind: StringKind::StringDoubleVerbatim,
+ },
+ STRING_SINGLE_VERBATIM => String {
+ syntax,
+ kind: StringKind::StringSingleVerbatim,
+ },
+ STRING_BLOCK => String {
+ syntax,
+ kind: StringKind::StringBlock,
+ },
+ _ => return None,
+ };
+ Some(res)
+ }
+ fn syntax(&self) -> &SyntaxToken {
+ &self.syntax
+ }
+}
+impl String {
+ pub fn kind(&self) -> StringKind {
+ self.kind
+ }
+}
+impl std::fmt::Display for String {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
+impl AstToken for Number {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ match kind {
+ FLOAT | META_FORCE_ENUM => true,
+ _ => false,
+ }
+ }
+ fn cast(syntax: SyntaxToken) -> Option<Self> {
+ let res = match syntax.kind() {
+ FLOAT => Number {
+ syntax,
+ kind: NumberKind::Float,
+ },
+ META_FORCE_ENUM => Number {
+ syntax,
+ kind: NumberKind::MetaForceEnum,
+ },
+ _ => return None,
+ };
+ Some(res)
+ }
+ fn syntax(&self) -> &SyntaxToken {
+ &self.syntax
+ }
+}
+impl Number {
+ pub fn kind(&self) -> NumberKind {
+ self.kind
+ }
+}
+impl std::fmt::Display for Number {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
+impl AstToken for ImportKind {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ match kind {
+ IMPORTSTR_KW | IMPORTBIN_KW | IMPORT_KW => true,
+ _ => false,
+ }
+ }
+ fn cast(syntax: SyntaxToken) -> Option<Self> {
+ let res = match syntax.kind() {
+ IMPORTSTR_KW => ImportKind {
+ syntax,
+ kind: ImportKindKind::ImportstrKw,
+ },
+ IMPORTBIN_KW => ImportKind {
+ syntax,
+ kind: ImportKindKind::ImportbinKw,
+ },
+ IMPORT_KW => ImportKind {
+ syntax,
+ kind: ImportKindKind::ImportKw,
+ },
+ _ => return None,
+ };
+ Some(res)
+ }
+ fn syntax(&self) -> &SyntaxToken {
+ &self.syntax
+ }
+}
+impl ImportKind {
+ pub fn kind(&self) -> ImportKindKind {
+ self.kind
+ }
+}
+impl std::fmt::Display for ImportKind {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
+impl AstToken for Visibility {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ match kind {
+ COLONCOLONCOLON | COLONCOLON | COLON => true,
+ _ => false,
+ }
+ }
+ fn cast(syntax: SyntaxToken) -> Option<Self> {
+ let res = match syntax.kind() {
+ COLONCOLONCOLON => Visibility {
+ syntax,
+ kind: VisibilityKind::Coloncoloncolon,
+ },
+ COLONCOLON => Visibility {
+ syntax,
+ kind: VisibilityKind::Coloncolon,
+ },
+ COLON => Visibility {
+ syntax,
+ kind: VisibilityKind::Colon,
+ },
+ _ => return None,
+ };
+ Some(res)
+ }
+ fn syntax(&self) -> &SyntaxToken {
+ &self.syntax
+ }
+}
+impl Visibility {
+ pub fn kind(&self) -> VisibilityKind {
+ self.kind
+ }
+}
+impl std::fmt::Display for Visibility {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
impl std::fmt::Display for Expr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
@@ -1765,31 +2876,36 @@
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for SourceFile {
+impl std::fmt::Display for Destruct {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for ExprBinary {
+impl std::fmt::Display for DestructArrayPart {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for BinaryOperator {
+impl std::fmt::Display for SourceFile {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for ExprUnary {
+impl std::fmt::Display for ExprBinary {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for UnaryOperator {
+impl std::fmt::Display for LhsExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
+impl std::fmt::Display for ExprUnary {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
impl std::fmt::Display for ExprSlice {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
@@ -1840,11 +2956,6 @@
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for Literal {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- std::fmt::Display::fmt(self.syntax(), f)
- }
-}
impl std::fmt::Display for ExprIntrinsicThisFile {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
@@ -1861,11 +2972,6 @@
}
}
impl std::fmt::Display for ExprString {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- std::fmt::Display::fmt(self.syntax(), f)
- }
-}
-impl std::fmt::Display for String {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
@@ -1875,47 +2981,47 @@
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for Number {
+impl std::fmt::Display for ExprArray {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for ExprArray {
+impl std::fmt::Display for ExprObject {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for ExprObject {
+impl std::fmt::Display for ExprArrayComp {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for ExprArrayComp {
+impl std::fmt::Display for ExprImport {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for ForSpec {
+impl std::fmt::Display for ExprVar {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for ExprImport {
+impl std::fmt::Display for ExprLocal {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for ExprVar {
+impl std::fmt::Display for ExprIfThenElse {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for ExprLocal {
+impl std::fmt::Display for TrueExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for ExprIfThenElse {
+impl std::fmt::Display for FalseExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
@@ -1945,6 +3051,16 @@
std::fmt::Display::fmt(self.syntax(), f)
}
}
+impl std::fmt::Display for SliceDescEnd {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
+impl std::fmt::Display for SliceDescStep {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
impl std::fmt::Display for Arg {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
@@ -1991,11 +3107,6 @@
}
}
impl std::fmt::Display for FieldNormal {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- std::fmt::Display::fmt(self.syntax(), f)
- }
-}
-impl std::fmt::Display for Visibility {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
@@ -2015,17 +3126,17 @@
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for IfSpec {
+impl std::fmt::Display for ForSpec {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for BindDestruct {
+impl std::fmt::Display for IfSpec {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for Destruct {
+impl std::fmt::Display for BindDestruct {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
@@ -2055,17 +3166,22 @@
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for DestructRest {
+impl std::fmt::Display for DestructObject {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
+impl std::fmt::Display for DestructObjectField {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for DestructObject {
+impl std::fmt::Display for DestructRest {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for DestructObjectField {
+impl std::fmt::Display for DestructArrayElement {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
crates/jrsonnet-rowan-parser/src/generated/syntax_kinds.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/generated/syntax_kinds.rs
+++ b/crates/jrsonnet-rowan-parser/src/generated/syntax_kinds.rs
@@ -1,7 +1,13 @@
//! This is a generated file, please do not edit manually. Changes can be
//! made in codegeneration that lives in `xtask` top-level dir.
-#![allow(bad_style, missing_docs, unreachable_pub)]
+#![allow(
+ bad_style,
+ missing_docs,
+ unreachable_pub,
+ clippy::manual_non_exhaustive,
+ clippy::match_like_matches_macro
+)]
use logos::Logos;
#[doc = r" The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT`."]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Logos)]
@@ -89,6 +95,52 @@
INTRINSIC_ID,
#[token("$intrinsic")]
INTRINSIC,
+ #[regex("(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?")]
+ FLOAT,
+ #[regex("(?:0|[1-9][0-9]*)\\.[^0-9]")]
+ ERROR_FLOAT_JUNK_AFTER_POINT,
+ #[regex("(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?[eE][^+\\-0-9]")]
+ ERROR_FLOAT_JUNK_AFTER_EXPONENT,
+ #[regex("(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?[eE][+-][^0-9]")]
+ ERROR_FLOAT_JUNK_AFTER_EXPONENT_SIGN,
+ #[regex("\"(?s:[^\"\\\\]|\\\\.)*\"")]
+ STRING_DOUBLE,
+ #[regex("\"(?s:[^\"\\\\]|\\\\.)*")]
+ ERROR_STRING_DOUBLE_UNTERMINATED,
+ #[regex("'(?s:[^'\\\\]|\\\\.)*'")]
+ STRING_SINGLE,
+ #[regex("'(?s:[^'\\\\]|\\\\.)*")]
+ ERROR_STRING_SINGLE_UNTERMINATED,
+ #[regex("@\"(?:[^\"]|\"\")*\"")]
+ STRING_DOUBLE_VERBATIM,
+ #[regex("@\"(?:[^\"]|\"\")*")]
+ ERROR_STRING_DOUBLE_VERBATIM_UNTERMINATED,
+ #[regex("@'(?:[^']|'')*'")]
+ STRING_SINGLE_VERBATIM,
+ #[regex("@'(?:[^']|'')*")]
+ ERROR_STRING_SINGLE_VERBATIM_UNTERMINATED,
+ #[regex("@[^\"'\\s]\\S+")]
+ ERROR_STRING_VERBATIM_MISSING_QUOTES,
+ #[regex("\\|\\|\\|", crate::string_block::lex_str_block_test)]
+ STRING_BLOCK,
+ ERROR_STRING_BLOCK_UNEXPECTED_END,
+ ERROR_STRING_BLOCK_MISSING_NEW_LINE,
+ ERROR_STRING_BLOCK_MISSING_TERMINATION,
+ ERROR_STRING_BLOCK_MISSING_INDENT,
+ #[regex("[_a-zA-Z][_a-zA-Z0-9]*")]
+ IDENT,
+ #[regex("[ \\t\\n\\r]+")]
+ WHITESPACE,
+ #[regex("//[^\\r\\n]*(\\r\\n|\\n)?")]
+ SINGLE_LINE_SLASH_COMMENT,
+ #[regex("#[^\\r\\n]*(\\r\\n|\\n)?")]
+ SINGLE_LINE_HASH_COMMENT,
+ #[regex("/\\*([^*]|\\*[^/])*\\*/")]
+ MULTI_LINE_COMMENT,
+ #[regex("/\\*/")]
+ ERROR_COMMENT_TOO_SHORT,
+ #[regex("/\\*([^*]|\\*[^/])+")]
+ ERROR_COMMENT_UNTERMINATED,
#[token("tailstrict")]
TAILSTRICT_KW,
#[token("importstr")]
@@ -111,6 +163,7 @@
ERROR_KW,
#[token("in")]
IN_KW,
+ ERROR_NO_OPERATOR,
#[token("null")]
NULL_KW,
#[token("true")]
@@ -121,39 +174,17 @@
SELF_KW,
#[token("super")]
SUPER_KW,
+ META_FORCE_ENUM,
#[token("for")]
FOR_KW,
#[token("assert")]
ASSERT_KW,
- #[regex("(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?")]
- NUMBER,
- #[regex("\"(?s:[^\"\\\\]|\\\\.)*\"")]
- STRING_DOUBLE,
- #[regex("'(?s:[^'\\\\]|\\\\.)*'")]
- STRING_SINGLE,
- #[regex("@\"(?:[^\"]|\"\")*\"")]
- STRING_DOUBLE_VERBATIM,
- #[regex("@'(?:[^']|'')*'")]
- STRING_SINGLE_VERBATIM,
- #[regex("\\|\\|\\|")]
- STRING_BLOCK,
- #[regex("[_a-zA-Z][_a-zA-Z0-9]*")]
- IDENT,
- #[regex("[ \\t\\n\\r]+")]
- WHITESPACE,
- #[regex("//[^\\r\\n]*(\\r\\n|\\n)?")]
- SINGLE_LINE_SLASH_COMMENT,
- #[regex("#[^\\r\\n]*(\\r\\n|\\n)?")]
- SINGLE_LINE_HASH_COMMENT,
- #[regex("/\\*([^*]|\\*[^/])*\\*/")]
- MULTI_LINE_COMMENT,
#[error]
ERROR,
SOURCE_FILE,
EXPR_BINARY,
- BINARY_OPERATOR,
+ LHS_EXPR,
EXPR_UNARY,
- UNARY_OPERATOR,
EXPR_SLICE,
SLICE_DESC,
EXPR_INDEX,
@@ -164,26 +195,27 @@
EXPR_OBJ_EXTEND,
EXPR_PARENED,
EXPR_LITERAL,
- LITERAL,
EXPR_INTRINSIC_THIS_FILE,
EXPR_INTRINSIC_ID,
EXPR_INTRINSIC,
EXPR_STRING,
- STRING,
EXPR_NUMBER,
EXPR_ARRAY,
EXPR_OBJECT,
EXPR_ARRAY_COMP,
- FOR_SPEC,
EXPR_IMPORT,
EXPR_VAR,
EXPR_LOCAL,
EXPR_IF_THEN_ELSE,
+ TRUE_EXPR,
+ FALSE_EXPR,
EXPR_FUNCTION,
PARAMS_DESC,
EXPR_ASSERT,
ASSERTION,
EXPR_ERROR,
+ SLICE_DESC_END,
+ SLICE_DESC_STEP,
ARG,
OBJ_BODY_COMP,
OBJ_LOCAL_POST_COMMA,
@@ -194,21 +226,21 @@
MEMBER_ASSERT_STMT,
MEMBER_FIELD,
FIELD_NORMAL,
- VISIBILITY,
FIELD_METHOD,
FIELD_NAME_FIXED,
FIELD_NAME_DYNAMIC,
+ FOR_SPEC,
IF_SPEC,
BIND_DESTRUCT,
- DESTRUCT,
BIND_FUNCTION,
PARAM,
DESTRUCT_FULL,
DESTRUCT_SKIP,
DESTRUCT_ARRAY,
- DESTRUCT_REST,
DESTRUCT_OBJECT,
DESTRUCT_OBJECT_FIELD,
+ DESTRUCT_REST,
+ DESTRUCT_ARRAY_ELEMENT,
EXPR,
OBJ_BODY,
COMP_SPEC,
@@ -216,6 +248,15 @@
MEMBER,
FIELD,
FIELD_NAME,
+ DESTRUCT,
+ DESTRUCT_ARRAY_PART,
+ BINARY_OPERATOR,
+ UNARY_OPERATOR,
+ LITERAL,
+ STRING,
+ NUMBER,
+ IMPORT_KIND,
+ VISIBILITY,
#[doc(hidden)]
__LAST,
}
@@ -223,76 +264,23 @@
impl SyntaxKind {
pub fn is_keyword(self) -> bool {
match self {
- TAILSTRICT_KW | IMPORTSTR_KW | IMPORTBIN_KW | IMPORT_KW | LOCAL_KW | IF_KW
- | THEN_KW | ELSE_KW | FUNCTION_KW | ERROR_KW | IN_KW | NULL_KW | TRUE_KW | FALSE_KW
- | SELF_KW | SUPER_KW | FOR_KW | ASSERT_KW => true,
- _ => false,
- }
- }
- pub fn is_punct(self) -> bool {
- match self {
OR | AND | BIT_OR | BIT_XOR | BIT_AND | EQ | NE | LT | GT | LE | GE | LHS | RHS
| PLUS | MINUS | MUL | DIV | MODULO | NOT | BIT_NOT | L_BRACK | R_BRACK | L_PAREN
| R_PAREN | L_BRACE | R_BRACE | COLON | COLONCOLON | COLONCOLONCOLON | SEMI | DOT
| DOTDOTDOT | COMMA | DOLLAR | ASSIGN | QUESTION_MARK | INTRINSIC_THIS_FILE
- | INTRINSIC_ID | INTRINSIC => true,
+ | INTRINSIC_ID | INTRINSIC | TAILSTRICT_KW | IMPORTSTR_KW | IMPORTBIN_KW
+ | IMPORT_KW | LOCAL_KW | IF_KW | THEN_KW | ELSE_KW | FUNCTION_KW | ERROR_KW | IN_KW
+ | NULL_KW | TRUE_KW | FALSE_KW | SELF_KW | SUPER_KW | FOR_KW | ASSERT_KW => true,
_ => false,
}
}
- pub fn from_keyword(ident: &str) -> Option<SyntaxKind> {
- let kw = match ident {
- "tailstrict" => TAILSTRICT_KW,
- "importstr" => IMPORTSTR_KW,
- "importbin" => IMPORTBIN_KW,
- "import" => IMPORT_KW,
- "local" => LOCAL_KW,
- "if" => IF_KW,
- "then" => THEN_KW,
- "else" => ELSE_KW,
- "function" => FUNCTION_KW,
- "error" => ERROR_KW,
- "in" => IN_KW,
- "null" => NULL_KW,
- "true" => TRUE_KW,
- "false" => FALSE_KW,
- "self" => SELF_KW,
- "super" => SUPER_KW,
- "for" => FOR_KW,
- "assert" => ASSERT_KW,
- _ => return None,
- };
- Some(kw)
- }
- pub fn from_char(c: char) -> Option<SyntaxKind> {
- let tok = match c {
- '|' => BIT_OR,
- '^' => BIT_XOR,
- '&' => BIT_AND,
- '<' => LT,
- '>' => GT,
- '+' => PLUS,
- '-' => MINUS,
- '*' => MUL,
- '/' => DIV,
- '%' => MODULO,
- '!' => NOT,
- '~' => BIT_NOT,
- '[' => L_BRACK,
- ']' => R_BRACK,
- '(' => L_PAREN,
- ')' => R_PAREN,
- '{' => L_BRACE,
- '}' => R_BRACE,
- ':' => COLON,
- ';' => SEMI,
- '.' => DOT,
- ',' => COMMA,
- '$' => DOLLAR,
- '=' => ASSIGN,
- '?' => QUESTION_MARK,
- _ => return None,
- };
- Some(tok)
+ pub fn is_enum(self) -> bool {
+ match self {
+ EXPR | OBJ_BODY | COMP_SPEC | BIND | MEMBER | FIELD | FIELD_NAME | DESTRUCT
+ | DESTRUCT_ARRAY_PART | BINARY_OPERATOR | UNARY_OPERATOR | LITERAL | STRING
+ | NUMBER | IMPORT_KIND | VISIBILITY => true,
+ _ => false,
+ }
}
pub fn from_raw(r: u16) -> Self {
assert!(r < Self::__LAST as u16);
@@ -303,5 +291,5 @@
}
}
#[macro_export]
-macro_rules ! T { [||] => { $ crate :: SyntaxKind :: OR } ; [&&] => { $ crate :: SyntaxKind :: AND } ; [|] => { $ crate :: SyntaxKind :: BIT_OR } ; [^] => { $ crate :: SyntaxKind :: BIT_XOR } ; [&] => { $ crate :: SyntaxKind :: BIT_AND } ; [==] => { $ crate :: SyntaxKind :: EQ } ; [!=] => { $ crate :: SyntaxKind :: NE } ; [<] => { $ crate :: SyntaxKind :: LT } ; [>] => { $ crate :: SyntaxKind :: GT } ; [<=] => { $ crate :: SyntaxKind :: LE } ; [>=] => { $ crate :: SyntaxKind :: GE } ; [<<] => { $ crate :: SyntaxKind :: LHS } ; [>>] => { $ crate :: SyntaxKind :: RHS } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [*] => { $ crate :: SyntaxKind :: MUL } ; [/] => { $ crate :: SyntaxKind :: DIV } ; [%] => { $ crate :: SyntaxKind :: MODULO } ; [!] => { $ crate :: SyntaxKind :: NOT } ; [~] => { $ crate :: SyntaxKind :: BIT_NOT } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_BRACE } ; ['}'] => { $ crate :: SyntaxKind :: R_BRACE } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLONCOLON } ; [:::] => { $ crate :: SyntaxKind :: COLONCOLONCOLON } ; [;] => { $ crate :: SyntaxKind :: SEMI } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [...] => { $ crate :: SyntaxKind :: DOTDOTDOT } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['$'] => { $ crate :: SyntaxKind :: DOLLAR } ; [=] => { $ crate :: SyntaxKind :: ASSIGN } ; [?] => { $ crate :: SyntaxKind :: QUESTION_MARK } ; ["$intrinsicThisFile"] => { $ crate :: SyntaxKind :: INTRINSIC_THIS_FILE } ; ["$intrinsicId"] => { $ crate :: SyntaxKind :: INTRINSIC_ID } ; ["$intrinsic"] => { $ crate :: SyntaxKind :: INTRINSIC } ; [tailstrict] => { $ crate :: SyntaxKind :: TAILSTRICT_KW } ; [importstr] => { $ crate :: SyntaxKind :: IMPORTSTR_KW } ; [importbin] => { $ crate :: SyntaxKind :: IMPORTBIN_KW } ; [import] => { $ crate :: SyntaxKind :: IMPORT_KW } ; [local] => { $ crate :: SyntaxKind :: LOCAL_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [then] => { $ crate :: SyntaxKind :: THEN_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [function] => { $ crate :: SyntaxKind :: FUNCTION_KW } ; [error] => { $ crate :: SyntaxKind :: ERROR_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [null] => { $ crate :: SyntaxKind :: NULL_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [assert] => { $ crate :: SyntaxKind :: ASSERT_KW } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; }
+macro_rules ! T { [||] => { $ crate :: SyntaxKind :: OR } ; [&&] => { $ crate :: SyntaxKind :: AND } ; [|] => { $ crate :: SyntaxKind :: BIT_OR } ; [^] => { $ crate :: SyntaxKind :: BIT_XOR } ; [&] => { $ crate :: SyntaxKind :: BIT_AND } ; [==] => { $ crate :: SyntaxKind :: EQ } ; [!=] => { $ crate :: SyntaxKind :: NE } ; [<] => { $ crate :: SyntaxKind :: LT } ; [>] => { $ crate :: SyntaxKind :: GT } ; [<=] => { $ crate :: SyntaxKind :: LE } ; [>=] => { $ crate :: SyntaxKind :: GE } ; [<<] => { $ crate :: SyntaxKind :: LHS } ; [>>] => { $ crate :: SyntaxKind :: RHS } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [*] => { $ crate :: SyntaxKind :: MUL } ; [/] => { $ crate :: SyntaxKind :: DIV } ; [%] => { $ crate :: SyntaxKind :: MODULO } ; [!] => { $ crate :: SyntaxKind :: NOT } ; [~] => { $ crate :: SyntaxKind :: BIT_NOT } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_BRACE } ; ['}'] => { $ crate :: SyntaxKind :: R_BRACE } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLONCOLON } ; [:::] => { $ crate :: SyntaxKind :: COLONCOLONCOLON } ; [;] => { $ crate :: SyntaxKind :: SEMI } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [...] => { $ crate :: SyntaxKind :: DOTDOTDOT } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['$'] => { $ crate :: SyntaxKind :: DOLLAR } ; [=] => { $ crate :: SyntaxKind :: ASSIGN } ; [?] => { $ crate :: SyntaxKind :: QUESTION_MARK } ; ["$intrinsicThisFile"] => { $ crate :: SyntaxKind :: INTRINSIC_THIS_FILE } ; ["$intrinsicId"] => { $ crate :: SyntaxKind :: INTRINSIC_ID } ; ["$intrinsic"] => { $ crate :: SyntaxKind :: INTRINSIC } ; [tailstrict] => { $ crate :: SyntaxKind :: TAILSTRICT_KW } ; [importstr] => { $ crate :: SyntaxKind :: IMPORTSTR_KW } ; [importbin] => { $ crate :: SyntaxKind :: IMPORTBIN_KW } ; [import] => { $ crate :: SyntaxKind :: IMPORT_KW } ; [local] => { $ crate :: SyntaxKind :: LOCAL_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [then] => { $ crate :: SyntaxKind :: THEN_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [function] => { $ crate :: SyntaxKind :: FUNCTION_KW } ; [error] => { $ crate :: SyntaxKind :: ERROR_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [null] => { $ crate :: SyntaxKind :: NULL_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [assert] => { $ crate :: SyntaxKind :: ASSERT_KW } }
pub use T;
crates/jrsonnet-rowan-parser/src/generated/tokens.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/generated/tokens.rs
+++ /dev/null
@@ -1,155 +0,0 @@
-//! This is a generated file, please do not edit manually. Changes can be
-//! made in codegeneration that lives in `xtask` top-level dir.
-
-use crate::{
- ast::AstToken,
- SyntaxKind::{self, *},
- SyntaxToken,
-};
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Whitespace {
- pub(crate) syntax: SyntaxToken,
-}
-impl std::fmt::Display for Whitespace {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- std::fmt::Display::fmt(&self.syntax, f)
- }
-}
-impl AstToken for Whitespace {
- fn can_cast(kind: SyntaxKind) -> bool { kind == WHITESPACE }
- fn cast(syntax: SyntaxToken) -> Option<Self> {
- if Self::can_cast(syntax.kind()) {
- Some(Self { syntax })
- } else {
- None
- }
- }
- fn syntax(&self) -> &SyntaxToken { &self.syntax }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Comment {
- pub(crate) syntax: SyntaxToken,
-}
-impl std::fmt::Display for Comment {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- std::fmt::Display::fmt(&self.syntax, f)
- }
-}
-impl AstToken for Comment {
- fn can_cast(kind: SyntaxKind) -> bool { kind == COMMENT }
- fn cast(syntax: SyntaxToken) -> Option<Self> {
- if Self::can_cast(syntax.kind()) {
- Some(Self { syntax })
- } else {
- None
- }
- }
- fn syntax(&self) -> &SyntaxToken { &self.syntax }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct String {
- pub(crate) syntax: SyntaxToken,
-}
-impl std::fmt::Display for String {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- std::fmt::Display::fmt(&self.syntax, f)
- }
-}
-impl AstToken for String {
- fn can_cast(kind: SyntaxKind) -> bool { kind == STRING }
- fn cast(syntax: SyntaxToken) -> Option<Self> {
- if Self::can_cast(syntax.kind()) {
- Some(Self { syntax })
- } else {
- None
- }
- }
- fn syntax(&self) -> &SyntaxToken { &self.syntax }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct StringVerbantim {
- pub(crate) syntax: SyntaxToken,
-}
-impl std::fmt::Display for StringVerbantim {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- std::fmt::Display::fmt(&self.syntax, f)
- }
-}
-impl AstToken for StringVerbantim {
- fn can_cast(kind: SyntaxKind) -> bool { kind == STRING_VERBANTIM }
- fn cast(syntax: SyntaxToken) -> Option<Self> {
- if Self::can_cast(syntax.kind()) {
- Some(Self { syntax })
- } else {
- None
- }
- }
- fn syntax(&self) -> &SyntaxToken { &self.syntax }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct StringBlock {
- pub(crate) syntax: SyntaxToken,
-}
-impl std::fmt::Display for StringBlock {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- std::fmt::Display::fmt(&self.syntax, f)
- }
-}
-impl AstToken for StringBlock {
- fn can_cast(kind: SyntaxKind) -> bool { kind == STRING_BLOCK }
- fn cast(syntax: SyntaxToken) -> Option<Self> {
- if Self::can_cast(syntax.kind()) {
- Some(Self { syntax })
- } else {
- None
- }
- }
- fn syntax(&self) -> &SyntaxToken { &self.syntax }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Number {
- pub(crate) syntax: SyntaxToken,
-}
-impl std::fmt::Display for Number {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- std::fmt::Display::fmt(&self.syntax, f)
- }
-}
-impl AstToken for Number {
- fn can_cast(kind: SyntaxKind) -> bool { kind == NUMBER }
- fn cast(syntax: SyntaxToken) -> Option<Self> {
- if Self::can_cast(syntax.kind()) {
- Some(Self { syntax })
- } else {
- None
- }
- }
- fn syntax(&self) -> &SyntaxToken { &self.syntax }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Ident {
- pub(crate) syntax: SyntaxToken,
-}
-impl std::fmt::Display for Ident {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- std::fmt::Display::fmt(&self.syntax, f)
- }
-}
-impl AstToken for Ident {
- fn can_cast(kind: SyntaxKind) -> bool { kind == IDENT }
- fn cast(syntax: SyntaxToken) -> Option<Self> {
- if Self::can_cast(syntax.kind()) {
- Some(Self { syntax })
- } else {
- None
- }
- }
- fn syntax(&self) -> &SyntaxToken { &self.syntax }
-}
crates/jrsonnet-rowan-parser/src/lex.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/lex.rs
+++ b/crates/jrsonnet-rowan-parser/src/lex.rs
@@ -6,40 +6,6 @@
use crate::SyntaxKind;
-impl SyntaxKind {
- pub fn is_trivia(self) -> bool {
- matches!(
- self,
- Self::WHITESPACE
- | Self::MULTI_LINE_COMMENT
- | Self::SINGLE_LINE_HASH_COMMENT
- | Self::SINGLE_LINE_SLASH_COMMENT
- )
- }
- pub fn is_string(self) -> bool {
- matches!(
- self,
- Self::STRING_SINGLE
- | Self::STRING_DOUBLE
- | Self::STRING_SINGLE_VERBATIM
- | Self::STRING_DOUBLE_VERBATIM
- | Self::STRING_BLOCK
- )
- }
- pub fn is_number(self) -> bool {
- matches!(self, Self::NUMBER)
- }
- pub fn is_literal(self) -> bool {
- matches!(
- self,
- Self::NULL_KW
- | Self::TRUE_KW | Self::FALSE_KW
- | Self::SELF_KW | Self::DOLLAR
- | Self::SUPER_KW
- )
- }
-}
-
pub struct Lexer<'a> {
inner: logos::Lexer<'a, SyntaxKind>,
}
@@ -74,7 +40,7 @@
}
}
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
pub struct Lexeme<'i> {
pub kind: SyntaxKind,
pub text: &'i str,
crates/jrsonnet-rowan-parser/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/lib.rs
+++ b/crates/jrsonnet-rowan-parser/src/lib.rs
@@ -2,6 +2,7 @@
mod ast;
mod binary;
+mod classify;
mod event;
mod generated;
mod language;
@@ -13,8 +14,27 @@
mod token_set;
mod unary;
-pub use generated::syntax_kinds::SyntaxKind;
+pub use ast::{AstChildren, AstNode, AstToken};
+use event::Sink;
+use generated::nodes::SourceFile;
+pub use generated::{nodes, syntax_kinds::SyntaxKind};
pub use language::{
JsonnetLanguage, PreorderWithTokens, SyntaxElement, SyntaxElementChildren, SyntaxNode,
SyntaxNodeChildren, SyntaxToken,
};
+use lex::lex;
+use parser::{Parser, SyntaxError};
+pub fn parse(input: &str) -> (SourceFile, Vec<SyntaxError>) {
+ let lexemes = lex(input);
+ let parser = Parser::new(&lexemes);
+ let events = parser.parse();
+ let sink = Sink::new(events, &lexemes);
+
+ let parse = sink.finish();
+ (
+ SourceFile {
+ syntax: parse.syntax(),
+ },
+ parse.errors,
+ )
+}
crates/jrsonnet-rowan-parser/src/marker.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/marker.rs
+++ b/crates/jrsonnet-rowan-parser/src/marker.rs
@@ -7,7 +7,7 @@
pub pos: usize,
}
impl Ranger {
- pub fn finish(mut self, p: &Parser) -> FinishedRanger {
+ pub fn finish(self, p: &Parser) -> FinishedRanger {
FinishedRanger {
start_token: self.pos,
end_token: self.pos.max(p.offset.saturating_sub(1)),
@@ -20,6 +20,7 @@
pub end_token: usize,
}
impl FinishedRanger {
+ #[allow(dead_code)]
pub fn had_error_since(&self, p: &Parser) -> bool {
p.last_error_token >= self.start_token
}
@@ -28,76 +29,94 @@
#[must_use]
pub struct Marker {
pub start_event_idx: usize,
- pub token: usize,
bomb: DropBomb,
}
impl Marker {
- pub fn new(pos: usize, token: usize) -> Self {
+ pub fn new(pos: usize) -> Self {
Self {
start_event_idx: pos,
- token,
bomb: DropBomb::new("marked dropped while not completed"),
}
}
pub fn complete(mut self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker {
self.bomb.defuse();
+ assert!(
+ !kind.is_enum(),
+ "{kind:?} is a enum kind, you should use variant kinds instead"
+ );
+ // TODO: is_parser should return true if enum variant has #[regex]/#[token] over it
+ // debug_assert!(
+ // !kind.is_parser(),
+ // "{kind:?} should be only emitted by parser, not used directly"
+ // );
let event_at_pos = &mut p.events[self.start_event_idx];
- assert_eq!(*event_at_pos, Event::Placeholder);
+ assert_eq!(*event_at_pos, Event::Pending);
*event_at_pos = Event::Start {
kind,
forward_parent: None,
};
- p.events.push(Event::Finish);
+ let finish_event_idx = p.events.len();
+ p.events.push(Event::Finish { wrapper: None });
p.entered -= 1;
p.clear_outdated_hints();
CompletedMarker {
start_event_idx: self.start_event_idx,
- start_token: self.token,
- end_token: self.token.max(p.offset.saturating_sub(1)),
+ finish_event_idx,
}
}
+ pub fn forget(mut self, p: &mut Parser) {
+ self.bomb.defuse();
+ let event_at_pos = &mut p.events[self.start_event_idx];
+ assert_eq!(*event_at_pos, Event::Pending);
+
+ *event_at_pos = Event::Noop;
+ p.entered -= 1;
+ p.clear_outdated_hints();
+ }
}
pub struct CompletedMarker {
start_event_idx: usize,
- pub start_token: usize,
- pub end_token: usize,
+ finish_event_idx: usize,
}
impl CompletedMarker {
pub(super) fn precede(self, p: &mut Parser) -> Marker {
- let mut new_m = p.start();
- new_m.token = self.start_token;
-
- if let Event::Start {
- ref mut forward_parent,
- ..
- } = p.events[self.start_event_idx]
- {
- *forward_parent = Some(new_m.start_event_idx - self.start_event_idx);
- } else {
- unreachable!();
+ let new_m = p.start();
+ match &mut p.events[self.start_event_idx] {
+ Event::Start { forward_parent, .. } => {
+ *forward_parent = Some(new_m.start_event_idx - self.start_event_idx);
+ }
+ _ => unreachable!(),
}
new_m
}
+ /// Create new node around existing marker, not counting anything that comes after it
+ pub fn wrap(self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker {
+ let new_m = p.start();
+ match &mut p.events[self.start_event_idx] {
+ Event::Start { forward_parent, .. } => {
+ *forward_parent = Some(new_m.start_event_idx - self.start_event_idx);
+ }
+ _ => unreachable!(),
+ }
+
+ let completed = new_m.complete(p, kind);
+
+ match &mut p.events[self.finish_event_idx] {
+ Event::Finish { wrapper } => {
+ *wrapper = Some(completed.finish_event_idx - self.finish_event_idx);
+ }
+ _ => unreachable!(),
+ }
+ completed
+ }
}
pub trait AsRange {
fn as_range(&self, p: &Parser) -> TextRange;
fn end_token(&self) -> usize;
-}
-
-impl AsRange for CompletedMarker {
- fn as_range(&self, p: &Parser) -> TextRange {
- TextRange::new(
- p.start_of_token(self.start_token),
- p.end_of_token(self.end_token),
- )
- }
- fn end_token(&self) -> usize {
- self.end_token
- }
}
impl AsRange for FinishedRanger {
crates/jrsonnet-rowan-parser/src/parser.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/parser.rs
+++ b/crates/jrsonnet-rowan-parser/src/parser.rs
@@ -5,9 +5,10 @@
use crate::{
binary::BinaryOperator,
- event::{Event, Sink},
- lex::{lex, Lexeme},
+ event::Event,
+ lex::Lexeme,
marker::{AsRange, CompletedMarker, Marker, Ranger},
+ string_block::{lex_str_block, StringBlockError},
token_set::SyntaxKindSet,
unary::UnaryOperator,
SyntaxKind,
@@ -43,9 +44,10 @@
pub last_error_token: usize,
expected_syntax: Option<ExpectedSyntax>,
expected_syntax_tracking_state: Rc<Cell<ExpectedSyntaxTrackingState>>,
+ steps: Cell<u64>,
}
-const DEFAULT_RECOVERY_SET: SyntaxKindSet = TS![; ')' ']' '}' local];
+const DEFAULT_RECOVERY_SET: SyntaxKindSet = TS![];
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum SyntaxError {
@@ -68,9 +70,9 @@
},
}
-impl Into<LabeledSpan> for SyntaxError {
- fn into(self) -> LabeledSpan {
- match self {
+impl From<SyntaxError> for LabeledSpan {
+ fn from(val: SyntaxError) -> Self {
+ match val {
SyntaxError::Unexpected {
expected,
found,
@@ -91,7 +93,7 @@
),
SyntaxError::Custom { error, range } | SyntaxError::Hint { error, range } => {
LabeledSpan::new_with_span(
- Some(format!("{}", error)),
+ Some(error),
SourceSpan::new(
SourceOffset::from(usize::from(range.start())),
SourceOffset::from(usize::from(range.end() - range.start())),
@@ -103,7 +105,7 @@
}
impl<'i> Parser<'i> {
- fn new(lexemes: &'i [Lexeme<'i>]) -> Self {
+ pub fn new(lexemes: &'i [Lexeme<'i>]) -> Self {
Self {
lexemes,
offset: 0,
@@ -115,6 +117,7 @@
expected_syntax_tracking_state: Rc::new(Cell::new(
ExpectedSyntaxTrackingState::Unnamed,
)),
+ steps: Cell::new(0),
}
}
pub fn clear_outdated_hints(&mut self) {
@@ -132,27 +135,21 @@
.set(ExpectedSyntaxTrackingState::Unnamed);
}
pub fn start(&mut self) -> Marker {
+ self.skip_trivia();
let start_event_idx = self.events.len();
- self.events.push(Event::Placeholder);
+ self.events.push(Event::Pending);
self.entered += 1;
- Marker::new(start_event_idx, self.offset)
+ Marker::new(start_event_idx)
}
pub fn start_ranger(&mut self) -> Ranger {
+ self.skip_trivia();
let pos = self.offset;
Ranger { pos }
}
- fn parse(mut self) -> Vec<Event> {
+ pub fn parse(mut self) -> Vec<Event> {
let m = self.start();
expr(&mut self);
- if !self.at_end() {
- let ranger = self.start_ranger();
-
- while self.peek().is_some() {
- self.bump()
- }
- let end = ranger.finish(&self);
- self.custom_error(end, "unexpected input after expression");
- }
+ self.expect(EOF);
m.complete(&mut self, SOURCE_FILE);
self.events
@@ -168,7 +165,9 @@
recovery_set: SyntaxKindSet,
) {
if self.at(kind) {
- self.bump();
+ if kind != EOF {
+ self.bump();
+ }
} else {
self.error_with_recovery_set(recovery_set);
}
@@ -180,9 +179,6 @@
} else {
self.error_with_no_skip();
}
- }
- pub(crate) fn last_token_range(&self) -> Option<TextRange> {
- self.lexemes.last().map(|Lexeme { range, .. }| *range)
}
fn current_token(&self) -> Lexeme<'i> {
self.lexemes[self.offset]
@@ -236,15 +232,19 @@
&mut self,
recovery_set: SyntaxKindSet,
) -> Option<CompletedMarker> {
- let expected_syntax = self.expected_syntax.take().unwrap();
+ let expected_syntax = self
+ .expected_syntax
+ .take()
+ .unwrap_or(ExpectedSyntax::Named("unknown"));
self.expected_syntax_tracking_state
.set(ExpectedSyntaxTrackingState::Unnamed);
- if self.at_end() || self.at_set(recovery_set) {
+ self.skip_trivia();
+ if self.at_end() || self.at_ts(recovery_set) {
let range = self
.previous_token()
.map(|t| t.range)
- .unwrap_or(TextRange::at(TextSize::from(0), TextSize::from(0)));
+ .unwrap_or_else(|| TextRange::at(TextSize::from(0), TextSize::from(0)));
self.events.push(Event::Error(SyntaxError::Missing {
expected: expected_syntax,
@@ -256,7 +256,7 @@
let current_token = self.current_token();
self.events.push(Event::Error(SyntaxError::Unexpected {
- expected: expected_syntax.clone(),
+ expected: expected_syntax,
found: current_token.kind,
range: current_token.range,
}));
@@ -270,30 +270,85 @@
fn bump(&mut self) {
self.skip_trivia();
+ self.bump_remap(self.current());
+ }
+ fn bump_remap(&mut self, kind: SyntaxKind) {
+ self.skip_trivia();
assert_ne!(self.offset, self.lexemes.len(), "already at end");
- self.events.push(Event::Token);
+ self.events.push(Event::Token { kind });
self.offset += 1;
self.clear_expected_syntaxes();
}
- fn peek(&mut self) -> Option<SyntaxKind> {
- self.skip_trivia();
- self.peek_raw()
+ fn step(&self) {
+ use std::fmt::Write;
+ let steps = self.steps.get();
+ if steps >= 15000000 {
+ let mut out = "seems like parsing is stuck".to_owned();
+ {
+ let last = 20;
+ write!(out, "\n\nLast {} events:", last).unwrap();
+ for (i, event) in self
+ .events
+ .iter()
+ .skip(self.events.len().saturating_sub(last))
+ .enumerate()
+ {
+ write!(out, "\n{i}. {event:?}").unwrap();
+ }
+ }
+ {
+ let next = 20;
+ write!(out, "\n\nNext {next} tokens:").unwrap();
+ for (i, tok) in self.lexemes.iter().skip(self.offset).take(next).enumerate() {
+ write!(out, "\n{i}. {tok:?}").unwrap();
+ }
+ }
+ panic!("{out}")
+ }
+ self.steps.set(steps + 1);
+ }
+ fn nth(&self, i: usize) -> SyntaxKind {
+ self.step();
+ let mut offset = self.offset;
+ for _ in 0..i {
+ while self
+ .lexemes
+ .get(offset)
+ .map(|l| l.kind.is_trivia())
+ .unwrap_or(false)
+ {
+ offset += 1;
+ }
+ offset += 1;
+ }
+ while self
+ .lexemes
+ .get(offset)
+ .map(|l| l.kind.is_trivia())
+ .unwrap_or(false)
+ {
+ offset += 1;
+ }
+ self.lexemes.get(offset).map(|l| l.kind).unwrap_or(EOF)
}
- pub fn peek_token(&mut self) -> Option<&Lexeme<'i>> {
- self.skip_trivia();
- self.peek_token_raw()
+ fn current(&self) -> SyntaxKind {
+ self.nth(0)
}
fn skip_trivia(&mut self) {
- while self.peek_raw().map(|c| c.is_trivia()).unwrap_or(false) {
+ while self.peek_raw().is_trivia() {
self.offset += 1;
}
- }
- fn peek_raw(&mut self) -> Option<SyntaxKind> {
- self.lexemes.get(self.offset).map(|l| l.kind)
}
- fn peek_token_raw(&mut self) -> Option<&Lexeme<'i>> {
+ fn current_lexeme(&mut self) -> Option<&Lexeme> {
+ self.skip_trivia();
self.lexemes.get(self.offset)
}
+ fn peek_raw(&mut self) -> SyntaxKind {
+ self.lexemes
+ .get(self.offset)
+ .map(|l| l.kind)
+ .unwrap_or(SyntaxKind::EOF)
+ }
#[must_use]
pub(crate) fn expected_syntax_name(&mut self, name: &'static str) -> ExpectedSyntaxGuard {
self.expected_syntax_tracking_state
@@ -303,16 +358,19 @@
ExpectedSyntaxGuard::new(Rc::clone(&self.expected_syntax_tracking_state))
}
pub fn at(&mut self, kind: SyntaxKind) -> bool {
+ self.nth_at(0, kind)
+ }
+ pub fn nth_at(&mut self, n: usize, kind: SyntaxKind) -> bool {
if let ExpectedSyntaxTrackingState::Unnamed = self.expected_syntax_tracking_state.get() {
self.expected_syntax = Some(ExpectedSyntax::Unnamed(kind));
}
- self.peek() == Some(kind)
+ self.nth(n) == kind
}
- pub fn at_set(&mut self, set: SyntaxKindSet) -> bool {
- self.peek().map_or(false, |k| set.contains(k))
+ pub fn at_ts(&mut self, set: SyntaxKindSet) -> bool {
+ set.contains(self.current())
}
pub fn at_end(&mut self) -> bool {
- self.peek().is_none()
+ self.at(EOF)
}
}
pub(crate) struct ExpectedSyntaxGuard {
@@ -352,8 +410,8 @@
}}
}
-fn expr(p: &mut Parser) {
- expr_binding_power(p, 0);
+fn expr(p: &mut Parser) -> Option<CompletedMarker> {
+ expr_binding_power(p, 0)
}
fn expr_binding_power(p: &mut Parser, minimum_binding_power: u8) -> Option<CompletedMarker> {
let mut lhs = lhs(p)?;
@@ -392,7 +450,7 @@
p.bump();
}
- let m = lhs.precede(p);
+ let m = lhs.wrap(p, LHS_EXPR).precede(p);
let parsed_rhs = expr_binding_power(p, right_binding_power).is_some();
lhs = m.complete(
p,
@@ -414,11 +472,11 @@
if p.at(T![for]) {
let m = p.start();
p.bump();
- p.expect(IDENT);
+ name(p);
p.expect(T![in]);
expr(p);
m.complete(p, FOR_SPEC);
- } else if p.at(T![in]) {
+ } else if p.at(T![if]) {
let m = p.start();
p.bump();
expr(p);
@@ -439,7 +497,7 @@
if p.at(T![,]) {
p.bump();
true
- } else if p.at_set(set) {
+ } else if p.at_ts(set) {
p.expect_with_no_skip(T![,]);
p.bump();
true
@@ -449,18 +507,76 @@
}
fn field_name(p: &mut Parser) {
let _e = p.expected_syntax_name("field name");
+ let m = p.start();
if p.at(T!['[']) {
p.bump();
expr(p);
p.expect(T![']']);
+ m.complete(p, FIELD_NAME_DYNAMIC);
} else if p.at(IDENT) {
+ name(p);
+ m.complete(p, FIELD_NAME_FIXED);
+ } else if p.current().is_string() {
+ string(p);
+ m.complete(p, FIELD_NAME_FIXED);
+ } else {
+ p.error_with_recovery_set(TS![;]);
+ }
+}
+fn visibility(p: &mut Parser) {
+ if p.at_ts(TS![: :: :::]) {
p.bump()
} else {
- p.error_with_recovery_set(TS![;]);
+ p.error_with_recovery_set(TS![]);
}
}
+fn field(p: &mut Parser) {
+ let m = p.start();
+ field_name(p);
+ let plus = if p.at(T![+]) {
+ let r = p.start_ranger();
+ p.bump();
+ Some(r.finish(p))
+ } else {
+ None
+ };
+ let params = if p.at(T!['(']) {
+ if let Some(plus) = plus {
+ p.custom_error(plus, "can't extend with method");
+ }
+ params_desc(p);
+ if p.at(T![+]) {
+ let r = p.start_ranger();
+ p.bump();
+ p.custom_error(r.finish(p), "can't extend with method");
+ }
+ true
+ } else {
+ false
+ };
+ visibility(p);
+ expr(p);
+
+ if params {
+ m.complete(p, FIELD_METHOD)
+ } else {
+ m.complete(p, FIELD_NORMAL)
+ };
+}
+fn assertion(p: &mut Parser) {
+ assert!(p.at(T![assert]));
+ let m = p.start();
+ p.bump();
+ expr(p).map(|c| c.wrap(p, LHS_EXPR));
+ if p.at(T![:]) {
+ p.bump();
+ expr(p);
+ }
+ m.complete(p, ASSERTION);
+}
fn object(p: &mut Parser) -> CompletedMarker {
assert!(p.at(T!['{']));
+ let m_t = p.start();
let m = p.start();
p.bump();
@@ -470,13 +586,19 @@
break;
}
let m = p.start();
- field_name(p);
- p.expect(T![,]);
- expr(p);
- while p.at(T![for]) || p.at(T![if]) {
- compspec(p)
- }
- m.complete(p, MEMBER);
+ if p.at(T![local]) {
+ obj_local(p);
+ m.complete(p, MEMBER_BIND_STMT)
+ } else if p.at(T![assert]) {
+ assertion(p);
+ m.complete(p, MEMBER_ASSERT_STMT)
+ } else {
+ field(p);
+ while p.at(T![for]) || p.at(T![if]) {
+ compspec(p)
+ }
+ m.complete(p, MEMBER_FIELD)
+ };
if comma_with_alternatives(p, SyntaxKindSet::new(&[T![=]])) {
continue;
}
@@ -484,10 +606,19 @@
break;
}
- m.complete(p, OBJ_BODY)
+ m.complete(p, OBJ_BODY_MEMBER_LIST);
+ m_t.complete(p, EXPR_OBJECT)
+}
+fn param(p: &mut Parser) {
+ let m = p.start();
+ destruct(p);
+ if p.at(T![=]) {
+ p.bump();
+ expr(p);
+ }
+ m.complete(p, PARAM);
}
-
-fn params(p: &mut Parser) -> CompletedMarker {
+fn params_desc(p: &mut Parser) -> CompletedMarker {
assert!(p.at(T!['(']));
let m = p.start();
p.bump();
@@ -496,14 +627,8 @@
if p.at(T![')']) {
p.bump();
break;
- }
- let m = p.start();
- p.expect(IDENT);
- if p.at(T![=]) {
- p.bump();
- expr(p);
}
- m.complete(p, PARAM);
+ param(p);
if comma(p) {
continue;
}
@@ -513,48 +638,39 @@
m.complete(p, PARAMS_DESC)
}
-fn args(p: &mut Parser) {
+fn args_desc(p: &mut Parser) {
+ let m = p.start();
assert!(p.at(T!['(']));
p.bump();
- let mut error_positional_start = None::<Marker>;
- let mut started_named = Cell::new(false);
- let mut on_positional = |p: &mut Parser, m: Marker| {
- let c = m.complete(p, ARG);
- if started_named.get() && error_positional_start.is_none() {
- error_positional_start = Some(c.precede(p));
- }
- };
+ let started_named = Cell::new(false);
+
loop {
if p.at(T![')']) {
break;
}
let m = p.start();
- if p.at(IDENT) {
+ if p.at(IDENT) && p.nth_at(1, T![=]) {
+ name(p);
p.bump();
- if p.at(T![=]) {
- p.bump();
- expr(p);
- m.complete(p, ARG);
- started_named.set(true);
- } else {
- on_positional(p, m);
- }
+ expr(p);
+ m.complete(p, ARG);
+ started_named.set(true);
} else {
expr(p);
- on_positional(p, m);
+ m.complete(p, ARG);
}
if comma(p) {
continue;
}
break;
}
- if let Some(error_positional_start) = error_positional_start {
- let c = error_positional_start.complete(p, ERROR);
- p.custom_error(c, "positional arguments can't be placed after named")
+ p.expect(T![')']);
+ if p.at(T![tailstrict]) {
+ p.bump()
}
- p.expect(T![')']);
+ m.complete(p, ARGS_DESC);
}
fn array(p: &mut Parser) -> CompletedMarker {
@@ -605,7 +721,45 @@
m.complete(p, EXPR_ARRAY)
}
}
-
+/// Returns true if it was slice, false if just index
+#[must_use]
+fn slice_desc_or_index(p: &mut Parser) -> bool {
+ let m = p.start();
+ p.bump();
+ // TODO: do not treat :, ::, ::: as full tokens?
+ // Start
+ if !p.at(T![:]) && !p.at(T![::]) {
+ expr(p);
+ }
+ if p.at(T![:]) {
+ p.bump();
+ // End
+ if !p.at(T![']']) {
+ expr(p).map(|c| c.wrap(p, SLICE_DESC_END));
+ }
+ if p.at(T![:]) {
+ p.bump();
+ // Step
+ if !p.at(T![']']) {
+ expr(p).map(|c| c.wrap(p, SLICE_DESC_STEP));
+ }
+ }
+ } else if p.at(T![::]) {
+ p.bump();
+ // End
+ if !p.at(T![']']) {
+ expr(p).map(|c| c.wrap(p, SLICE_DESC_END));
+ }
+ } else {
+ // It was not a slice
+ p.expect(T![']']);
+ m.forget(p);
+ return false;
+ }
+ p.expect(T![']']);
+ m.complete(p, SLICE_DESC);
+ true
+}
fn lhs(p: &mut Parser) -> Option<CompletedMarker> {
let mut lhs = lhs_basic(p)?;
@@ -613,34 +767,20 @@
if p.at(T![.]) {
let m = lhs.precede(p);
p.bump();
- p.expect(IDENT);
+ name(p);
lhs = m.complete(p, EXPR_INDEX);
} else if p.at(T!['[']) {
- let m = lhs.precede(p);
- p.bump();
- // Start
- if !p.at(T![:]) {
- expr(p);
- }
- if p.at(T![:]) {
- p.bump();
- // End
- if !p.at(T![']']) && !p.at(T![:]) {
- expr(p);
- }
- if p.at(T![:]) {
- p.bump();
- // Step
- if !p.at(T![']']) {
- expr(p);
- }
- }
+ if slice_desc_or_index(p) {
+ lhs = lhs.precede(p).complete(p, EXPR_SLICE);
+ } else {
+ lhs = lhs
+ .wrap(p, LHS_EXPR)
+ .precede(p)
+ .complete(p, EXPR_INDEX_EXPR);
}
- p.expect(T![']']);
- lhs = m.complete(p, EXPR_SLICE);
} else if p.at(T!['(']) {
let m = lhs.precede(p);
- args(p);
+ args_desc(p);
lhs = m.complete(p, EXPR_APPLY);
} else {
break;
@@ -649,25 +789,199 @@
Some(lhs)
}
-
+fn name(p: &mut Parser) {
+ let m = p.start();
+ p.expect(IDENT);
+ m.complete(p, NAME);
+}
+fn destruct_rest(p: &mut Parser) {
+ assert!(p.at(T![...]));
+ p.bump();
+ let m = p.start();
+ if p.at(IDENT) {
+ p.bump()
+ }
+ m.complete(p, DESTRUCT_REST);
+}
+fn destruct_object_field(p: &mut Parser) {
+ let m = p.start();
+ name(p);
+ if p.at(T![:]) {
+ p.bump();
+ destruct(p);
+ };
+ if p.at(T![=]) {
+ p.bump();
+ expr(p);
+ }
+ m.complete(p, DESTRUCT_OBJECT_FIELD);
+}
+fn obj_local(p: &mut Parser) {
+ assert!(p.at(T![local]));
+ let m = p.start();
+ p.bump();
+ bind(p);
+ m.complete(p, OBJ_LOCAL);
+}
+fn destruct(p: &mut Parser) -> CompletedMarker {
+ let m = p.start();
+ if p.at(T![?]) {
+ p.bump();
+ m.complete(p, DESTRUCT_SKIP)
+ } else if p.at(T!['[']) {
+ p.bump();
+ let mut had_rest = false;
+ loop {
+ if p.at(T![']']) {
+ p.bump();
+ break;
+ } else if p.at(T![...]) {
+ let m_err = p.start_ranger();
+ destruct_rest(p);
+ if had_rest {
+ p.custom_error(m_err.finish(p), "only one rest can be present in array");
+ }
+ had_rest = true;
+ } else {
+ destruct(p);
+ }
+ if p.at(T![,]) {
+ p.bump();
+ continue;
+ }
+ p.expect(T![']']);
+ break;
+ }
+ m.complete(p, DESTRUCT_ARRAY)
+ } else if p.at(T!['{']) {
+ p.bump();
+ let mut had_rest = false;
+ loop {
+ if p.at(T!['}']) {
+ p.bump();
+ break;
+ } else if p.at(T![...]) {
+ let m_err = p.start_ranger();
+ destruct_rest(p);
+ if had_rest {
+ p.custom_error(m_err.finish(p), "only one rest can be present in object");
+ }
+ had_rest = true;
+ } else {
+ if had_rest {
+ p.error_with_recovery_set(TS![]);
+ }
+ destruct_object_field(p);
+ }
+ if p.at(T![,]) {
+ p.bump();
+ continue;
+ }
+ p.expect(T!['}']);
+ break;
+ }
+ m.complete(p, DESTRUCT_OBJECT)
+ } else if p.at(IDENT) {
+ name(p);
+ m.complete(p, DESTRUCT_FULL)
+ } else {
+ m.complete(p, ERROR)
+ }
+}
+fn bind(p: &mut Parser) {
+ let m = p.start();
+ if p.at(IDENT) && p.nth_at(1, T!['(']) {
+ name(p);
+ params_desc(p);
+ p.expect(T![=]);
+ expr(p);
+ m.complete(p, BIND_FUNCTION)
+ } else {
+ destruct(p);
+ p.expect(T![=]);
+ expr(p);
+ m.complete(p, BIND_DESTRUCT)
+ };
+}
+fn string(p: &mut Parser) {
+ assert!(p.current().is_string());
+ if p.at(STRING_BLOCK) {
+ // We use custom lexer, which skips enough bytes, but not returns error
+ // Instead we should call lexer again to verify if there is something wrong with string block
+ let mut lexer = logos::Lexer::<SyntaxKind>::new(dbg!(
+ &p.current_lexeme().expect("parser is at string block").text
+ ));
+ // In kinds, string blocks is parsed at least as `|||`
+ lexer.bump(3);
+ let res = lex_str_block(&mut lexer);
+ debug_assert!(lexer.next().is_none(), "str_block is lexed");
+ match res {
+ Ok(_) => {
+ p.bump();
+ }
+ Err(e) => p.bump_remap(match e {
+ StringBlockError::UnexpectedEnd => ERROR_STRING_BLOCK_UNEXPECTED_END,
+ StringBlockError::MissingNewLine => ERROR_STRING_BLOCK_MISSING_NEW_LINE,
+ StringBlockError::MissingTermination => ERROR_STRING_BLOCK_MISSING_TERMINATION,
+ StringBlockError::MissingIndent => ERROR_STRING_BLOCK_MISSING_INDENT,
+ }),
+ }
+ } else {
+ p.bump();
+ }
+}
+fn number(p: &mut Parser) {
+ assert!(p.current().is_number());
+ p.bump();
+}
+fn literal(p: &mut Parser) {
+ assert!(p.current().is_literal());
+ p.bump();
+}
fn lhs_basic(p: &mut Parser) -> Option<CompletedMarker> {
let _e = p.expected_syntax_name("value");
- Some(if p.peek().map(|l| l.is_literal()).unwrap_or(false) {
+ Some(if p.current().is_literal() {
let m = p.start();
- p.bump();
+ literal(p);
m.complete(p, EXPR_LITERAL)
- } else if p.peek().map(|l| l.is_string()).unwrap_or(false) {
+ } else if p.current().is_string() {
let m = p.start();
- p.bump();
+ string(p);
m.complete(p, EXPR_STRING)
- } else if p.peek().map(|l| l.is_number()).unwrap_or(false) {
+ } else if p.current().is_number() {
let m = p.start();
- p.bump();
+ number(p);
m.complete(p, EXPR_NUMBER)
} else if p.at(IDENT) {
let m = p.start();
- p.bump();
+ name(p);
m.complete(p, EXPR_VAR)
+ } else if p.at(INTRINSIC_THIS_FILE) {
+ let m = p.start();
+ p.bump();
+ m.complete(p, EXPR_INTRINSIC_THIS_FILE)
+ } else if p.at(INTRINSIC_ID) {
+ let m = p.start();
+ p.bump();
+ m.complete(p, EXPR_INTRINSIC_ID)
+ } else if p.at(INTRINSIC) {
+ let m = p.start();
+ p.bump();
+ p.expect(T!['(']);
+ name(p);
+ p.expect(T![')']);
+ m.complete(p, EXPR_INTRINSIC)
+ } else if p.at(T![if]) {
+ let m = p.start();
+ p.bump();
+ expr(p);
+ p.expect(T![then]);
+ expr(p).map(|c| c.wrap(p, TRUE_EXPR));
+ if p.at(T![else]) {
+ p.bump();
+ expr(p).map(|c| c.wrap(p, FALSE_EXPR));
+ }
+ m.complete(p, EXPR_IF_THEN_ELSE)
} else if p.at(T!['[']) {
array(p)
} else if p.at(T!['{']) {
@@ -675,35 +989,26 @@
} else if p.at(T![local]) {
let m = p.start();
p.bump();
- let mut sus_local = None;
loop {
- p.expect_with_recovery_set(IDENT, TS![= ; local]);
- if p.at(T!['(']) {
- params(p);
+ if p.at(T![;]) {
+ p.bump();
+ break;
}
-
- let sus_local_candidate = p.start_ranger();
- p.expect_with_recovery_set(T![=], TS![; local]);
+ bind(p);
- sus_local = p.at(T![local]).then(|| sus_local_candidate.finish(p));
- expr(p);
-
- if !comma(p) {
- break;
+ if p.at(T![,]) {
+ p.bump();
+ continue;
}
- }
- p.expect(T![;]);
- if let Some(sus_local) = sus_local {
- if sus_local.had_error_since(p) {
- p.custom_error(sus_local, "unusal local placement, missing ';' ?")
- }
+ p.expect(T![;]);
+ break;
}
expr(p);
- m.complete(p, T![local])
+ m.complete(p, EXPR_LOCAL)
} else if p.at(T![function]) {
let m = p.start();
p.bump();
- args(p);
+ params_desc(p);
expr(p);
m.complete(p, EXPR_FUNCTION)
} else if p.at(T![error]) {
@@ -713,20 +1018,17 @@
m.complete(p, EXPR_ERROR)
} else if p.at(T![assert]) {
let m = p.start();
- p.bump();
+ assertion(p);
+ p.expect(T![;]);
expr(p);
- if p.at(T![:]) {
- p.bump();
- expr(p);
- }
m.complete(p, EXPR_ASSERT)
} else if p.at(T![import]) || p.at(T![importstr]) || p.at(T![importbin]) {
let m = p.start();
p.bump();
- expr(p);
+ string(p);
m.complete(p, EXPR_IMPORT)
} else if p.at(T![-]) || p.at(T![!]) || p.at(T![~]) {
- let op = match p.peek().unwrap() {
+ let op = match p.current() {
T![-] => UnaryOperator::Minus,
T![!] => UnaryOperator::Not,
T![~] => UnaryOperator::BitNegate,
@@ -746,7 +1048,7 @@
p.bump();
m.complete(p, EXPR_PARENED)
} else {
- p.error_with_no_skip();
+ p.error_with_recovery_set(TS![]);
return None;
})
}
@@ -755,14 +1057,4 @@
pub fn syntax(&self) -> SyntaxNode {
SyntaxNode::new_root(self.green_node.clone())
}
-}
-
-pub fn parse(input: &str) -> Parse {
- let lexemes = lex(input);
- let parser = Parser::new(&lexemes);
- let events = parser.parse();
- dbg!(&events);
- let sink = Sink::new(events, &lexemes);
-
- sink.finish()
}
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__array_comp.snapdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__array_comp.snap
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__array_comp.snap
@@ -1,43 +1,34 @@
---
-source: crates/jrsonnet-rowan-parser/src/lib.rs
-assertion_line: 88
+source: crates/jrsonnet-rowan-parser/src/tests.rs
expression: "[a for a in [1, 2, 3]]\n"
-
---
-Root@0..23
- Array@0..23
- SymbolLeftBracket@0..1 "["
- ArrayElem@1..21
- BodyDef@1..3
- Ident@1..3
- Ident@1..2 "a"
- Whitespace@2..3 " "
- CompspecFor@3..21
- KeywordFor@3..6 "for"
- Whitespace@6..7 " "
- Ident@7..8 "a"
- Whitespace@8..9 " "
- OpIn@9..11 "in"
- Whitespace@11..12 " "
- Array@12..21
- SymbolLeftBracket@12..13 "["
- ArrayElem@13..14
- BodyDef@13..14
- Literal@13..14
- Number@13..14 "1"
- SymbolComma@14..15 ","
- Whitespace@15..16 " "
- ArrayElem@16..17
- BodyDef@16..17
- Literal@16..17
- Number@16..17 "2"
- SymbolComma@17..18 ","
- Whitespace@18..19 " "
- ArrayElem@19..20
- BodyDef@19..20
- Literal@19..20
- Number@19..20 "3"
- SymbolRightBracket@20..21 "]"
- SymbolRightBracket@21..22 "]"
- Whitespace@22..23 "\n"
+SOURCE_FILE@0..22
+ EXPR_ARRAY_COMP@0..22
+ L_BRACK@0..1 "["
+ EXPR_VAR@1..2
+ NAME@1..2
+ IDENT@1..2 "a"
+ WHITESPACE@2..3 " "
+ FOR_SPEC@3..21
+ FOR_KW@3..6 "for"
+ WHITESPACE@6..7 " "
+ NAME@7..8
+ IDENT@7..8 "a"
+ WHITESPACE@8..9 " "
+ IN_KW@9..11 "in"
+ WHITESPACE@11..12 " "
+ EXPR_ARRAY@12..21
+ L_BRACK@12..13 "["
+ EXPR_NUMBER@13..14
+ FLOAT@13..14 "1"
+ COMMA@14..15 ","
+ WHITESPACE@15..16 " "
+ EXPR_NUMBER@16..17
+ FLOAT@16..17 "2"
+ COMMA@17..18 ","
+ WHITESPACE@18..19 " "
+ EXPR_NUMBER@19..20
+ FLOAT@19..20 "3"
+ R_BRACK@20..21 "]"
+ R_BRACK@21..22 "]"
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__array_comp_incompatible_with_multiple_elems.snapdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__array_comp_incompatible_with_multiple_elems.snap
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__array_comp_incompatible_with_multiple_elems.snap
@@ -1,58 +1,48 @@
---
-source: crates/jrsonnet-rowan-parser/src/lib.rs
-assertion_line: 88
+source: crates/jrsonnet-rowan-parser/src/tests.rs
expression: "[a for a in [1, 2, 3], b]\n"
-
---
-Root@0..26
- Array@0..26
- SymbolLeftBracket@0..1 "["
- ArrayElem@1..21
- BodyDef@1..3
- Ident@1..3
- Ident@1..2 "a"
- Whitespace@2..3 " "
- CompspecFor@3..21
- KeywordFor@3..6 "for"
- Whitespace@6..7 " "
- Ident@7..8 "a"
- Whitespace@8..9 " "
- OpIn@9..11 "in"
- Whitespace@11..12 " "
- Array@12..21
- SymbolLeftBracket@12..13 "["
- ArrayElem@13..14
- BodyDef@13..14
- Literal@13..14
- Number@13..14 "1"
- SymbolComma@14..15 ","
- Whitespace@15..16 " "
- ArrayElem@16..17
- BodyDef@16..17
- Literal@16..17
- Number@16..17 "2"
- SymbolComma@17..18 ","
- Whitespace@18..19 " "
- ArrayElem@19..20
- BodyDef@19..20
- Literal@19..20
- Number@19..20 "3"
- SymbolRightBracket@20..21 "]"
- SymbolComma@21..22 ","
- Whitespace@22..23 " "
- ArrayElem@23..24
- BodyDef@23..24
- Ident@23..24
- Ident@23..24 "b"
- SymbolRightBracket@24..25 "]"
- Whitespace@25..26 "\n"
+SOURCE_FILE@0..25
+ EXPR_ARRAY@0..25
+ L_BRACK@0..1 "["
+ EXPR_VAR@1..2
+ NAME@1..2
+ IDENT@1..2 "a"
+ WHITESPACE@2..3 " "
+ FOR_SPEC@3..21
+ FOR_KW@3..6 "for"
+ WHITESPACE@6..7 " "
+ NAME@7..8
+ IDENT@7..8 "a"
+ WHITESPACE@8..9 " "
+ IN_KW@9..11 "in"
+ WHITESPACE@11..12 " "
+ EXPR_ARRAY@12..21
+ L_BRACK@12..13 "["
+ EXPR_NUMBER@13..14
+ FLOAT@13..14 "1"
+ COMMA@14..15 ","
+ WHITESPACE@15..16 " "
+ EXPR_NUMBER@16..17
+ FLOAT@16..17 "2"
+ COMMA@17..18 ","
+ WHITESPACE@18..19 " "
+ EXPR_NUMBER@19..20
+ FLOAT@19..20 "3"
+ R_BRACK@20..21 "]"
+ COMMA@21..22 ","
+ WHITESPACE@22..23 " "
+ EXPR_VAR@23..24
+ NAME@23..24
+ IDENT@23..24 "b"
+ R_BRACK@24..25 "]"
===
Custom { error: "compspec may only be used if there is only one array element", range: 3..21 }
===
- [38;2;255;30;30m×[0m syntax error
- ╭────
- [2m1[0m │ [a for a in [1, 2, 3], b]
- · [38;2;246;87;248m ─────────┬────────[0m
- · [38;2;246;87;248m╰── [38;2;246;87;248mcompspec may only be used if there is only one array element[0m[0m
- ╰────
+ x syntax error
+ ,----
+ 1 | [a for a in [1, 2, 3], b]
+ : ^^^^^^^^^|^^^^^^^^
+ : `-- compspec may only be used if there is only one array element
+ `----
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__empty.snapdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__empty.snap
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__empty.snap
@@ -1,18 +1,14 @@
---
-source: crates/jrsonnet-rowan-parser/src/lib.rs
-assertion_line: 88
+source: crates/jrsonnet-rowan-parser/src/tests.rs
expression: " "
-
---
-Root@0..1
- Whitespace@0..1 " "
+SOURCE_FILE@0..1
+ WHITESPACE@0..1 " "
===
Missing { expected: Named("value"), offset: 1 }
===
- [38;2;255;30;30m×[0m syntax error
- ╭────
- [2m1[0m │
- · [38;2;246;87;248m ▲[0m
- · [38;2;246;87;248m╰── [38;2;246;87;248mmissing value[0m[0m
- ╰────
+ x syntax error
+ ,----
+ 1 |
+ `----
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__function.snapdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__function.snap
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__function.snap
@@ -1,34 +1,38 @@
---
-source: crates/jrsonnet-rowan-parser/src/lib.rs
-assertion_line: 88
+source: crates/jrsonnet-rowan-parser/src/tests.rs
expression: "function(a, b = 1) a + b\n"
-
---
-Root@0..25
- FunctionDef@0..25
- KeywordFunction@0..8 "function"
- LParen@8..9 "("
- DefPositionalArg@9..10
- Ident@9..10 "a"
- SymbolComma@10..11 ","
- Whitespace@11..12 " "
- DefNamedArg@12..17
- Ident@12..13 "b"
- Whitespace@13..14 " "
- SymbolAssign@14..15 "="
- Whitespace@15..16 " "
- Literal@16..17
- Number@16..17 "1"
- RParen@17..18 ")"
- Whitespace@18..19 " "
- BodyDef@19..25
- BinOp@19..25
- Ident@19..21
- Ident@19..20 "a"
- Whitespace@20..21 " "
- OpPlus@21..22 "+"
- Whitespace@22..23 " "
- Ident@23..25
- Ident@23..24 "b"
- Whitespace@24..25 "\n"
+SOURCE_FILE@0..24
+ EXPR_FUNCTION@0..24
+ FUNCTION_KW@0..8 "function"
+ PARAMS_DESC@8..18
+ L_PAREN@8..9 "("
+ PARAM@9..10
+ DESTRUCT_FULL@9..10
+ NAME@9..10
+ IDENT@9..10 "a"
+ COMMA@10..11 ","
+ WHITESPACE@11..12 " "
+ PARAM@12..17
+ DESTRUCT_FULL@12..13
+ NAME@12..13
+ IDENT@12..13 "b"
+ WHITESPACE@13..14 " "
+ ASSIGN@14..15 "="
+ WHITESPACE@15..16 " "
+ EXPR_NUMBER@16..17
+ FLOAT@16..17 "1"
+ R_PAREN@17..18 ")"
+ WHITESPACE@18..19 " "
+ EXPR_BINARY@19..24
+ LHS_EXPR@19..20
+ EXPR_VAR@19..20
+ NAME@19..20
+ IDENT@19..20 "a"
+ WHITESPACE@20..21 " "
+ PLUS@21..22 "+"
+ WHITESPACE@22..23 " "
+ EXPR_VAR@23..24
+ NAME@23..24
+ IDENT@23..24 "b"
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__function_error_body.snapdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__function_error_body.snap
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__function_error_body.snap
@@ -1,29 +1,30 @@
---
-source: crates/jrsonnet-rowan-parser/src/lib.rs
-assertion_line: 88
+source: crates/jrsonnet-rowan-parser/src/tests.rs
expression: "function(a, b)\n"
-
---
-Root@0..15
- FunctionDef@0..15
- KeywordFunction@0..8 "function"
- LParen@8..9 "("
- DefPositionalArg@9..10
- Ident@9..10 "a"
- SymbolComma@10..11 ","
- Whitespace@11..12 " "
- DefPositionalArg@12..13
- Ident@12..13 "b"
- RParen@13..14 ")"
- Whitespace@14..15 "\n"
- BodyDef@15..15
+SOURCE_FILE@0..14
+ EXPR_FUNCTION@0..14
+ FUNCTION_KW@0..8 "function"
+ PARAMS_DESC@8..14
+ L_PAREN@8..9 "("
+ PARAM@9..10
+ DESTRUCT_FULL@9..10
+ NAME@9..10
+ IDENT@9..10 "a"
+ COMMA@10..11 ","
+ WHITESPACE@11..12 " "
+ PARAM@12..13
+ DESTRUCT_FULL@12..13
+ NAME@12..13
+ IDENT@12..13 "b"
+ R_PAREN@13..14 ")"
===
Missing { expected: Named("value"), offset: 14 }
===
- [38;2;255;30;30m×[0m syntax error
- ╭────
- [2m1[0m │ function(a, b)
- · [38;2;246;87;248m ▲[0m
- · [38;2;246;87;248m╰── [38;2;246;87;248mmissing value[0m[0m
- ╰────
+ x syntax error
+ ,----
+ 1 | function(a, b)
+ : ^
+ : `-- missing value
+ `----
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__function_error_no_value.snapdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__function_error_no_value.snap
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__function_error_no_value.snap
@@ -1,41 +1,39 @@
---
-source: crates/jrsonnet-rowan-parser/src/lib.rs
-assertion_line: 88
+source: crates/jrsonnet-rowan-parser/src/tests.rs
expression: "function(a, b = ) a + b\n"
-
---
-Root@0..24
- FunctionDef@0..24
- KeywordFunction@0..8 "function"
- LParen@8..9 "("
- DefPositionalArg@9..10
- Ident@9..10 "a"
- SymbolComma@10..11 ","
- Whitespace@11..12 " "
- DefNamedArg@12..16
- Ident@12..13 "b"
- Whitespace@13..14 " "
- SymbolAssign@14..15 "="
- Whitespace@15..16 " "
- RParen@16..17 ")"
- Whitespace@17..18 " "
- BodyDef@18..24
- BinOp@18..24
- Ident@18..20
- Ident@18..19 "a"
- Whitespace@19..20 " "
- OpPlus@20..21 "+"
- Whitespace@21..22 " "
- Ident@22..24
- Ident@22..23 "b"
- Whitespace@23..24 "\n"
+SOURCE_FILE@0..24
+ EXPR_FUNCTION@0..24
+ FUNCTION_KW@0..8 "function"
+ PARAMS_DESC@8..18
+ L_PAREN@8..9 "("
+ PARAM@9..10
+ IDENT@9..10 "a"
+ COMMA@10..11 ","
+ WHITESPACE@11..12 " "
+ PARAM@12..16
+ IDENT@12..13 "b"
+ WHITESPACE@13..14 " "
+ ASSIGN@14..15 "="
+ WHITESPACE@15..16 " "
+ R_PAREN@16..17 ")"
+ WHITESPACE@17..18 " "
+ EXPR_BINARY@18..24
+ EXPR_VAR@18..20
+ IDENT@18..19 "a"
+ WHITESPACE@19..20 " "
+ PLUS@20..21 "+"
+ WHITESPACE@21..22 " "
+ EXPR_VAR@22..24
+ IDENT@22..23 "b"
+ WHITESPACE@23..24 "\n"
===
Missing { expected: Named("value"), offset: 15 }
===
- [38;2;255;30;30m×[0m syntax error
- ╭────
- [2m1[0m │ function(a, b = ) a + b
- · [38;2;246;87;248m ▲[0m
- · [38;2;246;87;248m╰── [38;2;246;87;248mmissing value[0m[0m
- ╰────
+ x syntax error
+ ,----
+ 1 | function(a, b = ) a + b
+ : ^
+ : `-- missing value
+ `----
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__function_error_rparen.snapdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__function_error_rparen.snap
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__function_error_rparen.snap
@@ -1,30 +1,31 @@
---
-source: crates/jrsonnet-rowan-parser/src/lib.rs
-assertion_line: 88
+source: crates/jrsonnet-rowan-parser/src/tests.rs
expression: "function(a, b\n"
-
---
-Root@0..14
- FunctionDef@0..14
- KeywordFunction@0..8 "function"
- LParen@8..9 "("
- DefPositionalArg@9..10
- Ident@9..10 "a"
- SymbolComma@10..11 ","
- Whitespace@11..12 " "
- DefPositionalArg@12..14
- Ident@12..13 "b"
- Whitespace@13..14 "\n"
- BodyDef@14..14
+SOURCE_FILE@0..13
+ EXPR_FUNCTION@0..13
+ FUNCTION_KW@0..8 "function"
+ PARAMS_DESC@8..13
+ L_PAREN@8..9 "("
+ PARAM@9..10
+ DESTRUCT_FULL@9..10
+ NAME@9..10
+ IDENT@9..10 "a"
+ COMMA@10..11 ","
+ WHITESPACE@11..12 " "
+ PARAM@12..13
+ DESTRUCT_FULL@12..13
+ NAME@12..13
+ IDENT@12..13 "b"
===
-Missing { expected: Unnamed(RParen), offset: 13 }
+Missing { expected: Unnamed(R_PAREN), offset: 13 }
Missing { expected: Named("value"), offset: 13 }
===
- [38;2;255;30;30m×[0m syntax error
- ╭────
- [2m1[0m │ function(a, b
- · [38;2;246;87;248m ▲[0m
- · [38;2;246;87;248m│[0m[38;2;30;201;212m╰── [38;2;30;201;212mmissing value[0m[0m
- · [38;2;246;87;248m╰── [38;2;246;87;248mmissing RParen[0m[0m
- ╰────
+ x syntax error
+ ,----
+ 1 | function(a, b
+ : ^
+ : |`-- missing value
+ : `-- missing R_PAREN
+ `----
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__local_no_value_recovery.snapdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__local_no_value_recovery.snap
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__local_no_value_recovery.snap
@@ -1,47 +1,39 @@
---
-source: crates/jrsonnet-rowan-parser/src/lib.rs
-assertion_line: 88
+source: crates/jrsonnet-rowan-parser/src/tests.rs
expression: "local a =\nlocal b = 3;\n1\n"
-
---
-Root@0..25
- Local@0..25
- KeywordLocal@0..5 "local"
- Whitespace@5..6 " "
- Ident@6..7 "a"
- Whitespace@7..8 " "
- SymbolAssign@8..9 "="
- Whitespace@9..10 "\n"
- Local@10..25
- KeywordLocal@10..15 "local"
- Whitespace@15..16 " "
- Ident@16..17 "b"
- Whitespace@17..18 " "
- SymbolAssign@18..19 "="
- Whitespace@19..20 " "
- Literal@20..21
- Number@20..21 "3"
- SymbolSemi@21..22 ";"
- Whitespace@22..23 "\n"
- BodyDef@23..25
- Literal@23..25
- Number@23..24 "1"
- Whitespace@24..25 "\n"
- BodyDef@25..25
+SOURCE_FILE@0..25
+ LOCAL_KW@0..25
+ LOCAL_KW@0..5 "local"
+ WHITESPACE@5..6 " "
+ IDENT@6..7 "a"
+ WHITESPACE@7..8 " "
+ ASSIGN@8..9 "="
+ WHITESPACE@9..10 "\n"
+ LOCAL_KW@10..25
+ LOCAL_KW@10..15 "local"
+ WHITESPACE@15..16 " "
+ IDENT@16..17 "b"
+ WHITESPACE@17..18 " "
+ ASSIGN@18..19 "="
+ WHITESPACE@19..20 " "
+ EXPR_NUMBER@20..21
+ NUMBER@20..21 "3"
+ SEMI@21..22 ";"
+ WHITESPACE@22..23 "\n"
+ EXPR_NUMBER@23..25
+ NUMBER@23..24 "1"
+ WHITESPACE@24..25 "\n"
===
-Missing { expected: Unnamed(SymbolSemi), offset: 24 }
-Custom { error: "unusal local placement, missing ';' ?", range: 8..9 }
+Missing { expected: Unnamed(SEMI), offset: 24 }
Missing { expected: Named("value"), offset: 24 }
===
- [38;2;255;30;30m×[0m syntax error
- ╭─[1:1]
- [2m1[0m │ local a =
- · [38;2;246;87;248m ┬[0m
- · [38;2;246;87;248m╰── [38;2;246;87;248munusal local placement, missing ';' ?[0m[0m
- [2m2[0m │ local b = 3;
- [2m3[0m │ 1
- · [38;2;30;201;212m ▲[0m
- · [38;2;30;201;212m│[0m[38;2;145;246;111m╰── [38;2;145;246;111mmissing value[0m[0m
- · [38;2;30;201;212m╰── [38;2;30;201;212mmissing SymbolSemi[0m[0m
- ╰────
+ x syntax error
+ ,-[2:1]
+ 2 | local b = 3;
+ 3 | 1
+ : ^
+ : |`-- missing value
+ : `-- missing SEMI
+ `----
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__local_no_value_recovery.snap.newdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__local_no_value_recovery.snap.new
+++ /dev/null
@@ -1,43 +0,0 @@
----
-source: crates/jrsonnet-rowan-parser/src/lib.rs
-assertion_line: 88
-expression: "local a =\nlocal b = 3;\n1\n"
-
----
-Root@0..25
- Local@0..25
- KeywordLocal@0..5 "local"
- Whitespace@5..6 " "
- Ident@6..7 "a"
- Whitespace@7..8 " "
- SymbolAssign@8..9 "="
- Whitespace@9..10 "\n"
- Local@10..25
- KeywordLocal@10..15 "local"
- Whitespace@15..16 " "
- Ident@16..17 "b"
- Whitespace@17..18 " "
- SymbolAssign@18..19 "="
- Whitespace@19..20 " "
- Literal@20..21
- Number@20..21 "3"
- SymbolSemi@21..22 ";"
- Whitespace@22..23 "\n"
- BodyDef@23..25
- Literal@23..25
- Number@23..24 "1"
- Whitespace@24..25 "\n"
- BodyDef@25..25
-===
-Missing { expected: Unnamed(SymbolSemi), offset: 24 }
-Missing { expected: Named("value"), offset: 24 }
-===
- [38;2;255;30;30m×[0m syntax error
- ╭─[2:1]
- [2m2[0m │ local b = 3;
- [2m3[0m │ 1
- · [38;2;246;87;248m ▲[0m
- · [38;2;246;87;248m│[0m[38;2;30;201;212m╰── [38;2;30;201;212mmissing value[0m[0m
- · [38;2;246;87;248m╰── [38;2;246;87;248mmissing SymbolSemi[0m[0m
- ╰────
-
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__local_novalue.snapdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__local_novalue.snap
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__local_novalue.snap
@@ -1,29 +1,26 @@
---
-source: crates/jrsonnet-rowan-parser/src/lib.rs
-assertion_line: 88
+source: crates/jrsonnet-rowan-parser/src/tests.rs
expression: "local a =\n"
-
---
-Root@0..10
- Local@0..10
- KeywordLocal@0..5 "local"
- Whitespace@5..6 " "
- Ident@6..7 "a"
- Whitespace@7..8 " "
- SymbolAssign@8..9 "="
- Whitespace@9..10 "\n"
- BodyDef@10..10
+SOURCE_FILE@0..10
+ LOCAL_KW@0..10
+ LOCAL_KW@0..5 "local"
+ WHITESPACE@5..6 " "
+ IDENT@6..7 "a"
+ WHITESPACE@7..8 " "
+ ASSIGN@8..9 "="
+ WHITESPACE@9..10 "\n"
===
Missing { expected: Named("value"), offset: 9 }
-Missing { expected: Unnamed(SymbolSemi), offset: 9 }
+Missing { expected: Unnamed(SEMI), offset: 9 }
Missing { expected: Named("value"), offset: 9 }
===
- [38;2;255;30;30m×[0m syntax error
- ╭────
- [2m1[0m │ local a =
- · [38;2;246;87;248m ▲[0m
- · [38;2;145;246;111m╰── [38;2;145;246;111mmissing value[0m[0m
- · [38;2;246;87;248m│[0m[38;2;30;201;212m╰── [38;2;30;201;212mmissing SymbolSemi[0m[0m
- · [38;2;246;87;248m╰── [38;2;246;87;248mmissing value[0m[0m
- ╰────
+ x syntax error
+ ,----
+ 1 | local a =
+ : ^
+ : `-- missing value
+ : |`-- missing SEMI
+ : `-- missing value
+ `----
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__named_before_positional.snapdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__named_before_positional.snap
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__named_before_positional.snap
@@ -1,63 +1,61 @@
---
-source: crates/jrsonnet-rowan-parser/src/lib.rs
-assertion_line: 88
+source: crates/jrsonnet-rowan-parser/src/tests.rs
expression: "a(1, 2, b=4, 3, 5, k = 12, 6)\n"
-
---
-Root@0..30
- FunctionCall@0..30
- Ident@0..1
- Ident@0..1 "a"
- LParen@1..2 "("
- DefPositionalArg@2..3
- Literal@2..3
- Number@2..3 "1"
- SymbolComma@3..4 ","
- Whitespace@4..5 " "
- DefPositionalArg@5..6
- Literal@5..6
- Number@5..6 "2"
- SymbolComma@6..7 ","
- Whitespace@7..8 " "
- DefNamedArg@8..11
- Ident@8..9 "b"
- SymbolAssign@9..10 "="
- Literal@10..11
- Number@10..11 "4"
- SymbolComma@11..12 ","
- Whitespace@12..13 " "
- ErrorPositionalAfterNamed@13..28
- DefPositionalArg@13..14
- Literal@13..14
- Number@13..14 "3"
- SymbolComma@14..15 ","
- Whitespace@15..16 " "
- DefPositionalArg@16..17
- Literal@16..17
- Number@16..17 "5"
- SymbolComma@17..18 ","
- Whitespace@18..19 " "
- DefNamedArg@19..25
- Ident@19..20 "k"
- Whitespace@20..21 " "
- SymbolAssign@21..22 "="
- Whitespace@22..23 " "
- Literal@23..25
- Number@23..25 "12"
- SymbolComma@25..26 ","
- Whitespace@26..27 " "
- DefPositionalArg@27..28
- Literal@27..28
- Number@27..28 "6"
- RParen@28..29 ")"
- Whitespace@29..30 "\n"
+SOURCE_FILE@0..30
+ EXPR_APPLY@0..30
+ EXPR_VAR@0..1
+ IDENT@0..1 "a"
+ L_PAREN@1..2 "("
+ ARG@2..3
+ EXPR_NUMBER@2..3
+ NUMBER@2..3 "1"
+ COMMA@3..4 ","
+ WHITESPACE@4..5 " "
+ ARG@5..6
+ EXPR_NUMBER@5..6
+ NUMBER@5..6 "2"
+ COMMA@6..7 ","
+ WHITESPACE@7..8 " "
+ ARG@8..11
+ IDENT@8..9 "b"
+ ASSIGN@9..10 "="
+ EXPR_NUMBER@10..11
+ NUMBER@10..11 "4"
+ COMMA@11..12 ","
+ WHITESPACE@12..13 " "
+ ERROR@13..28
+ ARG@13..14
+ EXPR_NUMBER@13..14
+ NUMBER@13..14 "3"
+ COMMA@14..15 ","
+ WHITESPACE@15..16 " "
+ ARG@16..17
+ EXPR_NUMBER@16..17
+ NUMBER@16..17 "5"
+ COMMA@17..18 ","
+ WHITESPACE@18..19 " "
+ ARG@19..25
+ IDENT@19..20 "k"
+ WHITESPACE@20..21 " "
+ ASSIGN@21..22 "="
+ WHITESPACE@22..23 " "
+ EXPR_NUMBER@23..25
+ NUMBER@23..25 "12"
+ COMMA@25..26 ","
+ WHITESPACE@26..27 " "
+ ARG@27..28
+ EXPR_NUMBER@27..28
+ NUMBER@27..28 "6"
+ R_PAREN@28..29 ")"
+ WHITESPACE@29..30 "\n"
===
Custom { error: "positional arguments can't be placed after named", range: 13..28 }
===
- [38;2;255;30;30m×[0m syntax error
- ╭────
- [2m1[0m │ a(1, 2, b=4, 3, 5, k = 12, 6)
- · [38;2;246;87;248m ───────┬───────[0m
- · [38;2;246;87;248m╰── [38;2;246;87;248mpositional arguments can't be placed after named[0m[0m
- ╰────
+ x syntax error
+ ,----
+ 1 | a(1, 2, b=4, 3, 5, k = 12, 6)
+ : ^^^^^^^|^^^^^^^
+ : `-- positional arguments can't be placed after named
+ `----
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__no_lhs.snapdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__no_lhs.snap
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__no_lhs.snap
@@ -1,23 +1,19 @@
---
-source: crates/jrsonnet-rowan-parser/src/lib.rs
-assertion_line: 88
+source: crates/jrsonnet-rowan-parser/src/tests.rs
expression: "+ 2\n"
-
---
-Root@0..4
- OpPlus@0..1 "+"
- Whitespace@1..2 " "
- Number@2..3 "2"
- Whitespace@3..4 "\n"
+SOURCE_FILE@0..2
+ PLUS@0..1 "+"
+ WHITESPACE@1..2 " "
===
Missing { expected: Named("value"), offset: 0 }
-Custom { error: "unexpected input after expression", range: 0..3 }
+Custom { error: "unexpected input after expression", range: 0..1 }
===
- [38;2;255;30;30m×[0m syntax error
- ╭────
- [2m1[0m │ + 2
- · [38;2;246;87;248m▲[0m[38;2;30;201;212m─┬─[0m
- · [38;2;246;87;248m│[0m[38;2;30;201;212m╰── [38;2;30;201;212munexpected input after expression[0m[0m
- · [38;2;246;87;248m╰── [38;2;246;87;248mmissing value[0m[0m
- ╰────
+ x syntax error
+ ,----
+ 1 | + 2
+ : ^
+ : |`-- unexpected input after expression
+ : `-- missing value
+ `----
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__no_operator.snapdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__no_operator.snap
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__no_operator.snap
@@ -1,22 +1,20 @@
---
-source: crates/jrsonnet-rowan-parser/src/lib.rs
-assertion_line: 88
+source: crates/jrsonnet-rowan-parser/src/tests.rs
expression: "2 2\n"
-
---
-Root@0..4
- Literal@0..2
- Number@0..1 "2"
- Whitespace@1..2 " "
- Number@2..3 "2"
- Whitespace@3..4 "\n"
+SOURCE_FILE@0..3
+ EXPR_NUMBER@0..1
+ FLOAT@0..1 "2"
+ WHITESPACE@1..2 " "
+ ERROR@2..3
+ FLOAT@2..3 "2"
===
-Custom { error: "unexpected input after expression", range: 2..3 }
+Unexpected { expected: Unnamed(EOF), found: FLOAT, range: 2..3 }
===
- [38;2;255;30;30m×[0m syntax error
- ╭────
- [2m1[0m │ 2 2
- · [38;2;246;87;248m ┬[0m
- · [38;2;246;87;248m╰── [38;2;246;87;248munexpected input after expression[0m[0m
- ╰────
+ x syntax error
+ ,----
+ 1 | 2 2
+ : |
+ : `-- expected EOF, found FLOAT
+ `----
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__no_rhs.snapdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__no_rhs.snap
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__no_rhs.snap
@@ -1,23 +1,22 @@
---
-source: crates/jrsonnet-rowan-parser/src/lib.rs
-assertion_line: 88
+source: crates/jrsonnet-rowan-parser/src/tests.rs
expression: "a +\n"
-
---
-Root@0..4
- BinOp@0..4
- Ident@0..2
- Ident@0..1 "a"
- Whitespace@1..2 " "
- OpPlus@2..3 "+"
- Whitespace@3..4 "\n"
+SOURCE_FILE@0..3
+ EXPR_BINARY@0..3
+ LHS_EXPR@0..1
+ EXPR_VAR@0..1
+ NAME@0..1
+ IDENT@0..1 "a"
+ WHITESPACE@1..2 " "
+ PLUS@2..3 "+"
===
Missing { expected: Named("value"), offset: 3 }
===
- [38;2;255;30;30m×[0m syntax error
- ╭────
- [2m1[0m │ a +
- · [38;2;246;87;248m ▲[0m
- · [38;2;246;87;248m╰── [38;2;246;87;248mmissing value[0m[0m
- ╰────
+ x syntax error
+ ,----
+ 1 | a +
+ : ^
+ : `-- missing value
+ `----
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__plain_call.snapdiffbeforeafterboth--- /dev/null
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__plain_call.snap
@@ -0,0 +1,52 @@
+---
+source: crates/jrsonnet-rowan-parser/src/tests.rs
+expression: "std.substr(a, 0, std.length(b)) == b\n"
+---
+SOURCE_FILE@0..36
+ EXPR_BINARY@0..36
+ LHS_EXPR@0..31
+ EXPR_APPLY@0..31
+ EXPR_INDEX@0..10
+ EXPR_VAR@0..3
+ NAME@0..3
+ IDENT@0..3 "std"
+ DOT@3..4 "."
+ NAME@4..10
+ IDENT@4..10 "substr"
+ ARGS_DESC@10..31
+ L_PAREN@10..11 "("
+ ARG@11..12
+ EXPR_VAR@11..12
+ NAME@11..12
+ IDENT@11..12 "a"
+ COMMA@12..13 ","
+ WHITESPACE@13..14 " "
+ ARG@14..15
+ EXPR_NUMBER@14..15
+ FLOAT@14..15 "0"
+ COMMA@15..16 ","
+ WHITESPACE@16..17 " "
+ ARG@17..30
+ EXPR_APPLY@17..30
+ EXPR_INDEX@17..27
+ EXPR_VAR@17..20
+ NAME@17..20
+ IDENT@17..20 "std"
+ DOT@20..21 "."
+ NAME@21..27
+ IDENT@21..27 "length"
+ ARGS_DESC@27..30
+ L_PAREN@27..28 "("
+ ARG@28..29
+ EXPR_VAR@28..29
+ NAME@28..29
+ IDENT@28..29 "b"
+ R_PAREN@29..30 ")"
+ R_PAREN@30..31 ")"
+ WHITESPACE@31..32 " "
+ EQ@32..34 "=="
+ WHITESPACE@34..35 " "
+ EXPR_VAR@35..36
+ NAME@35..36
+ IDENT@35..36 "b"
+
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__stdlib.snapdiffbeforeafterbothno changes
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__str_block_missing_indent.snapdiffbeforeafterboth--- /dev/null
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__str_block_missing_indent.snap
@@ -0,0 +1,8 @@
+---
+source: crates/jrsonnet-rowan-parser/src/tests.rs
+expression: "|||\n"
+---
+SOURCE_FILE@0..4
+ EXPR_STRING@0..4
+ ERROR_STRING_BLOCK_MISSING_INDENT@0..4 "|||\n"
+
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__str_block_missing_indent_text.snapdiffbeforeafterboth--- /dev/null
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__str_block_missing_indent_text.snap
@@ -0,0 +1,8 @@
+---
+source: crates/jrsonnet-rowan-parser/src/tests.rs
+expression: "|||\nhello\n"
+---
+SOURCE_FILE@0..10
+ EXPR_STRING@0..10
+ ERROR_STRING_BLOCK_MISSING_INDENT@0..10 "|||\nhello\n"
+
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__str_block_missing_newline.snapdiffbeforeafterboth--- /dev/null
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__str_block_missing_newline.snap
@@ -0,0 +1,8 @@
+---
+source: crates/jrsonnet-rowan-parser/src/tests.rs
+expression: "|||hello\n"
+---
+SOURCE_FILE@0..9
+ EXPR_STRING@0..9
+ ERROR_STRING_BLOCK_MISSING_NEW_LINE@0..9 "|||hello\n"
+
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__str_block_missing_termination.snapdiffbeforeafterboth--- /dev/null
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__str_block_missing_termination.snap
@@ -0,0 +1,8 @@
+---
+source: crates/jrsonnet-rowan-parser/src/tests.rs
+expression: "|||\n\thello\n"
+---
+SOURCE_FILE@0..11
+ EXPR_STRING@0..11
+ ERROR_STRING_BLOCK_UNEXPECTED_END@0..11 "|||\n\thello\n"
+
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__wrong_field_end.snapdiffbeforeafterboth--- /dev/null
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__wrong_field_end.snap
@@ -0,0 +1,30 @@
+---
+source: crates/jrsonnet-rowan-parser/src/tests.rs
+expression: "{\n\ta: 1;\n\tb: 2;\n}\n"
+---
+SOURCE_FILE@0..10
+ OBJ_BODY@0..7
+ L_BRACE@0..1 "{"
+ WHITESPACE@1..3 "\n\t"
+ MEMBER@3..7
+ IDENT@3..4 "a"
+ COLON@4..5 ":"
+ WHITESPACE@5..6 " "
+ EXPR_NUMBER@6..7
+ NUMBER@6..7 "1"
+ SEMI@7..8 ";"
+ WHITESPACE@8..10 "\n\t"
+===
+Missing { expected: Unnamed(R_BRACE), offset: 7 }
+Custom { error: "unexpected input after expression", range: 7..8 }
+===
+ x syntax error
+ ,-[1:1]
+ 1 | {
+ 2 | a: 1;
+ : ^
+ : |`-- unexpected input after expression
+ : `-- missing R_BRACE
+ 3 | b: 2;
+ `----
+
crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__wrong_field_end.snap.newdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__wrong_field_end.snap.new
+++ /dev/null
@@ -1,41 +0,0 @@
----
-source: crates/jrsonnet-rowan-parser/src/lib.rs
-assertion_line: 88
-expression: "{\n\ta: 1;\n\tb: 2;\n}\n"
-
----
-Root@0..18
- Object@0..7
- SymbolLeftBrace@0..1 "{"
- Whitespace@1..3 "\n\t"
- Field@3..7
- Ident@3..4 "a"
- SymbolColon@4..5 ":"
- Whitespace@5..6 " "
- Literal@6..7
- Number@6..7 "1"
- SymbolSemi@7..8 ";"
- Whitespace@8..10 "\n\t"
- Ident@10..11 "b"
- SymbolColon@11..12 ":"
- Whitespace@12..13 " "
- Number@13..14 "2"
- SymbolSemi@14..15 ";"
- Whitespace@15..16 "\n"
- SymbolRightBrace@16..17 "}"
- Whitespace@17..18 "\n"
-===
-Missing { expected: Unnamed(SymbolRightBrace), offset: 7 }
-Custom { error: "unexpected input after expression", range: 7..17 }
-===
- [38;2;255;30;30m×[0m syntax error
- ╭─[1:1]
- [2m1[0m │ {
- [2m2[0m │ [38;2;246;87;248m╭[0m[38;2;246;87;248m─[0m[38;2;246;87;248m▶[0m a: 1;
- · [38;2;246;87;248m│[0m[38;2;30;201;212m│[0m[38;2;246;87;248m ▲[0m
- · [38;2;246;87;248m│[0m[38;2;30;201;212m│[0m [38;2;246;87;248m╰── [38;2;246;87;248mmissing SymbolRightBrace[0m[0m
- [2m3[0m │ [38;2;30;201;212m│[0m b: 2;
- [2m4[0m │ [38;2;30;201;212m├[0m[38;2;30;201;212m─[0m[38;2;30;201;212m▶[0m }
- · [38;2;30;201;212m╰[0m[38;2;30;201;212m───[0m[38;2;30;201;212m─[0m [38;2;30;201;212munexpected input after expression[0m
- ╰────
-
crates/jrsonnet-rowan-parser/src/string_block.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/string_block.rs
+++ b/crates/jrsonnet-rowan-parser/src/string_block.rs
@@ -1,23 +1,23 @@
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum StringBlockToken {
- Valid,
- UnexpectedEndOfString,
- MissingTextBlockNewLine,
- MissingTextBlockTermination,
- MissingTextBlockIndent,
+pub enum StringBlockError {
+ UnexpectedEnd,
+ MissingNewLine,
+ MissingTermination,
+ MissingIndent,
}
use std::ops::Range;
-use StringBlockToken::*;
+use logos::Lexer;
+use StringBlockError::*;
use crate::SyntaxKind;
-pub fn lex_str_block_test<'a>(lex: &mut logos::Lexer<'a, SyntaxKind>) {
- lex_str_block(lex);
+pub fn lex_str_block_test(lex: &mut Lexer<SyntaxKind>) {
+ let _ = lex_str_block(lex);
}
-fn lex_str_block<'a>(lex: &mut logos::Lexer<'a, SyntaxKind>) -> StringBlockToken {
+pub fn lex_str_block(lex: &mut Lexer<SyntaxKind>) -> Result<(), StringBlockError> {
struct Context<'a> {
source: &'a str,
index: usize,
@@ -116,7 +116,7 @@
a.len()
}
- fn guess_token_end_and_bump<'a>(lex: &mut logos::Lexer<'a, SyntaxKind>, ctx: &Context<'a>) {
+ fn guess_token_end_and_bump<'a>(lex: &mut Lexer<'a, SyntaxKind>, ctx: &Context<'a>) {
let end_index = ctx
.rest()
.find("|||")
@@ -140,12 +140,12 @@
Some('\n') => (),
None => {
guess_token_end_and_bump(lex, &ctx);
- return UnexpectedEndOfString;
+ return Err(UnexpectedEnd);
}
// Text block requires new line after |||.
Some(_) => {
guess_token_end_and_bump(lex, &ctx);
- return MissingTextBlockNewLine;
+ return Err(MissingNewLine);
}
}
@@ -160,7 +160,7 @@
if num_whitespace == 0 {
// Text block's first line must start with whitespace
guess_token_end_and_bump(lex, &ctx);
- return MissingTextBlockIndent;
+ return Err(MissingIndent);
}
loop {
@@ -171,7 +171,7 @@
match ctx.next() {
None => {
guess_token_end_and_bump(lex, &ctx);
- return UnexpectedEndOfString;
+ return Err(UnexpectedEnd);
}
Some('\n') => break,
Some(_) => (),
@@ -188,26 +188,21 @@
if num_whitespace == 0 {
// End of the text block
let mut term_indent = String::with_capacity(num_whitespace);
- loop {
- match ctx.peek() {
- Some(' ') | Some('\t') => {
- term_indent.push(ctx.next().unwrap());
- }
- _ => break,
- }
+ while let Some(' ' | '\t') = ctx.peek() {
+ term_indent.push(ctx.next().unwrap());
}
if !ctx.rest().starts_with("|||") {
// Text block not terminated with |||
let pos = ctx.pos();
- if pos.len() == 0 {
+ if pos.is_empty() {
// eof
lex.bump(ctx.index);
- return UnexpectedEndOfString;
+ return Err(UnexpectedEnd);
}
guess_token_end_and_bump(lex, &ctx);
- return MissingTextBlockTermination;
+ return Err(MissingTermination);
}
// Skip '|||'
@@ -217,5 +212,5 @@
}
lex.bump(ctx.index);
- Valid
+ Ok(())
}
crates/jrsonnet-rowan-parser/src/tests.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/tests.rs
+++ b/crates/jrsonnet-rowan-parser/src/tests.rs
@@ -1,9 +1,11 @@
#![cfg(test)]
-use miette::{Diagnostic, GraphicalReportHandler, LabeledSpan};
+use miette::{
+ Diagnostic, GraphicalReportHandler, GraphicalTheme, LabeledSpan, ThemeCharacters, ThemeStyles,
+};
use thiserror::Error;
-use crate::parser::parse;
+use crate::{parse, AstNode};
#[derive(Debug, Error)]
#[error("syntax error")]
@@ -44,19 +46,22 @@
fn process(text: &str) -> String {
use std::fmt::Write;
let mut out = String::new();
- let node = parse(text);
+ let (node, errors) = parse(text);
write!(out, "{:#?}", node.syntax()).unwrap();
- if !node.errors.is_empty() && !text.is_empty() {
+ if !errors.is_empty() && !text.is_empty() {
writeln!(out, "===").unwrap();
- for err in &node.errors {
+ for err in &errors {
writeln!(out, "{:?}", err).unwrap();
}
let diag = MyDiagnostic {
code: text.to_string(),
- spans: node.errors.into_iter().map(|e| e.into()).collect(),
+ spans: errors.into_iter().map(|e| e.into()).collect(),
};
- let handler = GraphicalReportHandler::new();
+ let handler = GraphicalReportHandler::new_themed(GraphicalTheme {
+ characters: ThemeCharacters::ascii(),
+ styles: ThemeStyles::none(),
+ });
write!(out, "===").unwrap();
handler.render_report(&mut out, &diag).unwrap();
@@ -77,51 +82,94 @@
mk_test!(
empty => r#" "#
function => r#"
- function(a, b = 1) a + b
- "#
+ function(a, b = 1) a + b
+ "#
function_error_no_value => r#"
- function(a, b = ) a + b
- "#
+ function(a, b = ) a + b
+ "#
function_error_rparen => r#"
- function(a, b
- "#
+ function(a, b
+ "#
function_error_body => r#"
- function(a, b)
- "#
+ function(a, b)
+ "#
local_novalue => r#"
- local a =
- "#
+ local a =
+ "#
local_no_value_recovery => r#"
- local a =
- local b = 3;
- 1
- "#
+ local a =
+ local b = 3;
+ 1
+ "#
array_comp => r#"
- [a for a in [1, 2, 3]]
- "#
+ [a for a in [1, 2, 3]]
+ "#
array_comp_incompatible_with_multiple_elems => r#"
- [a for a in [1, 2, 3], b]
- "#
+ [a for a in [1, 2, 3], b]
+ "#
no_rhs => r#"
- a +
- "#
+ a +
+ "#
no_lhs => r#"
- + 2
- "#
+ + 2
+ "#
no_operator => "
- 2 2
- "
+ 2 2
+ "
named_before_positional => "
- a(1, 2, b=4, 3, 5, k = 12, 6)
- "
+ a(1, 2, b=4, 3, 5, k = 12, 6)
+ "
wrong_field_end => "
- {
- a: 1;
- b: 2;
- }
- "
+ {
+ a: 1;
+ b: 2;
+ }
+ "
+
+
+ plain_call => "
+ std.substr(a, 0, std.length(b)) == b
+ "
+
+ destruct => "
+ local [a, b, c] = arr;
+ local [a, ...] = arr_rest;
+ local [..., a] = rest_arr;
+ local [...] = rest_in_arr;
+ local [a, ...n] = arr_rest_n;
+ local [...n, a] = rest_arr_n;
+ local [...n] = rest_in_arr_n;
+
+ local {a, b, c} = obj;
+ local {a, b, c, ...} = obj_rest;
+ local {a, b, c, ...n} = obj_rest_n;
+
+ null
+ "
+
+ str_block_missing_indent => "
+ |||
+ "
+ str_block_missing_termination => "
+ |||
+ hello
+ "
+ str_block_missing_newline => "
+ |||hello
+ "
+ str_block_missing_indent_text => "
+ |||
+ hello
+ "
);
+
+#[test]
+fn stdlib() {
+ let src = jrsonnet_stdlib::STDLIB_STR;
+ let result = process(src);
+ insta::assert_snapshot!("stdlib", result, src);
+}
crates/jrsonnet-rowan-parser/src/token_set.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/token_set.rs
+++ b/crates/jrsonnet-rowan-parser/src/token_set.rs
@@ -1,14 +1,15 @@
use crate::SyntaxKind;
#[derive(Clone, Copy, Default)]
-pub struct SyntaxKindSet(u64);
+pub struct SyntaxKindSet(u128);
impl SyntaxKindSet {
+ #[allow(dead_code)]
pub const EMPTY: Self = Self(0);
- pub const ALL: Self = Self(u64::MAX);
+ pub const ALL: Self = Self(u128::MAX);
pub const fn new(kinds: &[SyntaxKind]) -> SyntaxKindSet {
- let mut res = 0u64;
+ let mut res = 0u128;
let mut i = 0;
while i < kinds.len() {
res |= mask(kinds[i]);
@@ -26,8 +27,8 @@
}
}
-const fn mask(kind: SyntaxKind) -> u64 {
- 1u64 << (kind as usize)
+const fn mask(kind: SyntaxKind) -> u128 {
+ 1u128 << (kind as u128)
}
#[macro_export]
@@ -40,3 +41,11 @@
])
};
}
+
+#[test]
+fn sanity() {
+ assert!(
+ (SyntaxKind::ERROR as u32) < 127,
+ "can't keep KindSet as bitset"
+ );
+}
xtask/Cargo.tomldiffbeforeafterboth--- a/xtask/Cargo.toml
+++ b/xtask/Cargo.toml
@@ -5,6 +5,7 @@
[dependencies]
anyhow = "1.0.57"
+indexmap = "1.9.0"
itertools = "0.10.3"
proc-macro2 = "1.0.39"
quote = "1.0.18"
xtask/src/sourcegen/ast.rsdiffbeforeafterboth--- a/xtask/src/sourcegen/ast.rs
+++ b/xtask/src/sourcegen/ast.rs
@@ -1,7 +1,13 @@
+use std::collections::{BTreeSet, HashMap};
+
use proc_macro2::TokenStream;
-use quote::{format_ident, quote};
+use quote::format_ident;
+use ungrammar::{Grammar, Rule};
-use super::{escape_token_macro, KindsSrc};
+use super::{
+ util::{pluralize, to_lower_snake_case},
+ KindsSrc,
+};
impl AstNodeSrc {
pub fn remove_field(&mut self, to_remove: Vec<usize>) {
@@ -14,9 +20,9 @@
#[allow(dead_code)]
#[derive(Default, Debug)]
pub struct AstSrc {
- pub tokens: Vec<String>,
pub nodes: Vec<AstNodeSrc>,
pub enums: Vec<AstEnumSrc>,
+ pub token_enums: Vec<AstTokenEnumSrc>,
}
#[derive(Debug)]
pub struct AstNodeSrc {
@@ -38,7 +44,11 @@
#[derive(Debug, Eq, PartialEq)]
pub enum Cardinality {
+ /// This field may not exist in code
Optional,
+ /// This field should exist in correctly parsed code
+ Required,
+ /// There may be multiple field values of this kind
Many,
}
@@ -50,6 +60,13 @@
pub variants: Vec<String>,
}
+#[derive(Debug, Clone)]
+pub struct AstTokenEnumSrc {
+ pub doc: Vec<String>,
+ pub name: String,
+ pub variants: Vec<String>,
+}
+
impl Field {
pub fn is_many(&self) -> bool {
matches!(
@@ -60,25 +77,29 @@
}
)
}
- pub fn token_kind(&self) -> Option<TokenStream> {
+
+ pub fn token_name(&self) -> Option<String> {
+ match self {
+ Field::Token(token) => Some(token.clone()),
+ _ => None,
+ }
+ }
+ pub fn token_kind(&self, kinds: &KindsSrc) -> Option<TokenStream> {
match self {
- Field::Token(token) => {
- let token: TokenStream = escape_token_macro(token);
- Some(quote! { T![#token] })
- }
+ Field::Token(token) => Some(kinds.token(token).expect("token exists").reference()),
_ => None,
}
}
+ pub fn is_token_enum(&self, grammar: &AstSrc) -> bool {
+ match self {
+ Field::Node { ty, .. } => grammar.token_enums.iter().any(|e| &e.name == ty),
+ _ => false,
+ }
+ }
pub fn method_name(&self, kinds: &KindsSrc) -> proc_macro2::Ident {
match self {
- Field::Token(name) => {
- if let Some(punct_name) = kinds.get_punct_name(name) {
- format_ident!("{}_token", punct_name.to_lowercase())
- } else {
- format_ident!("{}_token", name.to_lowercase())
- }
- }
+ Field::Token(name) => kinds.token(name).expect("token exists").method_name(),
Field::Node { name, .. } => {
format_ident!("{}", name)
}
@@ -91,3 +112,275 @@
}
}
}
+
+pub fn lower(kinds: &KindsSrc, grammar: &Grammar) -> AstSrc {
+ let mut res = AstSrc {
+ // tokens,
+ ..Default::default()
+ };
+
+ let nodes = grammar.iter().collect::<Vec<_>>();
+
+ for &node in &nodes {
+ let name = grammar[node].name.clone();
+ let rule = &grammar[node].rule;
+ match lower_enum(grammar, rule) {
+ Some(variants) => {
+ let enum_src = AstEnumSrc {
+ doc: Vec::new(),
+ name,
+ traits: Vec::new(),
+ variants,
+ };
+ res.enums.push(enum_src);
+ }
+ None => match lower_token_enum(grammar, rule) {
+ Some(variants) => {
+ let tokens_enum_src = AstTokenEnumSrc {
+ doc: Vec::new(),
+ name,
+ variants,
+ };
+ res.token_enums.push(tokens_enum_src);
+ }
+ None => {
+ let mut fields = Vec::new();
+ lower_rule(&mut fields, grammar, None, rule, false);
+ let mut types = HashMap::new();
+ for field in fields.iter().filter(|f| f.token_name().is_none()) {
+ if let Some(old) = types.insert(field.ty(), field.method_name(kinds)) {
+ panic!("{name}.{} has same type as {name}.{}, resolve conflict by wrapping one field: {}", old, field.method_name(kinds), field.ty());
+ }
+ }
+ res.nodes.push(AstNodeSrc {
+ doc: Vec::new(),
+ name,
+ traits: Vec::new(),
+ fields,
+ });
+ }
+ },
+ }
+ }
+
+ deduplicate_fields(&mut res);
+ extract_struct_traits(kinds, &mut res);
+ extract_enum_traits(&mut res);
+ res
+}
+
+fn lower_enum(grammar: &Grammar, rule: &Rule) -> Option<Vec<String>> {
+ let alternatives = match rule {
+ Rule::Alt(it) => it,
+ _ => return None,
+ };
+ let mut variants = Vec::new();
+ for alternative in alternatives {
+ match alternative {
+ Rule::Node(it) => variants.push(grammar[*it].name.clone()),
+ Rule::Token(it) if grammar[*it].name == ";" => (),
+ _ => return None,
+ }
+ }
+ Some(variants)
+}
+fn lower_token_enum(grammar: &Grammar, rule: &Rule) -> Option<Vec<String>> {
+ let alternatives = match rule {
+ Rule::Alt(it) => it,
+ _ => return None,
+ };
+ let mut variants = Vec::new();
+ for alternative in alternatives {
+ match alternative {
+ Rule::Token(it) => variants.push(grammar[*it].name.clone()),
+ _ => return None,
+ }
+ }
+ Some(variants)
+}
+
+fn lower_rule(
+ acc: &mut Vec<Field>,
+ grammar: &Grammar,
+ label: Option<&String>,
+ rule: &Rule,
+ in_optional: bool,
+) {
+ if lower_comma_list(acc, grammar, label, rule) {
+ return;
+ }
+
+ match rule {
+ Rule::Node(node) => {
+ let ty = grammar[*node].name.clone();
+ let name = label.cloned().unwrap_or_else(|| to_lower_snake_case(&ty));
+ let field = Field::Node {
+ name,
+ ty,
+ cardinality: if in_optional {
+ Cardinality::Optional
+ } else {
+ Cardinality::Required
+ },
+ };
+ acc.push(field);
+ }
+ Rule::Token(token) => {
+ assert!(label.is_none(), "uexpected label: {:?}", label);
+ let name = grammar[*token].name.clone();
+ let field = Field::Token(name);
+ acc.push(field);
+ }
+ Rule::Rep(inner) => {
+ if let Rule::Node(node) = &**inner {
+ let ty = grammar[*node].name.clone();
+ let name = label
+ .cloned()
+ .unwrap_or_else(|| pluralize(&to_lower_snake_case(&ty)));
+ let field = Field::Node {
+ name,
+ ty,
+ cardinality: Cardinality::Many,
+ };
+ acc.push(field);
+ return;
+ }
+ todo!("unsupported repitition: {:?}", rule)
+ }
+ Rule::Labeled { label: l, rule } => {
+ assert!(label.is_none());
+ lower_rule(acc, grammar, Some(l), rule, in_optional);
+ }
+ Rule::Seq(rules) | Rule::Alt(rules) => {
+ for rule in rules {
+ lower_rule(acc, grammar, label, rule, in_optional)
+ }
+ }
+ Rule::Opt(rule) => lower_rule(acc, grammar, label, rule, true),
+ }
+}
+
+// (T (',' T)* ','?)
+fn lower_comma_list(
+ acc: &mut Vec<Field>,
+ grammar: &Grammar,
+ label: Option<&String>,
+ rule: &Rule,
+) -> bool {
+ let rule = match rule {
+ Rule::Seq(it) => it,
+ _ => return false,
+ };
+ let (node, repeat, trailing_comma) = match rule.as_slice() {
+ [Rule::Node(node), Rule::Rep(repeat), Rule::Opt(trailing_comma)] => {
+ (node, repeat, trailing_comma)
+ }
+ _ => return false,
+ };
+ let repeat = match &**repeat {
+ Rule::Seq(it) => it,
+ _ => return false,
+ };
+ match repeat.as_slice() {
+ [comma, Rule::Node(n)] if comma == &**trailing_comma && n == node => (),
+ _ => return false,
+ }
+ let ty = grammar[*node].name.clone();
+ let name = label
+ .cloned()
+ .unwrap_or_else(|| pluralize(&to_lower_snake_case(&ty)));
+ let field = Field::Node {
+ name,
+ ty,
+ cardinality: Cardinality::Many,
+ };
+ acc.push(field);
+ true
+}
+
+fn deduplicate_fields(ast: &mut AstSrc) {
+ for node in &mut ast.nodes {
+ let mut i = 0;
+ 'outer: while i < node.fields.len() {
+ for j in 0..i {
+ let f1 = &node.fields[i];
+ let f2 = &node.fields[j];
+ if f1 == f2 {
+ node.fields.remove(i);
+ continue 'outer;
+ }
+ }
+ i += 1;
+ }
+ }
+}
+
+fn extract_struct_traits(kinds: &KindsSrc, ast: &mut AstSrc) {
+ // TODO: add common accessor traits here.
+ let traits: &[(&str, &[&str])] = &[];
+
+ for node in &mut ast.nodes {
+ for (name, methods) in traits {
+ extract_struct_trait(kinds, node, name, methods);
+ }
+ }
+}
+
+fn extract_struct_trait(
+ kinds: &KindsSrc,
+ node: &mut AstNodeSrc,
+ trait_name: &str,
+ methods: &[&str],
+) {
+ let mut to_remove = Vec::new();
+ for (i, field) in node.fields.iter().enumerate() {
+ let method_name = field.method_name(kinds).to_string();
+ if methods.iter().any(|&it| it == method_name) {
+ to_remove.push(i);
+ }
+ }
+ if to_remove.len() == methods.len() {
+ node.traits.push(trait_name.to_string());
+ node.remove_field(to_remove);
+ }
+}
+
+fn extract_enum_traits(ast: &mut AstSrc) {
+ let enums = ast.enums.clone();
+ for enm in &mut ast.enums {
+ let nodes = &ast.nodes;
+
+ let mut variant_traits = enm.variants.iter().map(|var| {
+ nodes
+ .iter()
+ .find_map(|node| {
+ if &node.name != var {
+ return None;
+ }
+ Some(node.traits.iter().cloned().collect::<BTreeSet<_>>())
+ })
+ .unwrap_or_else(|| {
+ enums
+ .iter()
+ .find_map(|node| {
+ if &node.name != var {
+ return None;
+ }
+ Some(node.traits.iter().cloned().collect::<BTreeSet<_>>())
+ })
+ .unwrap_or_else(|| {
+ panic!("could not find struct {var} for enum {}::{var}", enm.name)
+ })
+ })
+ });
+
+ let mut enum_traits = match variant_traits.next() {
+ Some(it) => it,
+ None => continue,
+ };
+ for traits in variant_traits {
+ enum_traits = enum_traits.intersection(&traits).cloned().collect();
+ }
+ enm.traits = enum_traits.into_iter().collect();
+ }
+}
xtask/src/sourcegen/kinds.rsdiffbeforeafterboth--- /dev/null
+++ b/xtask/src/sourcegen/kinds.rs
@@ -0,0 +1,274 @@
+#[derive(Debug)]
+pub struct KindsSrc {
+ /// Key - how this token appears in ungrammar
+ defined_tokens: IndexMap<String, TokenKind>,
+ defined_node_names: HashSet<String>,
+ pub nodes: Vec<String>,
+}
+
+#[derive(Debug, Clone)]
+pub enum TokenKind {
+ /// May exist in token tree, but never in source code
+ Meta { grammar_name: String, name: String },
+ /// Specific parsing errors may be emitted as this type of kind
+ Error {
+ grammar_name: String,
+ name: String,
+ regex: Option<String>,
+ priority: Option<u32>,
+ },
+ /// Keyword - literal match of token
+ Keyword {
+ /// How this keyword appears in grammar/code, should be same as Kinds key
+ code: String,
+ name: String,
+ },
+ /// Literal - something defined by user, i.e strings, identifiers, smth
+ Literal {
+ /// How this keyword appears in grammar, should be same as Kinds key
+ grammar_name: String,
+ name: String,
+ /// Regex for Logos lexer
+ regex: String,
+ /// Path to custom lexer
+ lexer: Option<String>,
+ },
+}
+
+impl TokenKind {
+ pub fn grammar_name(&self) -> &str {
+ match self {
+ TokenKind::Keyword { code, .. } => code,
+ TokenKind::Literal { grammar_name, .. } => grammar_name,
+ TokenKind::Meta { grammar_name, .. } => grammar_name,
+ TokenKind::Error { grammar_name, .. } => grammar_name,
+ }
+ }
+ /// How this keyword should appear in kinds enum, screaming snake cased
+ pub fn name(&self) -> &str {
+ match self {
+ TokenKind::Keyword { name, .. } => name,
+ TokenKind::Literal { name, .. } => name,
+ TokenKind::Meta { name, .. } => name,
+ TokenKind::Error { name, .. } => name,
+ }
+ }
+ pub fn expand_kind(&self) -> TokenStream {
+ let name = format_ident!("{}", self.name());
+ let attr = match self {
+ TokenKind::Keyword { code, .. } => quote! {#[token(#code)]},
+ TokenKind::Literal { regex, lexer, .. } => {
+ let lexer = lexer
+ .as_deref()
+ .map(TokenStream::from_str)
+ .map(|r| r.expect("path is correct"));
+ quote! {#[regex(#regex, #lexer)]}
+ }
+ TokenKind::Error {
+ regex, priority, ..
+ } if regex.is_some() => {
+ let priority = priority.map(|p| quote! {, priority = #p});
+ quote! {#[regex(#regex #priority)]}
+ }
+ _ => quote! {},
+ };
+ quote! {
+ #attr
+ #name
+ }
+ }
+ pub fn expand_t_macros(&self) -> Option<TokenStream> {
+ match self {
+ TokenKind::Keyword { code, name } => {
+ let code = escape_token_macro(code);
+ let name = format_ident!("{name}");
+ Some(quote! {
+ [#code] => {$crate::SyntaxKind::#name}
+ })
+ }
+ // Meta items should not appear in T![_]
+ _ => None,
+ }
+ }
+
+ /// How this token should be referenced in code
+ /// Keywords are referenced with `T![_]` macro,
+ /// and literals are referenced directly by name
+ pub fn reference(&self) -> TokenStream {
+ match self {
+ TokenKind::Keyword { code, .. } => {
+ let code = escape_token_macro(code);
+ quote! {T![#code]}
+ }
+ _ => {
+ let name = self.name();
+ let ident = format_ident!("{name}");
+ quote! {#ident}
+ }
+ }
+ }
+
+ pub fn method_name(&self) -> Ident {
+ match self {
+ TokenKind::Keyword { name, .. } => {
+ format_ident!("{}_token", name.to_lowercase())
+ }
+ TokenKind::Literal { name, .. } => {
+ format_ident!("{}_lit", name.to_lowercase())
+ }
+ TokenKind::Meta { name, .. } => format_ident!("{}_meta", name.to_lowercase()),
+ TokenKind::Error { name, .. } => format_ident!("{}_error", name.to_lowercase()),
+ }
+ }
+}
+
+#[macro_export]
+macro_rules! define_kinds {
+ ($into:ident = lit($name:literal) => $regex:literal $(, $lexer:literal)? $(; $($rest:tt)*)?) => {{
+ $into.define_token(TokenKind::Literal {
+ grammar_name: format!("LIT_{}!", $name),
+ name: $name.to_owned(),
+ regex: $regex.to_owned(),
+ lexer: None $(.or_else(|| Some($lexer.to_string())))?,
+ });
+ $(define_kinds!($into = $($rest)*))?
+ }};
+ ($into:ident = error($name:literal$(, priority = $priority:literal)?) $(=> $regex:literal)? $(; $($rest:tt)*)?) => {{
+ $into.define_token(TokenKind::Error {
+ grammar_name: format!("ERROR_{}!", $name),
+ name: format!("ERROR_{}", $name),
+ regex: None$(.or(Some($regex.to_owned())))?,
+ priority: None$(.or(Some($priority)))?,
+ });
+ $(define_kinds!($into = $($rest)*))?
+ }};
+ ($into:ident = $tok:literal => $name:literal $(; $($rest:tt)*)?) => {{
+ $into.define_token(TokenKind::Keyword {
+ code: format!("{}", $tok),
+ name: $name.to_owned(),
+ });
+ $(define_kinds!($into = $($rest)*))?
+ }};
+ ($into:ident =) => {{}}
+}
+use std::{collections::HashSet, str::FromStr};
+
+pub use define_kinds;
+use indexmap::IndexMap;
+use proc_macro2::{Ident, TokenStream};
+use quote::{format_ident, quote};
+
+use super::escape_token_macro;
+
+impl KindsSrc {
+ pub fn new() -> Self {
+ Self {
+ defined_tokens: IndexMap::new(),
+ defined_node_names: HashSet::new(),
+ nodes: Vec::new(),
+ }
+ }
+ pub fn define_token(&mut self, token: TokenKind) {
+ assert!(
+ self.defined_node_names.insert(token.name().to_owned()),
+ "node name already defined: {}",
+ token.name()
+ );
+ assert!(
+ self.defined_tokens
+ .insert(token.grammar_name().to_owned(), token.clone())
+ .is_none(),
+ "token already defined: {}",
+ token.grammar_name()
+ )
+ }
+ pub fn define_node(&mut self, node: &str) {
+ assert!(
+ self.defined_node_names.insert(node.to_owned()),
+ "node name already defined: {}",
+ node
+ );
+ self.nodes.push(node.to_string())
+ }
+ pub fn token(&self, tok: &str) -> Option<&TokenKind> {
+ self.defined_tokens.get(tok)
+ }
+ pub fn is_token(&self, tok: &str) -> bool {
+ self.defined_tokens.contains_key(tok)
+ }
+ pub fn tokens(&self) -> impl Iterator<Item = &TokenKind> {
+ self.defined_tokens.iter().map(|(_, v)| v)
+ }
+}
+
+pub fn jsonnet_kinds() -> KindsSrc {
+ let mut kinds = KindsSrc::new();
+ define_kinds![kinds =
+ "||" => "OR";
+ "&&" => "AND";
+ "|" => "BIT_OR";
+ "^" => "BIT_XOR";
+ "&" => "BIT_AND";
+ "==" => "EQ";
+ "!=" => "NE";
+ "<" => "LT";
+ ">" => "GT";
+ "<=" => "LE";
+ ">=" => "GE";
+ "<<" => "LHS";
+ ">>" => "RHS";
+ "+" => "PLUS";
+ "-" => "MINUS";
+ "*" => "MUL";
+ "/" => "DIV";
+ "%" => "MODULO";
+ "!" => "NOT";
+ "~" => "BIT_NOT";
+ "[" => "L_BRACK";
+ "]" => "R_BRACK";
+ "(" => "L_PAREN";
+ ")" => "R_PAREN";
+ "{" => "L_BRACE";
+ "}" => "R_BRACE";
+ ":" => "COLON";
+ "::" => "COLONCOLON";
+ ":::" => "COLONCOLONCOLON";
+ ";" => "SEMI";
+ "." => "DOT";
+ "..." => "DOTDOTDOT";
+ "," => "COMMA";
+ "$" => "DOLLAR";
+ "=" => "ASSIGN";
+ "?" => "QUESTION_MARK";
+ "$intrinsicThisFile" => "INTRINSIC_THIS_FILE";
+ "$intrinsicId" => "INTRINSIC_ID";
+ "$intrinsic" => "INTRINSIC";
+ // Literals
+ lit("FLOAT") => r"(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?";
+ error("FLOAT_JUNK_AFTER_POINT") => r"(?:0|[1-9][0-9]*)\.[^0-9]";
+ error("FLOAT_JUNK_AFTER_EXPONENT") => r"(?:0|[1-9][0-9]*)(?:\.[0-9]+)?[eE][^+\-0-9]";
+ error("FLOAT_JUNK_AFTER_EXPONENT_SIGN") => r"(?:0|[1-9][0-9]*)(?:\.[0-9]+)?[eE][+-][^0-9]";
+ lit("STRING_DOUBLE") => "\"(?s:[^\"\\\\]|\\\\.)*\"";
+ error("STRING_DOUBLE_UNTERMINATED") => "\"(?s:[^\"\\\\]|\\\\.)*";
+ lit("STRING_SINGLE") => "'(?s:[^'\\\\]|\\\\.)*'";
+ error("STRING_SINGLE_UNTERMINATED") => "'(?s:[^'\\\\]|\\\\.)*";
+ lit("STRING_DOUBLE_VERBATIM") => "@\"(?:[^\"]|\"\")*\"";
+ error("STRING_DOUBLE_VERBATIM_UNTERMINATED") => "@\"(?:[^\"]|\"\")*";
+ lit("STRING_SINGLE_VERBATIM") => "@'(?:[^']|'')*'";
+ error("STRING_SINGLE_VERBATIM_UNTERMINATED") => "@'(?:[^']|'')*";
+ error("STRING_VERBATIM_MISSING_QUOTES") => "@[^\"'\\s]\\S+";
+ lit("STRING_BLOCK") => r"\|\|\|", "crate::string_block::lex_str_block_test";
+ error("STRING_BLOCK_UNEXPECTED_END");
+ error("STRING_BLOCK_MISSING_NEW_LINE");
+ error("STRING_BLOCK_MISSING_TERMINATION");
+ error("STRING_BLOCK_MISSING_INDENT");
+ lit("IDENT") => r"[_a-zA-Z][_a-zA-Z0-9]*";
+ lit("WHITESPACE") => r"[ \t\n\r]+";
+ lit("SINGLE_LINE_SLASH_COMMENT") => r"//[^\r\n]*(\r\n|\n)?";
+ lit("SINGLE_LINE_HASH_COMMENT") => r"#[^\r\n]*(\r\n|\n)?";
+ lit("MULTI_LINE_COMMENT") => r"/\*([^*]|\*[^/])*\*/";
+ error("COMMENT_TOO_SHORT") => r"/\*/";
+ error("COMMENT_UNTERMINATED") => r"/\*([^*]|\*[^/])+";
+ ];
+ kinds
+}
xtask/src/sourcegen/mod.rsdiffbeforeafterboth--- a/xtask/src/sourcegen/mod.rs
+++ b/xtask/src/sourcegen/mod.rs
@@ -1,22 +1,36 @@
-use std::{
- collections::{BTreeSet, HashSet},
- path::PathBuf,
-};
+use std::path::PathBuf;
use anyhow::Result;
-use ast::{AstEnumSrc, AstNodeSrc, AstSrc, Cardinality, Field};
+use ast::{lower, AstSrc};
use itertools::Itertools;
+use kinds::{KindsSrc, TokenKind};
use proc_macro2::{Punct, Spacing, TokenStream};
use quote::{format_ident, quote};
-use ungrammar::{Grammar, Rule};
-use util::{
- ensure_file_contents, pluralize, reformat, to_lower_snake_case, to_pascal_case,
- to_upper_snake_case,
-};
+use ungrammar::Grammar;
+use util::{ensure_file_contents, reformat, to_pascal_case, to_upper_snake_case};
mod ast;
+mod kinds;
mod util;
+enum SpecialName {
+ Literal,
+ Meta,
+ Error,
+}
+fn classify_special(name: &str) -> Option<(SpecialName, &str)> {
+ let name = name.strip_suffix('!')?;
+ Some(if let Some(name) = name.strip_prefix("LIT_") {
+ (SpecialName::Literal, name)
+ } else if let Some(name) = name.strip_prefix("META_") {
+ (SpecialName::Meta, name)
+ } else if let Some(name) = name.strip_prefix("ERROR_") {
+ (SpecialName::Error, name)
+ } else {
+ return None;
+ })
+}
+
pub fn generate_ungrammar() -> Result<()> {
let grammar: Grammar = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
@@ -24,93 +38,51 @@
))
.parse()?;
- let mut kinds: KindsSrc = KindsSrc {
- punct: puncts![
- "||" => "OR";
- "&&" => "AND";
- "|" => "BIT_OR";
- "^" => "BIT_XOR";
- "&" => "BIT_AND";
- "==" => "EQ";
- "!=" => "NE";
- "<" => "LT";
- ">" => "GT";
- "<=" => "LE";
- ">=" => "GE";
- "<<" => "LHS";
- ">>" => "RHS";
- "+" => "PLUS";
- "-" => "MINUS";
- "*" => "MUL";
- "/" => "DIV";
- "%" => "MODULO";
- "!" => "NOT";
- "~" => "BIT_NOT";
- "[" => "L_BRACK";
- "]" => "R_BRACK";
- "(" => "L_PAREN";
- ")" => "R_PAREN";
- "{" => "L_BRACE";
- "}" => "R_BRACE";
- ":" => "COLON";
- "::" => "COLONCOLON";
- ":::" => "COLONCOLONCOLON";
- ";" => "SEMI";
- "." => "DOT";
- "..." => "DOTDOTDOT";
- "," => "COMMA";
- "$" => "DOLLAR";
- "=" => "ASSIGN";
- "?" => "QUESTION_MARK";
- "$intrinsicThisFile" => "INTRINSIC_THIS_FILE";
- "$intrinsicId" => "INTRINSIC_ID";
- "$intrinsic" => "INTRINSIC";
- ],
- keywords: vec![],
- literals: literals![
- "NUMBER" => r"(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?";
- "STRING_DOUBLE" => "\"(?s:[^\"\\\\]|\\\\.)*\"";
- "STRING_SINGLE" => "'(?s:[^'\\\\]|\\\\.)*'";
- "STRING_DOUBLE_VERBATIM" => "@\"(?:[^\"]|\"\")*\"";
- "STRING_SINGLE_VERBATIM" => "@'(?:[^']|'')*'";
- "STRING_BLOCK" => r"\|\|\|";
-
- "IDENT" => r"[_a-zA-Z][_a-zA-Z0-9]*";
- "WHITESPACE" => r"[ \t\n\r]+";
- "SINGLE_LINE_SLASH_COMMENT" => r"//[^\r\n]*(\r\n|\n)?";
- "SINGLE_LINE_HASH_COMMENT" => r"#[^\r\n]*(\r\n|\n)?";
- "MULTI_LINE_COMMENT" => r"/\*([^*]|\*[^/])*\*/";
- ],
- nodes: vec![],
- };
-
+ let mut kinds = kinds::jsonnet_kinds();
let ast = lower(&kinds, &grammar);
+ for token in grammar.tokens() {
+ let token = &grammar[token];
+ let token = &token.name.clone();
+ if !kinds.is_token(token) {
+ if let Some((special, name)) = classify_special(token) {
+ match special {
+ SpecialName::Literal => panic!("literal is not defined: {name}"),
+ SpecialName::Meta => kinds.define_token(TokenKind::Meta {
+ grammar_name: token.to_owned(),
+ name: format!("META_{}", name),
+ }),
+ SpecialName::Error => kinds.define_token(TokenKind::Error {
+ grammar_name: token.to_owned(),
+ name: format!("ERROR_{}", name),
+ regex: None,
+ priority: None,
+ }),
+ };
+ continue;
+ };
+ let name = to_upper_snake_case(token);
+ kinds.define_token(TokenKind::Keyword {
+ code: token.to_owned(),
+ name: format!("{name}_KW"),
+ });
+ }
+ }
for node in &ast.nodes {
let name = to_upper_snake_case(&node.name);
- if !kinds.is_literal(&name) {
- kinds.nodes.push(name);
- }
+ kinds.define_node(&name);
}
for enum_ in &ast.enums {
let name = to_upper_snake_case(&enum_.name);
- if !kinds.is_literal(&name) {
- kinds.nodes.push(name);
- }
+ kinds.define_node(&name);
}
- for token in grammar.tokens() {
- let token = &grammar[token];
- let token = &token.name.clone();
- let name = to_upper_snake_case(token);
- if !kinds.is_punct(token) && !kinds.is_literal(&name) {
- kinds.keywords.push(token.to_owned());
- }
+ for token_enum in &ast.token_enums {
+ let name = to_upper_snake_case(&token_enum.name);
+ kinds.define_node(&name);
}
- let syntax_kinds = generate_syntax_kinds(&kinds)?;
+ let syntax_kinds = generate_syntax_kinds(&kinds, &ast)?;
- let tokens = generate_tokens(&ast)?;
-
let nodes = generate_nodes(&kinds, &ast)?;
ensure_file_contents(
&PathBuf::from(concat!(
@@ -118,13 +90,6 @@
"/../crates/jrsonnet-rowan-parser/src/generated/syntax_kinds.rs",
)),
&syntax_kinds,
- )?;
- ensure_file_contents(
- &PathBuf::from(concat!(
- env!("CARGO_MANIFEST_DIR"),
- "/../crates/jrsonnet-rowan-parser/src/generated/tokens.rs",
- )),
- &tokens,
)?;
ensure_file_contents(
&PathBuf::from(concat!(
@@ -134,123 +99,37 @@
&nodes,
)?;
Ok(())
-}
-
-fn generate_tokens(grammar: &AstSrc) -> Result<String> {
- let tokens = grammar.tokens.iter().map(|token| {
- let name = format_ident!("{}", token);
- let kind = format_ident!("{}", to_upper_snake_case(token));
- quote! {
- #[derive(Debug, Clone, PartialEq, Eq, Hash)]
- pub struct #name {
- pub(crate) syntax: SyntaxToken,
- }
- impl std::fmt::Display for #name {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- std::fmt::Display::fmt(&self.syntax, f)
- }
- }
- impl AstToken for #name {
- fn can_cast(kind: SyntaxKind) -> bool { kind == #kind }
- fn cast(syntax: SyntaxToken) -> Option<Self> {
- if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
- }
- fn syntax(&self) -> &SyntaxToken { &self.syntax }
- }
- }
- });
-
- Ok(reformat(
- "e! {
- use crate::{SyntaxKind::{self, *}, SyntaxToken, ast::AstToken};
- #(#tokens)*
- }
- .to_string(),
- )?
- .replace("#[derive", "\n#[derive"))
}
-fn generate_syntax_kinds(grammar: &KindsSrc) -> Result<String> {
- let (single_byte_tokens_values, single_byte_tokens): (Vec<_>, Vec<_>) = grammar
- .punct
- .iter()
- .filter(|(token, _name)| token.len() == 1)
- .map(|(token, name)| (token.chars().next().unwrap(), format_ident!("{}", name)))
- .unzip();
+fn generate_syntax_kinds(kinds: &KindsSrc, grammar: &AstSrc) -> Result<String> {
+ let t_macros = kinds.tokens().filter_map(TokenKind::expand_t_macros);
+ let token_kinds = kinds.tokens().map(TokenKind::expand_kind);
- let punctuation_values = grammar
- .punct
- .iter()
- .map(|(token, _name)| escape_token_macro(token));
- let punctuation = grammar
- .punct
- .iter()
- .map(|(_token, name)| format_ident!("{}", name))
- .collect::<Vec<_>>();
- let punctuation_enum = grammar
- .punct
- .iter()
- .map(|(token, name)| {
- let id = format_ident!("{}", name);
- quote! {
- #[token(#token)]
- #id
- }
- })
- .collect::<Vec<_>>();
+ let keywords = kinds
+ .tokens()
+ .filter(|k| matches!(k, TokenKind::Keyword { .. }))
+ .map(TokenKind::name)
+ .map(|n| format_ident!("{n}"));
- let x = |name: &str| format_ident!("{}_KW", to_upper_snake_case(name));
- let full_keywords_values = &grammar.keywords;
- let full_keywords = full_keywords_values.iter().map(|s| x(s.as_str()));
-
- let all_keywords_values = grammar.keywords.to_vec();
- let all_keywords_idents = all_keywords_values.iter().map(|kw| format_ident!("{}", kw));
- let all_keywords = all_keywords_values
+ let nodes = kinds
+ .nodes
.iter()
- .map(|s| x(&**s))
+ .map(|name| format_ident!("{}", name))
.collect::<Vec<_>>();
- let all_keywords_enum = all_keywords_values
- .iter()
- .map(|s| {
- let id = x(&**s);
- quote! {
- #[token(#s)]
- #id
- }
- })
- .collect::<Vec<_>>();
- let tokens_enum = grammar
- .literals
+ let enums = grammar
+ .enums
.iter()
- .map(|l| {
- let regex = &l.regex;
- let id = format_ident!("{}", l.name);
- let lexer = l
- .lexer
- .as_ref()
- .map(|l| {
- let id: TokenStream = l.parse().expect("path");
- quote! {
- , #id
- }
- })
- .unwrap_or_else(|| quote! {});
- quote! {
- #[regex(#regex #lexer)]
- #id
- }
- })
- .collect::<Vec<_>>();
-
- let nodes = grammar
- .nodes
- .iter()
- .map(|name| format_ident!("{}", name))
- .collect::<Vec<_>>();
+ .map(|e| format_ident!("{}", to_upper_snake_case(&e.name)))
+ .chain(
+ grammar
+ .token_enums
+ .iter()
+ .map(|e| format_ident!("{}", to_upper_snake_case(&e.name))),
+ );
let ast = quote! {
- #![allow(bad_style, missing_docs, unreachable_pub)]
+ #![allow(bad_style, missing_docs, unreachable_pub, clippy::manual_non_exhaustive, clippy::match_like_matches_macro)]
use logos::Logos;
/// The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT`.
@@ -261,9 +140,7 @@
TOMBSTONE,
#[doc(hidden)]
EOF,
- #(#punctuation_enum,)*
- #(#all_keywords_enum,)*
- #(#tokens_enum,)*
+ #(#token_kinds,)*
#[error]
ERROR,
#(#nodes,)*
@@ -275,32 +152,15 @@
impl SyntaxKind {
pub fn is_keyword(self) -> bool {
match self {
- #(#all_keywords)|* => true,
+ #(#keywords)|* => true,
_ => false,
}
}
-
- pub fn is_punct(self) -> bool {
+ pub fn is_enum(self) -> bool {
match self {
- #(#punctuation)|* => true,
+ #(#enums)|* => true,
_ => false,
}
- }
-
- pub fn from_keyword(ident: &str) -> Option<SyntaxKind> {
- let kw = match ident {
- #(#full_keywords_values => #full_keywords,)*
- _ => return None,
- };
- Some(kw)
- }
-
- pub fn from_char(c: char) -> Option<SyntaxKind> {
- let tok = match c {
- #(#single_byte_tokens_values => #single_byte_tokens,)*
- _ => return None,
- };
- Some(tok)
}
pub fn from_raw(r: u16) -> Self {
@@ -313,71 +173,13 @@
}
#[macro_export]
- macro_rules! T {
- #([#punctuation_values] => { $crate::SyntaxKind::#punctuation };)*
- #([#all_keywords_idents] => { $crate::SyntaxKind::#all_keywords };)*
- [lifetime_ident] => { $crate::SyntaxKind::LIFETIME_IDENT };
- [ident] => { $crate::SyntaxKind::IDENT };
- [shebang] => { $crate::SyntaxKind::SHEBANG };
- }
+ macro_rules! T {#(#t_macros);*}
pub use T;
};
reformat(&ast.to_string())
-}
-
-pub struct KindsSrc {
- pub punct: Vec<(String, String)>,
- pub keywords: Vec<String>,
- pub literals: Vec<LiteralKind>,
- pub nodes: Vec<String>,
-}
-
-pub struct LiteralKind {
- name: String,
- regex: String,
- lexer: Option<String>,
-}
-
-#[macro_export]
-macro_rules! literals {
- ($($name:expr => $regex:expr $(, $lexer:expr)?);* $(;)?) => {
- vec![
- $(LiteralKind {
- name: $name.to_owned(),
- regex: $regex.to_owned(),
- lexer: None $(.or_else(|| Some($lexer.to_string())))?,
- }),*
- ]
- };
-}
-
-#[macro_export]
-macro_rules! puncts {
- ($($tok:expr => $name:expr);* $(;)?) => {
- vec![
- $(($tok.to_owned(), $name.to_owned())),*
- ]
- };
}
-use crate::{literals, puncts};
-
-impl KindsSrc {
- pub fn is_punct(&self, tok: &str) -> bool {
- self.punct.iter().any(|(t, _)| *t == tok)
- }
- pub fn is_literal(&self, tok: &str) -> bool {
- self.literals.iter().any(|l| l.name == tok)
- }
- fn get_punct_name(&self, tok: &str) -> Option<&str> {
- self.punct
- .iter()
- .find(|(t, _)| *t == tok)
- .map(|(_, n)| n.as_str())
- }
-}
-
fn generate_nodes(kinds: &KindsSrc, grammar: &AstSrc) -> Result<String> {
let (node_defs, node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar
.nodes
@@ -400,12 +202,18 @@
support::children(&self.syntax)
}
}
- } else if let Some(token_kind) = field.token_kind() {
+ } else if let Some(token_kind) = field.token_kind(kinds) {
quote! {
pub fn #method_name(&self) -> Option<#ty> {
support::token(&self.syntax, #token_kind)
}
}
+ } else if field.is_token_enum(grammar) {
+ quote! {
+ pub fn #method_name(&self) -> Option<#ty> {
+ support::token_child(&self.syntax)
+ }
+ }
} else {
quote! {
pub fn #method_name(&self) -> Option<#ty> {
@@ -513,6 +321,80 @@
})
.unzip();
+ let (token_enum_defs, token_enum_boilerplate_impls): (Vec<_>, Vec<_>) = grammar
+ .token_enums
+ .iter()
+ .map(|en| {
+ let variants: Vec<_> = en
+ .variants
+ .iter()
+ .map(|token| {
+ format_ident!(
+ "{}",
+ to_pascal_case(kinds.token(token).expect("token exists").name())
+ )
+ })
+ .collect();
+ let name = format_ident!("{}", en.name);
+ let kind_name = format_ident!("{}Kind", en.name);
+ let kinds: Vec<_> = variants
+ .iter()
+ .map(|name| format_ident!("{}", to_upper_snake_case(&name.to_string())))
+ .collect();
+
+ let ast_node = quote! {
+ impl AstToken for #name {
+ fn can_cast(kind: SyntaxKind) -> bool {
+ match kind {
+ #(#kinds)|* => true,
+ _ => false,
+ }
+ }
+ fn cast(syntax: SyntaxToken) -> Option<Self> {
+ let res = match syntax.kind() {
+ #(
+ #kinds => #name { syntax, kind: #kind_name::#variants },
+ )*
+ _ => return None,
+ };
+ Some(res)
+ }
+ fn syntax(&self) -> &SyntaxToken {
+ &self.syntax
+ }
+ }
+ };
+
+ (
+ quote! {
+ #[pretty_doc_comment_placeholder_workaround]
+ #[derive(Debug, Clone, PartialEq, Eq, Hash)]
+ pub struct #name { syntax: SyntaxToken, kind: #kind_name }
+
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+ pub enum #kind_name {
+ #(#variants,)*
+ }
+ },
+ quote! {
+ #ast_node
+
+ impl #name {
+ pub fn kind(&self) -> #kind_name {
+ self.kind
+ }
+ }
+
+ impl std::fmt::Display for #name {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+ }
+ },
+ )
+ })
+ .unzip();
+
let (any_node_defs, any_node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar
.nodes
.iter()
@@ -581,32 +463,22 @@
}
});
- let defined_nodes: HashSet<_> = node_names.collect();
-
- for node in kinds
- .nodes
- .iter()
- .map(|kind| to_pascal_case(kind))
- .filter(|name| !defined_nodes.iter().any(|&it| it == name))
- {
- drop(node)
- // FIXME: restore this
- // eprintln!("Warning: node {} not defined in ast source", node);
- }
-
let ast = quote! {
- #![allow(non_snake_case)]
+ #![allow(non_snake_case, clippy::match_like_matches_macro)]
+
use crate::{
SyntaxNode, SyntaxToken, SyntaxKind::{self, *},
- ast::{self, AstNode, AstChildren, support},
+ ast::{AstNode, AstToken, AstChildren, support},
T,
};
#(#node_defs)*
#(#enum_defs)*
+ #(#token_enum_defs)*
#(#any_node_defs)*
#(#node_boilerplate_impls)*
#(#enum_boilerplate_impls)*
+ #(#token_enum_boilerplate_impls)*
#(#any_node_boilerplate_impls)*
#(#display_impls)*
};
@@ -636,276 +508,6 @@
use std::fmt::Write;
for line in contents {
writeln!(dest, "///{}", line).unwrap();
- }
-}
-
-fn lower(kinds: &KindsSrc, grammar: &Grammar) -> AstSrc {
- let tokens = "Whitespace Comment String StringVerbantim StringBlock Number Ident"
- .split_ascii_whitespace()
- .map(|it| it.to_string())
- .collect::<Vec<_>>();
-
- let mut res = AstSrc {
- tokens,
- ..Default::default()
- };
-
- let nodes = grammar.iter().collect::<Vec<_>>();
-
- for &node in &nodes {
- let name = grammar[node].name.clone();
- let rule = &grammar[node].rule;
- match lower_enum(grammar, rule) {
- Some(variants) => {
- let enum_src = AstEnumSrc {
- doc: Vec::new(),
- name,
- traits: Vec::new(),
- variants,
- };
- res.enums.push(enum_src);
- }
- None => {
- let mut fields = Vec::new();
- lower_rule(&mut fields, grammar, None, rule);
- res.nodes.push(AstNodeSrc {
- doc: Vec::new(),
- name,
- traits: Vec::new(),
- fields,
- });
- }
- }
- }
-
- deduplicate_fields(&mut res);
- extract_enums(&mut res);
- extract_struct_traits(kinds, &mut res);
- extract_enum_traits(&mut res);
- res
-}
-
-fn lower_enum(grammar: &Grammar, rule: &Rule) -> Option<Vec<String>> {
- let alternatives = match rule {
- Rule::Alt(it) => it,
- _ => return None,
- };
- let mut variants = Vec::new();
- for alternative in alternatives {
- match alternative {
- Rule::Node(it) => variants.push(grammar[*it].name.clone()),
- Rule::Token(it) if grammar[*it].name == ";" => (),
- _ => return None,
- }
- }
- Some(variants)
-}
-
-fn lower_rule(acc: &mut Vec<Field>, grammar: &Grammar, label: Option<&String>, rule: &Rule) {
- if lower_comma_list(acc, grammar, label, rule) {
- return;
- }
-
- match rule {
- Rule::Node(node) => {
- let ty = grammar[*node].name.clone();
- let name = label.cloned().unwrap_or_else(|| to_lower_snake_case(&ty));
- let field = Field::Node {
- name,
- ty,
- cardinality: Cardinality::Optional,
- };
- acc.push(field);
- }
- Rule::Token(token) => {
- assert!(label.is_none(), "uexpected label: {:?}", label);
- let name = grammar[*token].name.clone();
- let field = Field::Token(name);
- acc.push(field);
- }
- Rule::Rep(inner) => {
- if let Rule::Node(node) = &**inner {
- let ty = grammar[*node].name.clone();
- let name = label
- .cloned()
- .unwrap_or_else(|| pluralize(&to_lower_snake_case(&ty)));
- let field = Field::Node {
- name,
- ty,
- cardinality: Cardinality::Many,
- };
- acc.push(field);
- return;
- }
- todo!("unsupported repitition: {:?}", rule)
- }
- Rule::Labeled { label: l, rule } => {
- assert!(label.is_none());
- lower_rule(acc, grammar, Some(l), rule);
- }
- Rule::Seq(rules) | Rule::Alt(rules) => {
- for rule in rules {
- lower_rule(acc, grammar, label, rule)
- }
- }
- Rule::Opt(rule) => lower_rule(acc, grammar, label, rule),
- }
-}
-
-// (T (',' T)* ','?)
-fn lower_comma_list(
- acc: &mut Vec<Field>,
- grammar: &Grammar,
- label: Option<&String>,
- rule: &Rule,
-) -> bool {
- let rule = match rule {
- Rule::Seq(it) => it,
- _ => return false,
- };
- let (node, repeat, trailing_comma) = match rule.as_slice() {
- [Rule::Node(node), Rule::Rep(repeat), Rule::Opt(trailing_comma)] => {
- (node, repeat, trailing_comma)
- }
- _ => return false,
- };
- let repeat = match &**repeat {
- Rule::Seq(it) => it,
- _ => return false,
- };
- match repeat.as_slice() {
- [comma, Rule::Node(n)] if comma == &**trailing_comma && n == node => (),
- _ => return false,
- }
- let ty = grammar[*node].name.clone();
- let name = label
- .cloned()
- .unwrap_or_else(|| pluralize(&to_lower_snake_case(&ty)));
- let field = Field::Node {
- name,
- ty,
- cardinality: Cardinality::Many,
- };
- acc.push(field);
- true
-}
-
-fn deduplicate_fields(ast: &mut AstSrc) {
- for node in &mut ast.nodes {
- let mut i = 0;
- 'outer: while i < node.fields.len() {
- for j in 0..i {
- let f1 = &node.fields[i];
- let f2 = &node.fields[j];
- if f1 == f2 {
- node.fields.remove(i);
- continue 'outer;
- }
- }
- i += 1;
- }
- }
-}
-
-fn extract_enums(ast: &mut AstSrc) {
- for node in &mut ast.nodes {
- for enm in &ast.enums {
- let mut to_remove = Vec::new();
- for (i, field) in node.fields.iter().enumerate() {
- let ty = field.ty().to_string();
- if enm.variants.iter().any(|it| it == &ty) {
- to_remove.push(i);
- }
- }
- if to_remove.len() == enm.variants.len() {
- node.remove_field(to_remove);
- let ty = enm.name.clone();
- let name = to_lower_snake_case(&ty);
- node.fields.push(Field::Node {
- name,
- ty,
- cardinality: Cardinality::Optional,
- });
- }
- }
- }
-}
-
-fn extract_struct_traits(kinds: &KindsSrc, ast: &mut AstSrc) {
- // TODO: add common accessor traits here.
- let traits: &[(&str, &[&str])] = &[];
-
- for node in &mut ast.nodes {
- for (name, methods) in traits {
- extract_struct_trait(kinds, node, name, methods);
- }
- }
-}
-
-fn extract_struct_trait(
- kinds: &KindsSrc,
- node: &mut AstNodeSrc,
- trait_name: &str,
- methods: &[&str],
-) {
- let mut to_remove = Vec::new();
- for (i, field) in node.fields.iter().enumerate() {
- let method_name = field.method_name(kinds).to_string();
- if methods.iter().any(|&it| it == method_name) {
- to_remove.push(i);
- }
- }
- if to_remove.len() == methods.len() {
- node.traits.push(trait_name.to_string());
- node.remove_field(to_remove);
- }
-}
-
-fn extract_enum_traits(ast: &mut AstSrc) {
- let enums = ast.enums.clone();
- for enm in &mut ast.enums {
- if enm.name == "Stmt" {
- continue;
- }
- let nodes = &ast.nodes;
-
- let mut variant_traits = enm.variants.iter().map(|var| {
- nodes
- .iter()
- .find_map(|node| {
- if &node.name != var {
- return None;
- }
- Some(node.traits.iter().cloned().collect::<BTreeSet<_>>())
- })
- .unwrap_or_else(|| {
- enums
- .iter()
- .find_map(|node| {
- if &node.name != var {
- return None;
- }
- Some(node.traits.iter().cloned().collect::<BTreeSet<_>>())
- })
- .unwrap_or_else(|| {
- panic!("{}", {
- &format!(
- "Could not find a struct `{}` for enum `{}::{}`",
- var, enm.name, var
- )
- })
- })
- })
- });
-
- let mut enum_traits = match variant_traits.next() {
- Some(it) => it,
- None => continue,
- };
- for traits in variant_traits {
- enum_traits = enum_traits.intersection(&traits).cloned().collect();
- }
- enm.traits = enum_traits.into_iter().collect();
}
}
xtask/src/sourcegen/util.rsdiffbeforeafterboth--- a/xtask/src/sourcegen/util.rs
+++ b/xtask/src/sourcegen/util.rs
@@ -1,6 +1,6 @@
use std::{fs, path::Path};
-use anyhow::{bail, Result};
+use anyhow::Result;
use xshell::{cmd, Shell};
/// Checks that the `file` has the specified `contents`. If that is not the
@@ -15,13 +15,13 @@
eprintln!(" {} was not up-to-date, updating\n", file.display());
if std::env::var("CI").is_ok() {
- eprintln!("NOTE: run `cargo test` locally and commit the updated files\n");
+ eprintln!("NOTE: run `cargo xtask` locally and commit the updated files\n");
}
if let Some(parent) = file.parent() {
let _ = fs::create_dir_all(parent);
}
fs::write(file, contents).unwrap();
- bail!("some file was not up to date and has been updated, simply re-run the tests");
+ Ok(())
}
// Eww, someone configured git to use crlf?
@@ -80,9 +80,7 @@
// let _e = pushenv("RUSTUP_TOOLCHAIN", "stable");
// rustfmt()?;
let sh = Shell::new()?;
- let stdout = cmd!(sh, "rustfmt --config fn_single_line=true")
- .stdin(text)
- .read()?;
+ let stdout = cmd!(sh, "rustfmt").stdin(text).read()?;
Ok(format!(
"{}\n\n{}\n",
"//! This is a generated file, please do not edit manually. Changes can be