difftreelog
fix(parser) move suffixes to expr_basic, function parsing BREAKING CHANGE: Renamed: Args => ArgsDesc Params => ParamsDesc
in: master
2 files changed
crates/jsonnet-parser/src/expr.rsdiffbeforeafterboth1#[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}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}crates/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())
+ )
+ );
+ }
}