simplequery

package module
v1.0.1-0...-f550d7e Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 9, 2020 License: MIT Imports: 3 Imported by: 1

README

go-simplequery-parser

Parse a condition query into a nested struct.

Example

root, _ := Parse(`foo < 10 AND (bar = "x" OR NOT baz = "y")`)

returns a root Node that has the following nested structure:

AND {
  LT {
    ID {
      "foo",
    },
    VAL {
      "10",
    },
  },
  OR {
    EQ {
      ID {
        "bar",
      },
      VAL {
        "\"x\"",
      },
    },
    NOT {
      EQ {
        ID {
          "baz",
        },
        VAL {
          "\"y\"",
        },
      },
    },
  },
}

This package does not implement a matcher that checks data against it, but this can be easily achieved with functions like

func Match(node Node, data <your data>) bool {
    switch n := node.(type) {
    case AND:
        return Match(n.Node1, data) && Match(n.Node2, data)
    case OR:
        return Match(n.Node1, data) || Match(n.Node2, data)
    case NOT:
        return !Match(n.Node, data)
    ...
    case EQ:
        id, _ := n.Node1.(ID)
        raw, _ := n.Node2.(VAL)
        val := ... // parse raw as string, int, regex, ...
        return data.GetValue(id) == val
    case LT:
        ....
    ....
    }
}

Alternatively this package may be useful to generate another search query with another syntax from it (Atm I use this package to generate a MongoDB search query based on the above simpler query syntax).

Documentation

Overview

Example (Parse)
package main

import (
	"fmt"
)

func lexAndParse(condition string) {
	tokens, err := tokenize(condition)
	if err != nil {
		panic(err)
	}
	node, err := parse(tokens)
	if err != nil {
		fmt.Println(err.Error())
	} else {
		fmt.Println(node.String())
	}
}

func main() {
	lexAndParse("X = 5")
	lexAndParse("X = 5 AND Y = 6")
	lexAndParse("(X = 5 AND Y = 6)")
	lexAndParse("(X = 5 AND Y = 6) OR (X = 10 AND Y = 11)")
	lexAndParse("X < 5")
	lexAndParse("X <= 5")
	lexAndParse("NOT X = 5")
	lexAndParse("NOT (X = 10 AND Y = 11)")
	lexAndParse("5 OR 6")
}
Output:

EQ{ID{"X"},VAL{"5"}}
AND{EQ{ID{"X"},VAL{"5"}},EQ{ID{"Y"},VAL{"6"}}}
AND{EQ{ID{"X"},VAL{"5"}},EQ{ID{"Y"},VAL{"6"}}}
OR{AND{EQ{ID{"X"},VAL{"5"}},EQ{ID{"Y"},VAL{"6"}}},AND{EQ{ID{"X"},VAL{"10"}},EQ{ID{"Y"},VAL{"11"}}}}
LT{ID{"X"},VAL{"5"}}
LTE{ID{"X"},VAL{"5"}}
NOT{EQ{ID{"X"},VAL{"5"}}}
NOT{AND{EQ{ID{"X"},VAL{"10"}},EQ{ID{"Y"},VAL{"11"}}}}
OR{VAL{"5"},VAL{"6"}}
Example (Tokenize)
tokens, err := tokenize(`foo < 10 AND (bar = "x" OR NOT baz = "y")`)
if err != nil {
	panic(err)
}
for _, token := range tokens {
	fmt.Println(token)
}
Output:

ID["foo"]{1}
LT["<"]{5}
VAL["10"]{7}
AND["AND"]{10}
LPAR["("]{14}
ID["bar"]{15}
EQ["="]{19}
VAL["\"x\""]{21}
OR["OR"]{25}
NOT["NOT"]{28}
ID["baz"]{32}
EQ["="]{36}
VAL["\"y\""]{38}
RPAR[")"]{41}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AND

type AND struct {
	// contains filtered or unexported fields
}

func (AND) Children

func (n AND) Children() (Node, Node)

func (AND) String

func (n AND) String() string

func (AND) Value

func (_ AND) Value() string

type EQ

type EQ struct {
	// contains filtered or unexported fields
}

func (EQ) Children

func (n EQ) Children() (Node, Node)

func (EQ) String

func (n EQ) String() string

func (EQ) Value

func (_ EQ) Value() string

type GT

type GT struct {
	// contains filtered or unexported fields
}

func (GT) Children

func (n GT) Children() (Node, Node)

func (GT) String

func (n GT) String() string

func (GT) Value

func (_ GT) Value() string

type GTE

type GTE struct {
	// contains filtered or unexported fields
}

func (GTE) Children

func (n GTE) Children() (Node, Node)

func (GTE) String

func (n GTE) String() string

func (GTE) Value

func (_ GTE) Value() string

type ID

type ID struct {
	// contains filtered or unexported fields
}

func (ID) Children

func (_ ID) Children() (Node, Node)

func (ID) String

func (n ID) String() string

func (ID) Value

func (n ID) Value() string

type LT

type LT struct {
	// contains filtered or unexported fields
}

func (LT) Children

func (n LT) Children() (Node, Node)

func (LT) String

func (n LT) String() string

func (LT) Value

func (_ LT) Value() string

type LTE

type LTE struct {
	// contains filtered or unexported fields
}

func (LTE) Children

func (n LTE) Children() (Node, Node)

func (LTE) String

func (n LTE) String() string

func (LTE) Value

func (_ LTE) Value() string

type NE

type NE struct {
	// contains filtered or unexported fields
}

func (NE) Children

func (n NE) Children() (Node, Node)

func (NE) String

func (n NE) String() string

func (NE) Value

func (_ NE) Value() string

type NOT

type NOT struct {
	// contains filtered or unexported fields
}

func (NOT) Children

func (n NOT) Children() (Node, Node)

func (NOT) String

func (n NOT) String() string

func (NOT) Value

func (_ NOT) Value() string

type Node

type Node interface {
	String() string
	Value() string
	Children() (Node, Node)
}

func Parse

func Parse(condition string) (Node, error)
Example
package main

import (
	"fmt"
	"strings"
)

func main() {
	root, err := Parse(`foo < 10 AND (bar = "x" OR NOT baz = "y")`)
	if err != nil {
		panic(err)
	}
	prettyPrint(root)
}

func prettyPrint(root Node) {
	str := root.String()
	var indent = 0
	for _, char := range str {
		if char == '{' {
			fmt.Println(" {")
			indent++
			fmt.Print(strings.Repeat("  ", indent))
		} else if char == '}' {
			fmt.Println(",")
			indent--
			fmt.Print(strings.Repeat("  ", indent), "}")
		} else if char == ',' {
			fmt.Println(",")
			fmt.Print(strings.Repeat("  ", indent))
		} else {
			fmt.Print(string(char))
		}
	}
}
Output:

AND {
  LT {
    ID {
      "foo",
    },
    VAL {
      "10",
    },
  },
  OR {
    EQ {
      ID {
        "bar",
      },
      VAL {
        "\"x\"",
      },
    },
    NOT {
      EQ {
        ID {
          "baz",
        },
        VAL {
          "\"y\"",
        },
      },
    },
  },
}

type OR

type OR struct {
	// contains filtered or unexported fields
}

func (OR) Children

func (n OR) Children() (Node, Node)

func (OR) String

func (n OR) String() string

func (OR) Value

func (_ OR) Value() string

type VAL

type VAL struct {
	// contains filtered or unexported fields
}

func (VAL) Children

func (_ VAL) Children() (Node, Node)

func (VAL) String

func (n VAL) String() string

func (VAL) Value

func (n VAL) Value() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL