git.delta.rocks / jrsonnet / refs/commits / b99878e17f6e

difftreelog

fix(parser) move suffixes to expr_basic, function parsing BREAKING CHANGE: Renamed: Args => ArgsDesc Params => ParamsDesc

Лач2020-05-16parent: #9b267d5.patch.diff
in: master

2 files changed

modifiedcrates/jsonnet-parser/src/expr.rsdiffbeforeafterboth
before · crates/jsonnet-parser/src/expr.rs
1#[derive(Debug, Clone, PartialEq)]2pub enum FieldName {3	/// {fixed: 2}4	Fixed(String),5	/// {["dyn"+"amic"]: 3}6	Dyn(Box<Expr>),7}89#[derive(Debug, Clone, PartialEq)]10pub enum Visibility {11	/// :12	Normal,13	/// ::14	Hidden,15	/// :::16	Unhide,17}1819#[derive(Debug, Clone, PartialEq)]20pub struct AssertStmt(pub Box<Expr>, pub Option<Box<Expr>>);2122#[derive(Debug, Clone, PartialEq)]23pub enum FieldMember {24	Value {25		name: FieldName,26		plus: bool,27		visibility: Visibility,28		value: Expr,29	},30	Function {31		name: FieldName,32		params: Params,33		visibility: Visibility,34		value: Expr,35	},36}3738#[derive(Debug, Clone, PartialEq)]39pub enum Member {40	Field(FieldMember),41	BindStmt(Bind),42	AssertStmt(AssertStmt),43}4445#[derive(Debug, Clone, PartialEq)]46pub enum UnaryOpType {47	Plus,48	Minus,49	BitNot,50	Not,51}5253#[derive(Debug, Clone, PartialEq)]54pub enum BinaryOpType {55	Mul,56	Div,57	Mod,5859	Add,60	Sub,6162	Lhs,63	Rhs,6465	Lt,66	Gt,67	Lte,68	Gte,6970	In,7172	Eq,73	Ne,7475	BitAnd,76	BitOr,77	And,78	Or,7980	BitXor,81}8283#[derive(Debug, Clone, PartialEq)]84pub enum Param {85	Positional(String),86	Named(String, Box<Expr>),87}8889#[derive(Debug, Clone, PartialEq)]90pub struct Params(pub Vec<Param>);9192#[derive(Debug, Clone, PartialEq)]93pub enum Arg {94	Positional(Box<Expr>),95	Named(String, Box<Expr>),96}9798#[derive(Debug, Clone, PartialEq)]99pub struct Args(pub Vec<Arg>);100101#[derive(Debug, Clone, PartialEq)]102pub enum Bind {103	Value(String, Box<Expr>),104	Function(String, Params, Box<Expr>),105}106107#[derive(Debug, Clone, PartialEq)]108pub struct IfSpec(pub Box<Expr>);109#[derive(Debug, Clone, PartialEq)]110pub struct ForSpec(pub String, pub Vec<IfSpec>);111112#[derive(Debug, Clone, PartialEq)]113pub enum CompSpec {114	IfSpec(IfSpec),115	ForSpec(ForSpec),116}117118#[derive(Debug, Clone, PartialEq)]119pub enum ObjBody {120	MemberList(Vec<Member>),121	ObjComp {122		pre_locals: Vec<Bind>,123		key: Box<Expr>,124		value: Box<Expr>,125		post_locals: Vec<Bind>,126		first: ForSpec,127		rest: Vec<CompSpec>,128	},129}130131#[derive(Debug, Clone, PartialEq)]132pub enum ValueType {133	Null,134	True,135	False,136}137138#[derive(Debug, Clone, PartialEq)]139pub enum LiteralType {140	This,141	Super,142	Dollar,143}144145/// Syntax base146#[derive(Debug, Clone, PartialEq)]147pub enum Expr {148	Value(ValueType),149	/// Plain value: null/true/false150	Literal(LiteralType),151152	/// String value: "hello"153	Str(String),154	/// Number: 1, 2.0, 2e+20155	Num(f64),156	/// Variable name: test157	Var(String),158159	/// Array of expressions: [1, 2, "Hello"]160	Arr(Vec<Expr>),161	/// Array comprehension:162	/// ```jsonnet163	///  ingredients: [164	///    { kind: kind, qty: 4 / 3 }165	///    for kind in [166	///      'Honey Syrup',167	///      'Lemon Juice',168	///      'Farmers Gin',169	///    ]170	///  ],171	/// ```172	ArrComp(Box<Expr>, Vec<ForSpec>),173174	/// Object: {a: 2}175	Obj(ObjBody),176	/// Object extension: var1 {b: 2}177	ObjExtend(Box<Expr>, ObjBody),178179	/// (obj)180	Parened(Box<Expr>),181182	Params(Params),183	Args(Args),184185	UnaryOp(UnaryOpType, Box<Expr>),186	BinaryOp(Box<Expr>, BinaryOpType, Box<Expr>),187	AssertExpr(AssertStmt, Box<Expr>),188	LocalExpr(Vec<Bind>, Box<Expr>),189190	Bind(Bind),191	Import(String),192	ImportStr(String),193	Error(Box<Expr>),194	Apply(Box<Expr>, Args),195	Select(Box<Expr>, String),196	Index(Box<Expr>, Box<Expr>),197	Slice {198		value: Box<Expr>,199		start: Option<Box<Expr>>,200		end: Option<Box<Expr>>,201		step: Option<Box<Expr>>,202	},203	Function(Params, Box<Expr>),204	IfElse {205		cond: IfSpec,206		cond_then: Box<Expr>,207		cond_else: Option<Box<Expr>>,208	},209	IfSpec(IfSpec),210	ForSpec(ForSpec),211}
after · crates/jsonnet-parser/src/expr.rs
1#[derive(Debug, Clone, PartialEq)]2pub enum FieldName {3	/// {fixed: 2}4	Fixed(String),5	/// {["dyn"+"amic"]: 3}6	Dyn(Box<Expr>),7}89#[derive(Debug, Clone, PartialEq)]10pub enum Visibility {11	/// :12	Normal,13	/// ::14	Hidden,15	/// :::16	Unhide,17}1819#[derive(Debug, Clone, PartialEq)]20pub struct AssertStmt(pub Box<Expr>, pub Option<Box<Expr>>);2122#[derive(Debug, Clone, PartialEq)]23pub enum FieldMember {24	Value {25		name: FieldName,26		plus: bool,27		visibility: Visibility,28		value: Expr,29	},30	Function {31		name: FieldName,32		params: ParamsDesc,33		visibility: Visibility,34		value: Expr,35	},36}3738#[derive(Debug, Clone, PartialEq)]39pub enum Member {40	Field(FieldMember),41	BindStmt(Bind),42	AssertStmt(AssertStmt),43}4445#[derive(Debug, Clone, PartialEq)]46pub enum UnaryOpType {47	Plus,48	Minus,49	BitNot,50	Not,51}5253#[derive(Debug, Clone, PartialEq)]54pub enum BinaryOpType {55	Mul,56	Div,57	Mod,5859	Add,60	Sub,6162	Lhs,63	Rhs,6465	Lt,66	Gt,67	Lte,68	Gte,6970	In,7172	Eq,73	Ne,7475	BitAnd,76	BitOr,77	BitXor,7879	And,80	Or,81}8283#[derive(Debug, Clone, PartialEq)]84pub enum Param {85	Positional(String),86	Named(String, Box<Expr>),87}8889#[derive(Debug, Clone, PartialEq)]90pub struct ParamsDesc(pub Vec<Param>);9192#[derive(Debug, Clone, PartialEq)]93pub enum Arg {94	Positional(Box<Expr>),95	Named(String, Box<Expr>),96}9798#[derive(Debug, Clone, PartialEq)]99pub struct ArgsDesc(pub Vec<Arg>);100101#[derive(Debug, Clone, PartialEq)]102pub enum Bind {103	Value(String, Box<Expr>),104	Function(String, ParamsDesc, Box<Expr>),105}106107#[derive(Debug, Clone, PartialEq)]108pub struct IfSpec(pub Box<Expr>);109#[derive(Debug, Clone, PartialEq)]110pub struct ForSpec(pub String, pub Vec<IfSpec>);111112#[derive(Debug, Clone, PartialEq)]113pub enum CompSpec {114	IfSpec(IfSpec),115	ForSpec(ForSpec),116}117118#[derive(Debug, Clone, PartialEq)]119pub enum ObjBody {120	MemberList(Vec<Member>),121	ObjComp {122		pre_locals: Vec<Bind>,123		key: Box<Expr>,124		value: Box<Expr>,125		post_locals: Vec<Bind>,126		first: ForSpec,127		rest: Vec<CompSpec>,128	},129}130131#[derive(Debug, Clone, PartialEq)]132pub enum ValueType {133	Null,134	True,135	False,136}137138#[derive(Debug, Clone, PartialEq)]139pub enum LiteralType {140	This,141	Super,142	Dollar,143}144145/// Syntax base146#[derive(Debug, Clone, PartialEq)]147pub enum Expr {148	Value(ValueType),149	/// Plain value: null/true/false150	Literal(LiteralType),151152	/// String value: "hello"153	Str(String),154	/// Number: 1, 2.0, 2e+20155	Num(f64),156	/// Variable name: test157	Var(String),158159	/// Array of expressions: [1, 2, "Hello"]160	Arr(Vec<Expr>),161	/// Array comprehension:162	/// ```jsonnet163	///  ingredients: [164	///    { kind: kind, qty: 4 / 3 }165	///    for kind in [166	///      'Honey Syrup',167	///      'Lemon Juice',168	///      'Farmers Gin',169	///    ]170	///  ],171	/// ```172	ArrComp(Box<Expr>, Vec<ForSpec>),173174	/// Object: {a: 2}175	Obj(ObjBody),176	/// Object extension: var1 {b: 2}177	ObjExtend(Box<Expr>, ObjBody),178179	/// (obj)180	Parened(Box<Expr>),181182	Params(ParamsDesc),183	Args(ArgsDesc),184185	UnaryOp(UnaryOpType, Box<Expr>),186	BinaryOp(Box<Expr>, BinaryOpType, Box<Expr>),187	AssertExpr(AssertStmt, Box<Expr>),188	LocalExpr(Vec<Bind>, Box<Expr>),189190	Bind(Bind),191	Import(String),192	ImportStr(String),193	Error(Box<Expr>),194	Apply(Box<Expr>, ArgsDesc),195	Select(Box<Expr>, String),196	Index(Box<Expr>, Box<Expr>),197	Slice {198		value: Box<Expr>,199		start: Option<Box<Expr>>,200		end: Option<Box<Expr>>,201		step: Option<Box<Expr>>,202	},203	Function(ParamsDesc, Box<Expr>),204	IfElse {205		cond: IfSpec,206		cond_then: Box<Expr>,207		cond_else: Option<Box<Expr>>,208	},209	IfSpec(IfSpec),210	ForSpec(ForSpec),211}
modifiedcrates/jsonnet-parser/src/lib.rsdiffbeforeafterboth
--- a/crates/jsonnet-parser/src/lib.rs
+++ b/crates/jsonnet-parser/src/lib.rs
@@ -1,3 +1,5 @@
+#![feature(box_syntax)]
+
 use peg::parser;
 
 mod expr;
@@ -6,7 +8,7 @@
 enum Suffix {
 	String(String),
 	Expression(Expr),
-	Apply(expr::Args),
+	Apply(expr::ArgsDesc),
 }
 
 parser! {
@@ -18,27 +20,33 @@
 		rule digit() -> char = d:$(['0'..='9']) {d.chars().nth(0).unwrap()}
 		rule int() -> u32 = a:$(digit()+) { a.parse().unwrap() }
 		rule number() -> f64 = quiet!{a:$((['-'|'+'])? int() ("." int())? (['e'|'E'] (s:['+'|'-'])? int())?) { a.parse().unwrap() }} / expected!("<number>")
-		rule id() -> String = quiet!{ !("local" / "super" / "self" / "true" / "false" / "null" / "$" / "if" / "then" / "else") s:$(alpha() (alpha() / digit())*) {s.to_owned()}} / expected!("<identifier>")
+		rule id() -> String = quiet!{ !("local" / "super" / "self" / "true" / "false" / "null" / "$" / "if" / "then" / "else" / "function") s:$(alpha() (alpha() / digit())*) {s.to_owned()}} / expected!("<identifier>")
 
 		pub rule positional_param() -> expr::Param = name:id() {expr::Param::Positional(name)}
 		pub rule named_param() -> expr::Param = name:id() __() "=" __() expr:boxed_expr() {expr::Param::Named(name, expr)}
-		pub rule params() -> expr::Params
-			= positionals:(positional_param() ** delimiter()) delimiter() named:(named_param() ** delimiter()) {
-				expr::Params([&positionals[..], &named[..]].concat())
+		pub rule params() -> expr::ParamsDesc
+			= positionals:(positional_param() ** delimiter()) named: (delimiter() named:(named_param() ** delimiter()) {named})? {
+				if named.is_some() {
+					expr::ParamsDesc([&positionals[..], &named.unwrap()[..]].concat())
+				} else {
+					expr::ParamsDesc(positionals)
+				}
 			}
-			/ named:(named_param() ** delimiter()) {expr::Params(named)}
-			/ positionals:(positional_param() ** delimiter()) {expr::Params(positionals)}
-			/ {expr::Params(Vec::new())}
+			/ named:(named_param() ** delimiter()) {expr::ParamsDesc(named)}
+			/ {expr::ParamsDesc(Vec::new())}
 
 		pub rule positional_arg() -> expr::Arg = quiet!{name:boxed_expr() {expr::Arg::Positional(name)}}/expected!("<positional arg>")
 		pub rule named_arg() -> expr::Arg = quiet!{name:id() __() "=" __() expr:boxed_expr() {expr::Arg::Named(name, expr)}}/expected!("<named arg>")
-		pub rule args() -> expr::Args
-			= positionals:(positional_arg() ** delimiter()) delimiter() named:(named_arg() ** delimiter()) {
-				expr::Args([&positionals[..], &named[..]].concat())
+		pub rule args() -> expr::ArgsDesc
+			= positionals:(positional_arg() ** delimiter()) named: (delimiter() named:(named_arg() ** delimiter()) {named})? {
+				if named.is_some() {
+					expr::ArgsDesc([&positionals[..], &named.unwrap()[..]].concat())
+				} else {
+					expr::ArgsDesc(positionals)
+				}
 			}
-			/ named:(named_arg() ** delimiter()) {expr::Args(named)}
-			/ positionals:(positional_arg() ** delimiter()) {expr::Args(positionals)}
-			/ {expr::Args(Vec::new())}
+			/ named:(named_arg() ** delimiter()) {expr::ArgsDesc(named)}
+			/ {expr::ArgsDesc(Vec::new())}
 
 		pub rule bind() -> expr::Bind
 			= name:id() __() "=" __() expr:boxed_expr() {expr::Bind::Value(name, expr)}
@@ -118,6 +126,27 @@
 			/ if_then_else_expr()
 			/ local_expr()
 
+			/ "function" __() "(" __() params:params() __() ")" __() expr:boxed_expr() {Expr::Function(params, expr)}
+
+		rule expr_basic_with_suffix() -> Expr
+			= a:expr_basic() suffixes:(__() suffix:expr_suffix() {suffix})* {
+				let mut cur = a;
+				for suffix in suffixes {
+					match suffix {
+						Suffix::String(index) => {
+							cur = Expr::Index(Box::new(cur), Box::new(Expr::Str(index)))
+						},
+						Suffix::Expression(index) => {
+							cur = Expr::Index(Box::new(cur), Box::new(index))
+						},
+						Suffix::Apply(args) => {
+							cur = Expr::Apply(Box::new(cur), args)
+						}
+					}
+				}
+				cur
+			}
+
 		rule expr_suffix() -> Suffix
 			= "." __() s:id() { Suffix::String(s) }
 			/ "[" __() s:expr() __() "]" { Suffix::Expression(s) }
@@ -153,26 +182,10 @@
 				a:(@) __() "/" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Div, Box::new(b))}
 				a:(@) __() "%" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Mod, Box::new(b))}
 				--
-				e:expr_basic() {e}
+				e:expr_basic_with_suffix() {e}
 				"(" __() e:boxed_expr() __() ")" {Expr::Parened(e)}
-			} suffixes:(__() suffix:expr_suffix() {suffix})* {
-				let mut cur = a;
-				for suffix in suffixes {
-					match suffix {
-						Suffix::String(index) => {
-							cur = Expr::Index(Box::new(cur), Box::new(Expr::Str(index)))
-						},
-						Suffix::Expression(index) => {
-							cur = Expr::Index(Box::new(cur), Box::new(index))
-						},
-						Suffix::Apply(args) => {
-							cur = Expr::Apply(Box::new(cur), args)
-						}
-					}
-				}
-				cur
 			}
-			/ e:expr_basic() {e}
+			/ e:expr_basic_with_suffix() {e}
 
 		pub rule boxed_expr() -> Box<Expr> = e:expr() {Box::new(e)}
 		pub rule jsonnet() -> Expr = __() e:expr() __() {e}
@@ -206,4 +219,20 @@
 			)
 		);
 	}
+
+	#[test]
+	fn suffix_comparsion() {
+		use Expr::*;
+		assert_eq!(
+			parse("std.type(a) == \"string\"").unwrap(),
+			BinaryOp(
+				box Apply(
+					box Index(box Var("std".to_owned()), box Str("type".to_owned())),
+					ArgsDesc(vec![Arg::Positional(box Var("a".to_owned()))])
+				),
+				BinaryOpType::Eq,
+				box Str("string".to_owned())
+			)
+		);
+	}
 }