
Syntax.pudu
Pudu77 lines2.6 KB
1/** @Log.Expressions.Syntax.Tree — the parsed form of filter expressions */2module PuduLangLog.Expressions.Syntax34import PuduLangLog as Log56/** @Log.Expressions.Syntax.Expression — one node of an expression */7export type Expression = Constant(Log.Value)8 | Name(Str)9 | Member(Expression, Str)10 | Index(Expression, Expression)11 | Wildcard(Expression, Quantifier)12 | Call(Str, Array[Expression], Bool)13 | Unary(Str, Expression)14 | Binary(Str, Expression, Expression, Bool)15 | ArrayOf(Array[Element])16 | ObjectOf(Array[Field])17 | Conditional(Expression, Expression, Expression)1819/** @Log.Expressions.Syntax.Quantifier — whether any or every element must match */20export type Quantifier = AnyOf | AllOf2122/** @Log.Expressions.Syntax.Element — an array item or a spread array */23export type Element = Item(Expression) | SpreadItems(Expression)2425/** @Log.Expressions.Syntax.Field — an object member or a spread object */26export type Field = Pair(Str, Expression) | SpreadMembers(Expression)272829export fn namesIn(expression: &Expression) -> Array[Str] {30 var found: Array[Str] = []31 for part in partsOf(expression) {32 if let Name(name) = part {33 if !found.contains(name) { found = found.push(name) }34 }35 }36 found37}383940export fn callsIn(expression: &Expression) -> Array[Str] {41 var found: Array[Str] = []42 for part in partsOf(expression) {43 if let Call(name, _, _) = part { found = found.push(name) }44 }45 found46}474849fn partsOf(expression: &Expression) -> Array[Expression] {50 var found = [*expression]51 for child in children(expression) { found = found.concat(partsOf(&child)) }52 found53}545556fn children(expression: &Expression) -> Array[Expression] {57 match expression {58 case Constant(_) => []59 case Name(_) => []60 case Member(target, _) => [target]61 case Index(target, key) => [target, key]62 case Wildcard(target, _) => [target]63 case Call(_, arguments, _) => arguments64 case Unary(_, operand) => [operand]65 case Binary(_, left, right, _) => [left, right]66 case ArrayOf(elements) => elements.map(|element: Element| match element {67 case Item(item) => item68 case SpreadItems(items) => items69 })70 case ObjectOf(fields) => fields.map(|field: Field| match field {71 case Pair(_, held) => held72 case SpreadMembers(members) => members73 })74 case Conditional(condition, then, otherwise) => [condition, then, otherwise]75 }76}77