diff --git a/pkg/yqlib/treeops/lib.go b/pkg/yqlib/treeops/lib.go index b60d055..df0ba91 100644 --- a/pkg/yqlib/treeops/lib.go +++ b/pkg/yqlib/treeops/lib.go @@ -72,6 +72,8 @@ func CreateValueOperation(value interface{}, stringValue string) *Operation { node.Tag = "!!bool" case string: node.Tag = "!!str" + case nil: + node.Tag = "!!null" } return &Operation{ diff --git a/pkg/yqlib/treeops/operator_select_test.go b/pkg/yqlib/treeops/operator_select_test.go index 7053676..3a2dae1 100644 --- a/pkg/yqlib/treeops/operator_select_test.go +++ b/pkg/yqlib/treeops/operator_select_test.go @@ -35,6 +35,12 @@ var selectOperatorScenarios = []expressionScenario{ "D0, P[a things], (!!map)::{include: true}\n", "D0, P[a andMe], (!!map)::{include: fold}\n", }, + }, { + document: `[cat,~,dog]`, + expression: `.[] | select(. == ~)`, + expected: []string{ + "D0, P[1], (!!null)::~\n", + }, }, } diff --git a/pkg/yqlib/treeops/operator_value_test.go b/pkg/yqlib/treeops/operator_value_test.go index c7512f6..43408f7 100644 --- a/pkg/yqlib/treeops/operator_value_test.go +++ b/pkg/yqlib/treeops/operator_value_test.go @@ -67,6 +67,20 @@ var valueOperatorScenarios = []expressionScenario{ "D0, P[], (!!bool)::false\n", }, }, + { + document: ``, + expression: `Null`, + expected: []string{ + "D0, P[], (!!null)::Null\n", + }, + }, + { + document: ``, + expression: `~`, + expected: []string{ + "D0, P[], (!!null)::~\n", + }, + }, } func TestValueOperatorScenarios(t *testing.T) { diff --git a/pkg/yqlib/treeops/path_tokeniser.go b/pkg/yqlib/treeops/path_tokeniser.go index ca302f7..23c575c 100644 --- a/pkg/yqlib/treeops/path_tokeniser.go +++ b/pkg/yqlib/treeops/path_tokeniser.go @@ -151,6 +151,12 @@ func stringValue(wrapped bool) lex.Action { } } +func nullValue() lex.Action { + return func(s *lex.Scanner, m *machines.Match) (interface{}, error) { + return &Token{TokenType: OperationToken, Operation: CreateValueOperation(nil, string(m.Bytes))}, nil + } +} + func selfToken() lex.Action { return func(s *lex.Scanner, m *machines.Match) (interface{}, error) { op := &Operation{OperationType: SelfReference} @@ -200,6 +206,9 @@ func initLexer() (*lex.Lexer, error) { lexer.Add([]byte(`[Tt][Rr][Uu][Ee]`), booleanValue(true)) lexer.Add([]byte(`[Ff][Aa][Ll][Ss][Ee]`), booleanValue(false)) + lexer.Add([]byte(`[Nn][Uu][Ll][Ll]`), nullValue()) + lexer.Add([]byte(`~`), nullValue()) + lexer.Add([]byte(`"[^ "]+"`), stringValue(true)) lexer.Add([]byte(`\[`), literalToken(OpenCollect, false))