lexer

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Feb 21, 2024 License: AGPL-3.0 Imports: 6 Imported by: 0

Documentation

Overview

Example
package main

import (
	"fmt"
	"slices"
	"sort"
)

var data = map[string][]string{
	"MATIC (staked)": {
		"0x63ca58fdcfa0bab3e743", // result 1
		"0x75df00c550e4d5867269", // result 2
		"0xbb0574ee8d15b5869fef", // result 3
		"0xb9e3e451eebbbdcaed5a",
		"0x9be089b89bf7bbddd5ea",
	},
	"USDC": {
		"0x63ca58fdcfa0bab3e743", // result 1
		"0xcd82100c3bc9411ed352",
		"0xbb0574ee8d15b5869fef", // result 3
		"0x6a78167e9a02d3693a6e",
		"0xbb54d600f7dde07440ae",
	},
	"BTC": {
		"0x995129124181c3d67974",
		"0x75df00c550e4d5867269", // result 2
		"0xcf62ab575da9daece6c2",
		"0xd7427cf2e3e766e0e9de",
		"0x774d1ca6845e2f30ba2d",
	},
	"ETH": {
		"0x2479badef3c5f9d10bc7",
		"0x1650fd8d9aa883fef994",
		"0x75df00c550e4d5867269", // result 2
		"0x61ff45597f7ccb7cad1b",
		"0xaa5ba44ce301c784926d",
	},
	"wANT": {
		"0xbb0574ee8d15b5869fef", // result 3
		"0xc18d1a2c1687b6711832",
		"0x21dc25c4650fffbbff76",
		"0xb014c34d7e57a0da5284",
		"0xa88f67b54395697c6810",
	},
	"ANT": {
		"0x63ca58fdcfa0bab3e743", // result 1
		"0xbee2a6d71759d55238bf",
		"0x4dbf5af682b609c7ae41",
		"0x8ddf4e74cdaef6b44ffd",
		"0x75df00c550e4d5867269", // result 2
	},
}

func AND(iter *Iteration[[]string]) ([]string, error) {
	tagA, dataA := iter.A()
	if dataA == nil {
		dataA = data[tagA]
	}
	tagB, dataB := iter.B()
	if dataB == nil {
		dataB = data[tagB]
	}

	res := []string{}
	for _, a := range dataA {
		if slices.Contains(dataB, a) {
			res = append(res, a)
		}
	}
	return res, nil
}

func OR(iter *Iteration[[]string]) ([]string, error) {
	tagA, dataA := iter.A()
	if dataA == nil {
		dataA = data[tagA]
	}
	tagB, dataB := iter.B()
	if dataB == nil {
		dataB = data[tagB]
	}

	res := append([]string{}, dataB...)
	for _, a := range dataA {
		exist := false
		for _, b := range dataB {
			if a == b {
				exist = true
				break
			}
		}
		if !exist {
			res = append(res, a)
		}
	}
	return res, nil
}

func XOR(iter *Iteration[[]string]) ([]string, error) {
	tagA, dataA := iter.A()
	if dataA == nil {
		dataA = data[tagA]
	}
	tagB, dataB := iter.B()
	if dataB == nil {
		dataB = data[tagB]
	}

	res := []string{}
	for _, a := range dataA {
		exist := false
		for _, b := range dataB {
			if a == b {
				exist = true
				break
			}
		}
		if !exist {
			res = append(res, a)
		}
	}
	for _, b := range dataB {
		exist := false
		for _, a := range dataA {
			if b == a {
				exist = true
				break
			}
		}
		if !exist {
			res = append(res, b)
		}
	}
	return res, nil
}

func main() {
	predicate := "MATIC\\ \\(staked\\) AND ((USDC OR (BTC AND ETH)) AND (wANT XOR ANT))"
	operators := []*Operator[[]string]{
		{Tag: "AND", Fn: AND},
		{Tag: "OR", Fn: OR},
		{Tag: "XOR", Fn: XOR},
	}
	operatorsTags := []string{"AND", "OR", "XOR"}
	// create lexer and parse predicate
	rootToken, err := NewLexer(operatorsTags).Parse(predicate)
	if err != nil {
		panic(err)
	}
	// create evaluator and eval with operators
	res, err := NewEval(operators).EvalToken(rootToken)
	if err != nil {
		panic(err)
	}
	sort.Strings(res)
	fmt.Println(res)
}
Output:

[0x63ca58fdcfa0bab3e743 0x75df00c550e4d5867269 0xbb0574ee8d15b5869fef]

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ScapeTokenSymbol

func ScapeTokenSymbol(symbol string) string

Types

type Evaluator

type Evaluator[T any] struct {
	// contains filtered or unexported fields
}

Evaluator struct helps to evaluate a Part using the defined operators, that implements the referenced type. It contains a parameter to store the results of each level operation, passing it to each iteration that requires it.

func NewEval

func NewEval[T any](ops []*Operator[T]) *Evaluator[T]

NewEval function returns an initialized Evaluator with operators implementing the type referenced.

func (*Evaluator[T]) EvalToken

func (e *Evaluator[T]) EvalToken(p *Token) (T, error)

EvalToken methdo iterates over all the token provided childs executing the associated operator passing the tokens or values referenced by each token. The child tokens are sorted by descending level ensuring dependencies resolution and storing the partial results.

type Group

type Group struct {
	ID       int
	Operator string
	Level    int
	Tokens   map[string]*Token
	// contains filtered or unexported fields
}

Group struct envolves a group of tokens, identified by its ID. Any group will contain an operator tag, the level of the group, and the tokens of the group.

func NewEmptyGroup

func NewEmptyGroup(level int) *Group

NewEmptyGroup function returns an empty Group for the level provided. The group ID is randomly generated, and it is lower than or equal to maxGroupID.

func (*Group) AddToken

func (g *Group) AddToken(t *Token) error

AddToken method assign the token provided to the current group. If the group already contains the provided token, skip without error. If the group is already completed (already has two tokens), raises an error. The method assigns the provided token as first token if the group has not one. If it already has a first token, the provided token will be the second one.

func (*Group) Complete

func (g *Group) Complete() bool

Complete method returns if the current group is already completed which means that it has an operator and two tokens (first and second one).

func (*Group) MarshalJSON

func (g *Group) MarshalJSON() ([]byte, error)

MarshalJSON method helps to encode the current group into a JSON with just the important information, discarding internal information.

type Iteration

type Iteration[T any] struct {
	// contains filtered or unexported fields
}

Iteration struct helps to pass to every iteration the tokens or partial results required to execute the iteration operator.

func MockIteration

func MockIteration[T any](a, b string, aT, bT T) *Iteration[T]

MockIteration function returns a mocked Iteration with just the token symbols provided.

func (Iteration[T]) A

func (iter Iteration[T]) A() (string, T)

A method return the tag and the current of the first component of the operation of the current iteration. It helps to implement Operator's providing an API to work with results of previous operations but olso with external data source associated with the tag.

func (Iteration[T]) B

func (iter Iteration[T]) B() (string, T)

B method return the tag and the current of the second component of the operation of the current iteration. It helps to implement Operator's providing an API to work with results of previous operations but olso with external data source associated with the tag.

type Lexer

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

Lexer struct helps to parse a predicated with a predefined operators, generating a iterable struct to eval the it then.

func NewLexer

func NewLexer(ops []string) *Lexer

NewLexer returns a initialized lexer with the operators tags provided

func (*Lexer) Parse

func (l *Lexer) Parse(predicate string) (*Token, error)

Parse method tokenize the predicate provided a decode its groups levels recursively returning a Part

func (*Lexer) SupportedOperator

func (l *Lexer) SupportedOperator(tag string) bool

SupportedOperator method return if the tag provided is a operator supported by the current lexer

type Operator

type Operator[T any] struct {
	Tag string
	Fn  func(*Iteration[T]) (T, error)
}

Operator struct helps to define operations with their token tags and associated function that implements the type referenced.

type Token

type Token struct {
	Type    TokenType
	Literal string
	Childs  *Group
}

Token struct envolves any type of token (literal or group).

func NewGroupToken

func NewGroupToken(group *Group) *Token

NewGroupToken function returns a new group Token inflated with the provided group. If it is nil, the function inflate it with a emptye group at level 0. It set the resulting Token Literal attribute as the string group ID.

func NewLiteralToken

func NewLiteralToken(literal string) *Token

NewLiteralToken function returns a new literal Token inflated with the provided value.

func (*Token) AllGroups

func (t *Token) AllGroups() []*Group

AllGroups method returns all the group tokens from the current token to the last child, including it. The method calls itself recursively if the current token is a group token.

func (*Token) AllLiterals

func (t *Token) AllLiterals() []string

AllLiterals method returns all the literal tokens from the current token to the last child, including it. The method calls itself recursively if the current token is a group token.

func (*Token) Equals

func (a *Token) Equals(b *Token) bool

Equals method return if the a token is equal to b token. It compares the between both tokens string versions.

func (*Token) IsLiteral

func (t *Token) IsLiteral() bool

IsLiteral method returns if the current token is a literal token (or a group token).

func (*Token) MarshalJSON

func (t *Token) MarshalJSON() ([]byte, error)

MarshalJSON method helps to encode the current token into a JSON with just the important information, discarding internal information.

func (*Token) String

func (t *Token) String() string

String function returns the string version of the current token. It can be used as predicated input to generate the same token.

type TokenType

type TokenType int

TokenType custom type defines the Token type attribute.

const (
	// TokenTypeLiteral is the type value assigned to literal tokens
	TokenTypeLiteral TokenType = iota
	// TokenTypeGroup is the type value assigned to group tokens
	TokenTypeGroup
)

Jump to

Keyboard shortcuts

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