From b434fe4e14f6dcc8d1d7433a29351b8e8ea77d37 Mon Sep 17 00:00:00 2001 From: Charlie Stanton Date: Thu, 2 May 2024 21:45:45 +0100 Subject: Add , subex syntax to make FullMerge commands easier --- main/main_test.go | 15 +++++++++++---- subex/filter.go | 20 ++++++++++++++++++++ subex/parse.go | 11 +++++++++++ subex/subexast.go | 12 ++++++++++++ 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/main/main_test.go b/main/main_test.go index 3d10c48..076693d 100644 --- a/main/main_test.go +++ b/main/main_test.go @@ -6,7 +6,8 @@ import ( ) const miscInput string = `{"something":{"nested":"Here is my test value"},"array":["Hello","world","these","are","values"],"people":[{"first_name":"Charlie","last_name":"Johnson","age":22},{"first_name":"Tom","last_name":"Johnson","age":18},{"first_name":"Charlie","last_name":"Chaplin","age":122},{"first_name":"John","last_name":"Johnson","age":48}]}` -const mixedArray string = `{"array":["first",{"name":"second"},"third"]}` +const mixedArray string = `{"array":["first",null,3,{"name":"second"},"third"]}` +const mixedArray2 string = `{"array":["first",null,3,"second",{"name":"third"}]}` func TestSpecificCases(t *testing.T) { type test struct { @@ -116,7 +117,7 @@ func TestSpecificCases(t *testing.T) { }, { name: "Drop last element of array", - program: `M/#( "people" @( . #()# )@ )#/{ Ed }`, + program: `M/#( "people" @( . , )@ )#/{ Ed }`, input: miscInput, expected: `{"something":{"nested":"Here is my test value"},"array":["Hello","world","these","are","values"],"people":[{"first_name":"Charlie","last_name":"Johnson","age":22},{"first_name":"Tom","last_name":"Johnson","age":18},{"first_name":"Charlie","last_name":"Chaplin","age":122}]}`, }, @@ -128,9 +129,15 @@ func TestSpecificCases(t *testing.T) { }, { name: "Drop last element of mixed array", - program: `M/#( "array" @( . (~[.]~|@()@|#()#) )@ )#/{ Ed }`, + program: `M/#( "array" @( . , )@ )#/{ Ed }`, input: mixedArray, - expected: `{"array":["first",{"name":"second"}]}`, + expected: `{"array":["first",null,3,{"name":"second"}]}`, + }, + { + name: "Drop last element of mixed array 2", + program: `M/#( "array" @( . , )@ )#/{ Ed }`, + input: mixedArray2, + expected: `{"array":["first",null,3,"second"]}`, }, { name: "Prepend to array", diff --git a/subex/filter.go b/subex/filter.go index ae4b8ab..309d6c7 100644 --- a/subex/filter.go +++ b/subex/filter.go @@ -27,6 +27,26 @@ func (_ anyBoolFilter) valueFilter(value walk.Value) bool { return isBool } +type simpleValueFilter struct {} +func (_ simpleValueFilter) valueFilter(value walk.Value) bool { + switch value := value.(type) { + case walk.NullValue: + return true + case walk.BoolValue: + return true + case walk.NumberValue: + return true + case walk.StringValue: + return true + case walk.ArrayValue: + return len(value) == 0 + case walk.MapValue: + return len(value) == 0 + default: + panic("Invalid value type") + } +} + type anyValueFilter struct {} func (_ anyValueFilter) valueFilter(value walk.Value) bool { return true diff --git a/subex/parse.go b/subex/parse.go index 9a7a75c..e91008a 100644 --- a/subex/parse.go +++ b/subex/parse.go @@ -520,6 +520,17 @@ func parseSubex(l RuneReader, minPower int, inType Type) (lhs SubexAST, outType } else { lhs = SubexASTCopyAnyValue{} } + case ',': + switch inType { + case ValueType: + outType = inType + lhs = SubexASTCopyAnySimpleValue{} + case RuneType: + outType = inType + lhs = SubexASTCopyRune{','} + default: + panic("Invalid inType") + } case '?': outType = inType lhs = SubexASTCopyBool{} diff --git a/subex/subexast.go b/subex/subexast.go index d08ddac..655a783 100644 --- a/subex/subexast.go +++ b/subex/subexast.go @@ -238,6 +238,18 @@ func (ast SubexASTCopyNumber) String() string { return "%" } +// Read in a null, bool, number, string or empty array or map and output it unchanged +type SubexASTCopyAnySimpleValue struct {} +func (ast SubexASTCopyAnySimpleValue) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { + if inType != ValueType || outType != ValueType { + panic("Invalid types for SubexASTCopyAnySimpleValue") + } + return &SubexCopyState { + next: next, + filter: simpleValueFilter{}, + } +} + // Read in any single Atom and output it unchanged type SubexASTCopyAnyValue struct {} func (ast SubexASTCopyAnyValue) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { -- cgit v1.2.3