Documentation ¶
Overview ¶
Package gendsl provides framework a DSL in [Lisp](https://en.wikipedia.org/wiki/Lisp_(programming_language)) style and allows you to customize your own expressions so that you can integrate it into your own golang application without accessing any lexer or parser.
Index ¶
- Constants
- func Pretty(pretty bool) func(*parser) error
- func Size(size int) func(*parser) error
- type Bool
- type Env
- func (e *Env) Clone() *Env
- func (e *Env) Lookup(id string) (v Value, found bool)
- func (e *Env) WithBool(id string, b Bool) *Env
- func (e *Env) WithFloat(id string, f Float) *Env
- func (e *Env) WithInt(id string, i Int) *Env
- func (e *Env) WithNil(id string, n Nil) *Env
- func (e *Env) WithProcedure(id string, p Procedure) *Env
- func (e *Env) WithString(id string, s String) *Env
- func (e *Env) WithUint(id string, u Uint) *Env
- func (e *Env) WithUserData(id string, ud *UserData) *Env
- func (e *Env) WithValue(id string, val Value) *Env
- type EvalCtx
- type EvalOpt
- type EvaluateError
- type Expr
- type Float
- type Int
- type Nil
- type ParseContext
- type Procedure
- type ProcedureFn
- type String
- type SyntaxError
- type Uint
- type UnboundedIdentifierError
- type UserData
- type Value
- type ValueType
Examples ¶
Constants ¶
const ( ValueTypeInt = 1 << iota // Int ValueTypeUInt // Uint ValueTypeString // String ValueTypeBool // Bool ValueTypeFloat // Float ValueTypeProcedure // Procedure ValueTypeUserData // UserData ValueTypeNil // Nil )
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Env ¶
type Env struct {
// contains filtered or unexported fields
}
Env stores the mapping of identifiers and values. Note that an Env is not concurrently safe.
func (*Env) Lookup ¶
Lookup looks up the value of `id`. `found` report whether an value could be found in the env.
func (*Env) WithBool ¶
WithBool registers a gendsl.Bool into the env.
func (*Env) WithFloat ¶
WithFloat registers a gendsl.Float into the env.
func (*Env) WithInt ¶
WithInt registers a gendsl.Int into the env.
func (*Env) WithNil ¶
WithNil registers a gendsl.Nil into the env.
func (*Env) WithProcedure ¶
WithProcedure registers a gendsl.Procedure into the env.
func (*Env) WithString ¶
WithString registers a gendsl.String into the env.
func (*Env) WithUint ¶
WithUint registers a gendsl.Uint into the env.
func (*Env) WithUserData ¶
WithUserData registers a gendsl.UserData into the env.
type EvalCtx ¶
type EvalCtx struct { UserData any // UserData that is used across the entire script evaluation // contains filtered or unexported fields }
EvalCtx holds some information used for evaluation.
func NewEvalCtx ¶
NewEvalCtx creates a new EvalCtx with `p` as the output scope EvalCtx(nil is allowed), `userData` is argument used across the whole evaluation, `env` as the env for current scope evaluation, nil is allowed here and an empty env will be created for it.
func (*EvalCtx) Lookup ¶
Lookup looks up an identifier in the current env, and try to look it up in its outter scope recurssively if not found.
func (*EvalCtx) OutScopeEvalCtx ¶
OutScopeEvalCtx returns gendsl.EvalCtx from the outter scope.
type EvalOpt ¶
type EvalOpt struct {
Env *Env
}
EvalOpt for some options to control the evaluate behavior
type EvaluateError ¶
type EvaluateError struct { // pos where the expression cannot be evaluated. BeginLine, EndLine int BeginSym, EndSym int // contains filtered or unexported fields }
EvaluateError got thrown during the evaluation.
func (*EvaluateError) Cause ¶
func (s *EvaluateError) Cause() error
func (*EvaluateError) Error ¶
func (s *EvaluateError) Error() string
func (*EvaluateError) Unwrap ¶
func (s *EvaluateError) Unwrap() error
type Expr ¶
Expr wraps the evalution of an ast node, or in another word, an expression, It allows you control when the evalution can be done, or the env for evalution, so that you can program your procedure to act like a macro.
func (Expr) Eval ¶
Eval evaluate an gendsl.Expr, return the result of this expression.
These errors might be returned:
- gendsl.SyntaxError - when a syntax error is found in this expression
- gendsl.UnboundedIdentifierError - when an undefined id is used in this expression.
func (Expr) EvalWithEnv ¶
EvalWithEnv evaluate an gendsl.Expr with a new env, return the result of this expression. We will lookup an identifier in `env` first, and we will look it up again in the parent env when its value is not found in `env`.
These errors might be returned:
- gendsl.SyntaxError - when a syntax error is found in this expression
- gendsl.UnboundedIdentifierError - when an undefined id is used in this expression.
type ParseContext ¶
type ParseContext struct {
// contains filtered or unexported fields
}
ParseContext holds the stateless parser context for a compiled script. It can be reused and re-evaluated with different gendsl.EvalCtx.
func MakeParseContext ¶
func MakeParseContext(expr string) (*ParseContext, error)
MakeParseContext parses the expr and compiles it into an ast. You can save the *ParseContext for later usage, since there is no side-affect during evaluation.
func (*ParseContext) Eval ¶
func (c *ParseContext) Eval(evalCtx *EvalCtx) (Value, error)
Eval evaluates the compiled script with an evalCtx. It will panic if evalCtx is nil.
func (*ParseContext) PrintTree ¶
func (c *ParseContext) PrintTree()
PrintTree output the syntax tree to the stdio
type Procedure ¶
type Procedure struct {
Eval ProcedureFn
}
Procedure define how an expression in the format of (X Y Z...) got evaluated.
type ProcedureFn ¶
ProcedureFn specify the behavior of an gendsl.Procedure. `evalCtx` carry some information that might be used during the evaluation, see gendsl.EvalCtx
func CheckNArgs ¶
func CheckNArgs(nargs string, evalFn ProcedureFn) ProcedureFn
CheckNArgs check the amount of the operands for a procedure by wrapping an EvalFn.
`nargs` specify the pattern of the amount of operands:
- "+" to accept one or more than one operands
- "*" or "" to accept any amount of operands
- "?" to accept no or one operand
- "n" for whatever number the strconv.Atoi can accept, to check the exact amount of the operands
type SyntaxError ¶
type SyntaxError struct {
// contains filtered or unexported fields
}
SyntaxError got thrown when a parsing error found.
func (*SyntaxError) Error ¶
func (e *SyntaxError) Error() string
type UnboundedIdentifierError ¶
type UnboundedIdentifierError struct { ID string // ID that cannot be found // position where the unbounded id found BeginLine, EndLine int BeginSym, EndSym int }
UnboundedIdentifierError got thrown when an identifier cannot be found in env.
func (*UnboundedIdentifierError) Error ¶
func (s *UnboundedIdentifierError) Error() string
type UserData ¶
type UserData struct {
V any
}
UserData wraps any value. You can use it when no type of Value can be used.
type Value ¶
type Value interface { // Type return the ValueType of a Value. Type() ValueType // Unwrap convert Value to go value, so that it can be used with type conversion syntax. Unwrap() any // contains filtered or unexported methods }
Value represent all values that are used in the DSL[gendsl.ValueType]
A Value can be converted to a go value by calling Unwrap(), the type mapping is as following:
- Int -> int64
- Uint -> uint64
- String -> string
- Float -> float64
- Bool -> bool
- Nil -> nil
- Procedure -> EvalFn
- UserData -> any
func EvalExpr ¶
EvalExpr evaluates an `expr` with `env` and return a Value result which could be nil as the result.
Example ¶
package main import ( "fmt" "github.com/ccbhj/gendsl" ) func main() { plusOp := func(_ *gendsl.EvalCtx, args []gendsl.Expr, _ map[string]gendsl.Value) (gendsl.Value, error) { var ret gendsl.Int for _, arg := range args { v, err := arg.Eval() if err != nil { return nil, err } if v.Type() == gendsl.ValueTypeInt { ret += v.(gendsl.Int) } } return ret, nil } result, err := gendsl.EvalExpr("(PLUS ONE $TWO @THREE 4)", gendsl.NewEnv().WithInt("ONE", 1). WithInt("$TWO", 2). WithInt("@THREE", 3). WithProcedure("PLUS", gendsl.Procedure{ Eval: gendsl.CheckNArgs("+", plusOp), }), ) if err != nil { panic(err) } fmt.Println(result.Unwrap()) }
Output: 10
func EvalExprWithData ¶
EvalExprWithData evaluates an `expr` with `env`, and allow you to pass a data to use across the entrie evaluation.
Example ¶
package main import ( "fmt" "os" "github.com/ccbhj/gendsl" ) func main() { printlnOp := func(ectx *gendsl.EvalCtx, args []gendsl.Expr, _ map[string]gendsl.Value) (gendsl.Value, error) { output := ectx.UserData.(*os.File) for _, arg := range args { v, err := arg.Eval() if err != nil { return nil, err } fmt.Fprintln(output, v.Unwrap()) } return gendsl.Nil{}, nil } out := os.Stdout _, err := gendsl.EvalExprWithData("(PRINTLN ONE $TWO @THREE 4)", gendsl.NewEnv().WithInt("ONE", 1). WithInt("$TWO", 2). WithInt("@THREE", 3). WithProcedure("PRINTLN", gendsl.Procedure{ Eval: gendsl.CheckNArgs("+", printlnOp), }), out, ) if err != nil { panic(err) } }
Output: 1 2 3 4
Directories ¶
Path | Synopsis |
---|---|
cmd
|
|
echo
package main proveides a cmd that reads an expression from input or file and print the result or pretty print the ast for debugging.
|
package main proveides a cmd that reads an expression from input or file and print the result or pretty print the ast for debugging. |