--- /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" }
--- /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: {{
+ $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
Printable for Option
+where
+ P: Printable,
+{
+ fn print(&self) -> PrintItems {
+ if let Some(v) = self {
+ v.print()
+ } else {
+ p!(new: str(
+ &format!(
+ "/*missing {}*/",
+ type_name::
().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: {
+ 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: 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: 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: 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: {
+ p!(new: str("{") >i nl {o.obj_body()} {
+ 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: {
+ 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);
+}
--- 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" }
--- 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
--- 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
+ 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
+ where
+ Self: Sized;
+
+ fn syntax(&self) -> &SyntaxToken;
+
+ fn text(&self) -> &str {
+ self.syntax().text()
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct AstChildren {
+ inner: SyntaxNodeChildren,
+ ph: PhantomData,
+}
+
+impl AstChildren {
+ fn new(parent: &SyntaxNode) -> Self {
+ AstChildren {
+ inner: parent.children(),
+ ph: PhantomData,
+ }
+ }
+}
+
+impl Iterator for AstChildren {
+ type Item = N;
+ fn next(&mut self) -> Option {
+ self.inner.find_map(N::cast)
+ }
+}
+
+pub mod support {
+ use super::{AstChildren, AstNode, AstToken, SyntaxKind, SyntaxNode, SyntaxToken};
+
+ pub fn child(parent: &SyntaxNode) -> Option {
+ parent.children().find_map(N::cast)
+ }
+ pub fn token_child(parent: &SyntaxNode) -> Option {
+ parent.children_with_tokens().find_map(|n| match n {
+ rowan::NodeOrToken::Node(_) => None,
+ rowan::NodeOrToken::Token(t) => N::cast(t),
+ })
+ }
+
+ pub fn children(parent: &SyntaxNode) -> AstChildren {
+ AstChildren::new(parent)
+ }
+
+ pub fn token(parent: &SyntaxNode, kind: SyntaxKind) -> Option {
+ parent
+ .children_with_tokens()
+ .filter_map(|it| it.into_token())
+ .find(|it| it.kind() == kind)
+ }
+}
--- 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,
}
--- /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
+ )
+ }
+}
--- 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,
},
- Token,
- Finish,
- Placeholder,
+ /// Eat token
+ Token {
+ kind: SyntaxKind,
+ },
+ /// Position of finished node
+ Finish {
+ /// Same as forward_parent of Start, but for wrapping
+ wrapper: Option,
+ },
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);
}
}
}
--- 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;
--- 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 { support::child(&self.syntax) }
+ pub fn expr(&self) -> Option {
+ 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 { support::child(&self.syntax) }
- pub fn binary_operator(&self) -> Option { support::child(&self.syntax) }
- pub fn rhs(&self) -> Option { support::child(&self.syntax) }
+ pub fn lhs(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn binary_operator(&self) -> Option {
+ support::token_child(&self.syntax)
+ }
+ pub fn rhs(&self) -> Option {
+ 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 { support::token(&self.syntax, T![||]) }
- pub fn and_token(&self) -> Option { support::token(&self.syntax, T![&&]) }
- pub fn bit_or_token(&self) -> Option { support::token(&self.syntax, T![|]) }
- pub fn bit_xor_token(&self) -> Option { support::token(&self.syntax, T![^]) }
- pub fn bit_and_token(&self) -> Option { support::token(&self.syntax, T![&]) }
- pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![==]) }
- pub fn ne_token(&self) -> Option { support::token(&self.syntax, T![!=]) }
- pub fn lt_token(&self) -> Option { support::token(&self.syntax, T![<]) }
- pub fn gt_token(&self) -> Option { support::token(&self.syntax, T![>]) }
- pub fn le_token(&self) -> Option { support::token(&self.syntax, T![<=]) }
- pub fn ge_token(&self) -> Option { support::token(&self.syntax, T![>=]) }
- pub fn in_token(&self) -> Option { support::token(&self.syntax, T![in]) }
- pub fn lhs_token(&self) -> Option { support::token(&self.syntax, T![<<]) }
- pub fn rhs_token(&self) -> Option { support::token(&self.syntax, T![>>]) }
- pub fn plus_token(&self) -> Option { support::token(&self.syntax, T![+]) }
- pub fn minus_token(&self) -> Option { support::token(&self.syntax, T![-]) }
- pub fn mul_token(&self) -> Option { support::token(&self.syntax, T![*]) }
- pub fn div_token(&self) -> Option { support::token(&self.syntax, T![/]) }
- pub fn modulo_token(&self) -> Option { support::token(&self.syntax, T![%]) }
+impl LhsExpr {
+ pub fn expr(&self) -> Option {
+ 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 { support::child(&self.syntax) }
- pub fn rhs(&self) -> Option { support::child(&self.syntax) }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct UnaryOperator {
- pub(crate) syntax: SyntaxNode,
+ pub fn unary_operator(&self) -> Option {
+ support::token_child(&self.syntax)
+ }
+ pub fn rhs(&self) -> Option {
+ support::child(&self.syntax)
+ }
}
-impl UnaryOperator {
- pub fn minus_token(&self) -> Option { support::token(&self.syntax, T![-]) }
- pub fn not_token(&self) -> Option { support::token(&self.syntax, T![!]) }
- pub fn bit_not_token(&self) -> Option { 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 { support::child(&self.syntax) }
- pub fn l_brack_token(&self) -> Option { support::token(&self.syntax, T!['[']) }
- pub fn slice_desc(&self) -> Option { support::child(&self.syntax) }
- pub fn r_brack_token(&self) -> Option { support::token(&self.syntax, T![']']) }
+ pub fn expr(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn slice_desc(&self) -> Option {
+ 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 { support::child(&self.syntax) }
- pub fn colon_token(&self) -> Option { support::token(&self.syntax, T![:]) }
- pub fn end(&self) -> Option { support::child(&self.syntax) }
- pub fn step(&self) -> Option { support::child(&self.syntax) }
+ pub fn l_brack_token(&self) -> Option {
+ support::token(&self.syntax, T!['['])
+ }
+ pub fn from(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn colon_token(&self) -> Option {
+ support::token(&self.syntax, T![:])
+ }
+ pub fn end(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn step(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn r_brack_token(&self) -> Option {
+ 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 { support::child(&self.syntax) }
- pub fn dot_token(&self) -> Option { support::token(&self.syntax, T![.]) }
- pub fn index(&self) -> Option { support::child(&self.syntax) }
+ pub fn expr(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn dot_token(&self) -> Option {
+ support::token(&self.syntax, T![.])
+ }
+ pub fn index(&self) -> Option {
+ 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 { support::token(&self.syntax, T![ident]) }
+ pub fn ident_lit(&self) -> Option {
+ 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 { support::child(&self.syntax) }
- pub fn l_brack_token(&self) -> Option { support::token(&self.syntax, T!['[']) }
- pub fn index(&self) -> Option { support::child(&self.syntax) }
- pub fn r_brack_token(&self) -> Option { support::token(&self.syntax, T![']']) }
+ pub fn base(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn l_brack_token(&self) -> Option {
+ support::token(&self.syntax, T!['['])
+ }
+ pub fn index(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn r_brack_token(&self) -> Option {
+ 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 { support::child(&self.syntax) }
- pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) }
- pub fn args_desc(&self) -> Option { support::child(&self.syntax) }
- pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) }
- pub fn tailstrict_token(&self) -> Option {
+ pub fn expr(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn args_desc(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn tailstrict_kw_token(&self) -> Option {
support::token(&self.syntax, T![tailstrict])
}
}
@@ -141,7 +161,15 @@
pub(crate) syntax: SyntaxNode,
}
impl ArgsDesc {
- pub fn args(&self) -> AstChildren { support::children(&self.syntax) }
+ pub fn l_paren_token(&self) -> Option {
+ support::token(&self.syntax, T!['('])
+ }
+ pub fn args(&self) -> AstChildren {
+ support::children(&self.syntax)
+ }
+ pub fn r_paren_token(&self) -> Option {
+ 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 { support::child(&self.syntax) }
- pub fn l_brace_token(&self) -> Option { support::token(&self.syntax, T!['{']) }
- pub fn obj_body(&self) -> Option { support::child(&self.syntax) }
- pub fn r_brace_token(&self) -> Option { support::token(&self.syntax, T!['}']) }
+ pub fn lhs_expr(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn expr(&self) -> Option {
+ 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 { support::token(&self.syntax, T!['(']) }
- pub fn expr(&self) -> Option { support::child(&self.syntax) }
- pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) }
+ pub fn l_paren_token(&self) -> Option {
+ support::token(&self.syntax, T!['('])
+ }
+ pub fn expr(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn r_paren_token(&self) -> Option {
+ 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 { 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 { support::token(&self.syntax, T![null]) }
- pub fn true_token(&self) -> Option { support::token(&self.syntax, T![true]) }
- pub fn false_token(&self) -> Option { support::token(&self.syntax, T![false]) }
- pub fn self_token(&self) -> Option { support::token(&self.syntax, T![self]) }
- pub fn dollar_token(&self) -> Option { support::token(&self.syntax, T!['$']) }
- pub fn super_token(&self) -> Option { support::token(&self.syntax, T![super]) }
+ pub fn literal(&self) -> Option {
+ support::token_child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -214,9 +239,15 @@
pub fn intrinsic_token(&self) -> Option {
support::token(&self.syntax, T!["$intrinsic"])
}
- pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) }
- pub fn name(&self) -> Option { support::child(&self.syntax) }
- pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) }
+ pub fn l_paren_token(&self) -> Option {
+ support::token(&self.syntax, T!['('])
+ }
+ pub fn name(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn r_paren_token(&self) -> Option {
+ 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 { 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 {
- support::token(&self.syntax, T![string_double])
- }
- pub fn string_single_token(&self) -> Option {
- support::token(&self.syntax, T![string_single])
- }
- pub fn string_double_verbatim_token(&self) -> Option {
- support::token(&self.syntax, T![string_double_verbatim])
- }
- pub fn string_single_verbatim_token(&self) -> Option {
- support::token(&self.syntax, T![string_single_verbatim])
- }
- pub fn string_block_token(&self) -> Option {
- support::token(&self.syntax, T![string_block])
+ pub fn string(&self) -> Option {
+ support::token_child(&self.syntax)
}
}
@@ -254,25 +265,25 @@
pub(crate) syntax: SyntaxNode,
}
impl ExprNumber {
- pub fn number(&self) -> Option { support::child(&self.syntax) }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Number {
- pub(crate) syntax: SyntaxNode,
+ pub fn number(&self) -> Option {
+ support::token_child(&self.syntax)
+ }
}
-impl Number {
- pub fn number_token(&self) -> Option { 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 { support::token(&self.syntax, T!['[']) }
- pub fn exprs(&self) -> AstChildren { support::children(&self.syntax) }
- pub fn r_brack_token(&self) -> Option { support::token(&self.syntax, T![']']) }
+ pub fn l_brack_token(&self) -> Option {
+ support::token(&self.syntax, T!['['])
+ }
+ pub fn exprs(&self) -> AstChildren {
+ support::children(&self.syntax)
+ }
+ pub fn r_brack_token(&self) -> Option {
+ 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 { support::token(&self.syntax, T!['{']) }
- pub fn obj_body(&self) -> Option { support::child(&self.syntax) }
- pub fn r_brace_token(&self) -> Option { support::token(&self.syntax, T!['}']) }
+ pub fn l_brace_token(&self) -> Option {
+ support::token(&self.syntax, T!['{'])
+ }
+ pub fn obj_body(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn r_brace_token(&self) -> Option {
+ 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 { support::token(&self.syntax, T!['[']) }
- pub fn expr(&self) -> Option { support::child(&self.syntax) }
- pub fn comma_token(&self) -> Option { support::token(&self.syntax, T![,]) }
- pub fn for_spec(&self) -> Option { support::child(&self.syntax) }
- pub fn comp_specs(&self) -> AstChildren { support::children(&self.syntax) }
- pub fn r_brack_token(&self) -> Option { 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 {
+ support::token(&self.syntax, T!['['])
+ }
+ pub fn expr(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn comma_token(&self) -> Option {
+ support::token(&self.syntax, T![,])
+ }
+ pub fn comp_specs(&self) -> AstChildren {
+ support::children(&self.syntax)
+ }
+ pub fn r_brack_token(&self) -> Option {
+ support::token(&self.syntax, T![']'])
+ }
}
-impl ForSpec {
- pub fn for_token(&self) -> Option { support::token(&self.syntax, T![for]) }
- pub fn bind(&self) -> Option { support::child(&self.syntax) }
- pub fn in_token(&self) -> Option { support::token(&self.syntax, T![in]) }
- pub fn expr(&self) -> Option { 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 {
- support::token(&self.syntax, T![importstr])
+ pub fn import_kind(&self) -> Option {
+ support::token_child(&self.syntax)
}
- pub fn string(&self) -> Option { support::child(&self.syntax) }
- pub fn importbin_token(&self) -> Option {
- support::token(&self.syntax, T![importbin])
+ pub fn string(&self) -> Option {
+ support::token_child(&self.syntax)
}
- pub fn import_token(&self) -> Option { 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 { support::child(&self.syntax) }
+ pub fn name(&self) -> Option {
+ 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 { support::token(&self.syntax, T![local]) }
- pub fn binds(&self) -> AstChildren { support::children(&self.syntax) }
- pub fn semi_token(&self) -> Option { support::token(&self.syntax, T![;]) }
+ pub fn local_kw_token(&self) -> Option {
+ support::token(&self.syntax, T![local])
+ }
+ pub fn binds(&self) -> AstChildren {
+ support::children(&self.syntax)
+ }
+ pub fn semi_token(&self) -> Option {
+ support::token(&self.syntax, T![;])
+ }
+ pub fn expr(&self) -> Option {
+ 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 { support::token(&self.syntax, T![if]) }
- pub fn cond(&self) -> Option { support::child(&self.syntax) }
- pub fn then_token(&self) -> Option { support::token(&self.syntax, T![then]) }
- pub fn then(&self) -> Option { support::child(&self.syntax) }
- pub fn else_token(&self) -> Option { support::token(&self.syntax, T![else]) }
- pub fn else_(&self) -> Option { support::child(&self.syntax) }
+ pub fn if_kw_token(&self) -> Option {
+ support::token(&self.syntax, T![if])
+ }
+ pub fn cond(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn then_kw_token(&self) -> Option {
+ support::token(&self.syntax, T![then])
+ }
+ pub fn then(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn else_kw_token(&self) -> Option {
+ support::token(&self.syntax, T![else])
+ }
+ pub fn else_(&self) -> Option {
+ support::child(&self.syntax)
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct TrueExpr {
+ pub(crate) syntax: SyntaxNode,
+}
+impl TrueExpr {
+ pub fn expr(&self) -> Option {
+ support::child(&self.syntax)
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct FalseExpr {
+ pub(crate) syntax: SyntaxNode,
+}
+impl FalseExpr {
+ pub fn expr(&self) -> Option {
+ 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 {
+ pub fn function_kw_token(&self) -> Option {
support::token(&self.syntax, T![function])
}
- pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) }
- pub fn params_desc(&self) -> Option { support::child(&self.syntax) }
- pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) }
- pub fn expr(&self) -> Option { support::child(&self.syntax) }
+ pub fn l_paren_token(&self) -> Option {
+ support::token(&self.syntax, T!['('])
+ }
+ pub fn params_desc(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn r_paren_token(&self) -> Option {
+ support::token(&self.syntax, T![')'])
+ }
+ pub fn expr(&self) -> Option {
+ 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 { support::children(&self.syntax) }
+ pub fn l_paren_token(&self) -> Option {
+ support::token(&self.syntax, T!['('])
+ }
+ pub fn params(&self) -> AstChildren {
+ support::children(&self.syntax)
+ }
+ pub fn r_paren_token(&self) -> Option {
+ 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 { support::child(&self.syntax) }
- pub fn semi_token(&self) -> Option { support::token(&self.syntax, T![;]) }
- pub fn expr(&self) -> Option { support::child(&self.syntax) }
+ pub fn assertion(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn semi_token(&self) -> Option {
+ support::token(&self.syntax, T![;])
+ }
+ pub fn expr(&self) -> Option {
+ 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 { support::token(&self.syntax, T![assert]) }
- pub fn condition(&self) -> Option { support::child(&self.syntax) }
- pub fn colon_token(&self) -> Option { support::token(&self.syntax, T![:]) }
- pub fn expr(&self) -> Option { support::child(&self.syntax) }
+ pub fn assert_kw_token(&self) -> Option {
+ support::token(&self.syntax, T![assert])
+ }
+ pub fn condition(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn colon_token(&self) -> Option {
+ support::token(&self.syntax, T![:])
+ }
+ pub fn message(&self) -> Option {
+ 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 { support::token(&self.syntax, T![error]) }
- pub fn expr(&self) -> Option { support::child(&self.syntax) }
+ pub fn error_kw_token(&self) -> Option {
+ support::token(&self.syntax, T![error])
+ }
+ pub fn expr(&self) -> Option {
+ support::child(&self.syntax)
+ }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct SliceDescEnd {
+ pub(crate) syntax: SyntaxNode,
+}
+impl SliceDescEnd {
+ pub fn expr(&self) -> Option {
+ support::child(&self.syntax)
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct SliceDescStep {
+ pub(crate) syntax: SyntaxNode,
+}
+impl SliceDescStep {
+ pub fn expr(&self) -> Option {
+ support::child(&self.syntax)
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Arg {
pub(crate) syntax: SyntaxNode,
}
impl Arg {
- pub fn name(&self) -> Option { support::child(&self.syntax) }
- pub fn assign_token(&self) -> Option { support::token(&self.syntax, T![=]) }
- pub fn expr(&self) -> Option { support::child(&self.syntax) }
+ pub fn name(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn assign_token(&self) -> Option {
+ support::token(&self.syntax, T![=])
+ }
+ pub fn expr(&self) -> Option {
+ 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 { support::children(&self.syntax) }
- pub fn l_brack_token(&self) -> Option { support::token(&self.syntax, T!['[']) }
- pub fn key(&self) -> Option { support::child(&self.syntax) }
- pub fn r_brack_token(&self) -> Option { support::token(&self.syntax, T![']']) }
- pub fn plus_token(&self) -> Option { support::token(&self.syntax, T![+]) }
- pub fn colon_token(&self) -> Option { support::token(&self.syntax, T![:]) }
- pub fn value(&self) -> Option { support::child(&self.syntax) }
- pub fn post(&self) -> AstChildren { support::children(&self.syntax) }
- pub fn for_spec(&self) -> Option { support::child(&self.syntax) }
- pub fn comp_specs(&self) -> AstChildren { support::children(&self.syntax) }
+ pub fn pre(&self) -> AstChildren {
+ support::children(&self.syntax)
+ }
+ pub fn l_brack_token(&self) -> Option {
+ support::token(&self.syntax, T!['['])
+ }
+ pub fn key(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn r_brack_token(&self) -> Option {
+ support::token(&self.syntax, T![']'])
+ }
+ pub fn plus_token(&self) -> Option {
+ support::token(&self.syntax, T![+])
+ }
+ pub fn colon_token(&self) -> Option {
+ support::token(&self.syntax, T![:])
+ }
+ pub fn value(&self) -> Option {
+ support::child(&self.syntax)
+ }
+ pub fn post(&self) -> AstChildren