ast package full godoc
This commit is contained in:
parent
956044cfae
commit
fec3550702
7 changed files with 68 additions and 26 deletions
|
|
@ -19,12 +19,14 @@ package ast
|
||||||
|
|
||||||
import "gitlab.com/whom/shs/log"
|
import "gitlab.com/whom/shs/log"
|
||||||
|
|
||||||
/* determines whether or not to execute a system call
|
/* determines whether or not to execute a system binary
|
||||||
* when a function cannot be found in the functable
|
* when a function cannot be found in the functable
|
||||||
* (use case: shell)
|
* (use case: shell)
|
||||||
* ExecFunc determines the name of the system call function to fetch
|
|
||||||
*/
|
*/
|
||||||
var ExecWhenFuncUndef = false
|
var ExecWhenFuncUndef = false
|
||||||
|
|
||||||
|
/* name of the command used to execute a system binary
|
||||||
|
*/
|
||||||
var ExecFunc = "l"
|
var ExecFunc = "l"
|
||||||
|
|
||||||
/* Runs through an AST of tokens
|
/* Runs through an AST of tokens
|
||||||
|
|
|
||||||
|
|
@ -19,18 +19,35 @@ package ast
|
||||||
|
|
||||||
import "gitlab.com/whom/shs/log"
|
import "gitlab.com/whom/shs/log"
|
||||||
|
|
||||||
|
/* expected function header for any stdlib function
|
||||||
|
*/
|
||||||
type Operation func(*Token, VarTable, FuncTable) *Token
|
type Operation func(*Token, VarTable, FuncTable) *Token
|
||||||
|
|
||||||
|
/* holds a stdlib function along with relevant metadata
|
||||||
|
*/
|
||||||
type Function struct {
|
type Function struct {
|
||||||
|
// go function that list of args are passed to
|
||||||
Function Operation
|
Function Operation
|
||||||
|
|
||||||
|
// name of function
|
||||||
Name string
|
Name string
|
||||||
|
|
||||||
|
// number of times user has called this function
|
||||||
TimesCalled int
|
TimesCalled int
|
||||||
Args int // TODO: Make this a list of expected types (TAGs)
|
|
||||||
|
// number of args required
|
||||||
|
Args int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* holds a mapping of key to function
|
||||||
|
* passed to eval and into function calls
|
||||||
|
* initialized by repl at startup
|
||||||
|
*/
|
||||||
type FuncTable *map[string]*Function
|
type FuncTable *map[string]*Function
|
||||||
|
|
||||||
// TODO: Currently only checks arg list length
|
/* validates an individual call of a function
|
||||||
|
* makes sure correct arguments are passed in
|
||||||
|
*/
|
||||||
func (f Function) ParseFunction(args *Token) bool {
|
func (f Function) ParseFunction(args *Token) bool {
|
||||||
// handle infinite args
|
// handle infinite args
|
||||||
if f.Args < 0 {
|
if f.Args < 0 {
|
||||||
|
|
@ -52,6 +69,9 @@ func (f Function) ParseFunction(args *Token) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* handles a call to a function
|
||||||
|
* calls ParseFunction and increments TimesCalled
|
||||||
|
*/
|
||||||
func (f Function) CallFunction(args *Token, vt VarTable, ft FuncTable) *Token {
|
func (f Function) CallFunction(args *Token, vt VarTable, ft FuncTable) *Token {
|
||||||
if !f.ParseFunction(args) {
|
if !f.ParseFunction(args) {
|
||||||
log.Log(log.ERR,
|
log.Log(log.ERR,
|
||||||
|
|
@ -64,6 +84,8 @@ func (f Function) CallFunction(args *Token, vt VarTable, ft FuncTable) *Token {
|
||||||
return f.Function(args, vt, ft)
|
return f.Function(args, vt, ft)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* searches for function mapped to argument in FuncTable
|
||||||
|
*/
|
||||||
func GetFunction(arg string, table FuncTable) *Function {
|
func GetFunction(arg string, table FuncTable) *Function {
|
||||||
target, ok := (*table)[arg]
|
target, ok := (*table)[arg]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
@ -77,7 +99,7 @@ func GetFunction(arg string, table FuncTable) *Function {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* lists all functions in table
|
/* returns list of all functions in table
|
||||||
*/
|
*/
|
||||||
func ListFuncs(ft FuncTable) []string {
|
func ListFuncs(ft FuncTable) []string {
|
||||||
keys := make([]string, len(*ft))
|
keys := make([]string, len(*ft))
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,12 @@ import (
|
||||||
"unicode"
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// all delimiters that work on strings
|
||||||
const string_delims string = "\"'`"
|
const string_delims string = "\"'`"
|
||||||
|
|
||||||
|
/* takes a line of user input
|
||||||
|
* returns an unsimplified tree of tokens
|
||||||
|
*/
|
||||||
func Lex(input string) *Token {
|
func Lex(input string) *Token {
|
||||||
ret := lex(input)
|
ret := lex(input)
|
||||||
if ret == nil {
|
if ret == nil {
|
||||||
|
|
@ -201,6 +205,7 @@ error:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns true if a string could contain an int or float
|
||||||
func StrIsNumber(arg string) bool {
|
func StrIsNumber(arg string) bool {
|
||||||
dotCount := 0
|
dotCount := 0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,11 @@ package ast
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
|
/* token_t is a tag that declares the type of the
|
||||||
|
* datum contained in a token
|
||||||
|
*/
|
||||||
type Token_t int
|
type Token_t int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LIST Token_t = iota
|
LIST Token_t = iota
|
||||||
STRING Token_t = iota
|
STRING Token_t = iota
|
||||||
|
|
@ -31,6 +35,9 @@ const (
|
||||||
FALSE string = "F"
|
FALSE string = "F"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/* Contains a parsed lexeme
|
||||||
|
* and a pointer to the next parsed lexeme in the same scope
|
||||||
|
*/
|
||||||
type Token struct {
|
type Token struct {
|
||||||
Next *Token
|
Next *Token
|
||||||
Tag Token_t
|
Tag Token_t
|
||||||
|
|
|
||||||
|
|
@ -17,16 +17,23 @@
|
||||||
|
|
||||||
package ast
|
package ast
|
||||||
|
|
||||||
|
/* primitive stack type for tokens
|
||||||
|
* useful for iterative algorithms on tokens
|
||||||
|
*/
|
||||||
type TokenStack struct {
|
type TokenStack struct {
|
||||||
buffer []*Token
|
buffer []*Token
|
||||||
capacity int
|
capacity int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* push token onto stack
|
||||||
|
*/
|
||||||
func (s *TokenStack) Push(v *Token) {
|
func (s *TokenStack) Push(v *Token) {
|
||||||
s.capacity++
|
s.capacity++
|
||||||
s.buffer = append(s.buffer, v)
|
s.buffer = append(s.buffer, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* pop token off stack
|
||||||
|
*/
|
||||||
func (s *TokenStack) Pop() *Token {
|
func (s *TokenStack) Pop() *Token {
|
||||||
if s.capacity <= 0 {
|
if s.capacity <= 0 {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,19 @@ import (
|
||||||
"gitlab.com/whom/shs/log"
|
"gitlab.com/whom/shs/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Trigger this if you are using this for a shell
|
/* defines whether or not to synchronize tokens wiht os environment vars
|
||||||
|
* will not sync non stringable tokens
|
||||||
|
*/
|
||||||
var SyncTablesWithOSEnviron = false
|
var SyncTablesWithOSEnviron = false
|
||||||
|
|
||||||
|
/* mapping of key to token.
|
||||||
|
*/
|
||||||
type VarTable *map[string]*Token
|
type VarTable *map[string]*Token
|
||||||
|
|
||||||
|
/* retrieve the token cooresponding to a given key
|
||||||
|
* if SyncTablesWithOSEnviron is true and no token exists for a key
|
||||||
|
* os Environment variables will be searched for the key
|
||||||
|
*/
|
||||||
func GetVar(arg string, vt VarTable) *Token {
|
func GetVar(arg string, vt VarTable) *Token {
|
||||||
val, ok := (*vt)[arg]
|
val, ok := (*vt)[arg]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
@ -55,8 +63,10 @@ func GetVar(arg string, vt VarTable) *Token {
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this could be much more optimal
|
/* adds a key->token mapping to the table
|
||||||
// probably a stdlib thing
|
* if SyncTablesWithOSEnviron is true, will also add value to os environment
|
||||||
|
* will not do so for non stringable tokens
|
||||||
|
*/
|
||||||
func SetVar(variable string, value *Token, vt VarTable) {
|
func SetVar(variable string, value *Token, vt VarTable) {
|
||||||
(*vt)[variable] = value
|
(*vt)[variable] = value
|
||||||
if SyncTablesWithOSEnviron &&
|
if SyncTablesWithOSEnviron &&
|
||||||
|
|
@ -85,22 +95,9 @@ func ListVars(vt VarTable) []string {
|
||||||
return keys
|
return keys
|
||||||
}
|
}
|
||||||
|
|
||||||
// Library represents variables defined in inner scope
|
/* if SyncTablesWithOSEnviron is true
|
||||||
// It is assumed library is ordered from innermost scope to outermost scope
|
* function will put ever environment variable into VarTable
|
||||||
func GetVarFromTables(arg string, library []VarTable) *Token {
|
*/
|
||||||
var res *Token
|
|
||||||
res = nil
|
|
||||||
for i := 0; i < len(library); i += 1 {
|
|
||||||
res = GetVar(arg, library[i])
|
|
||||||
if res != nil {
|
|
||||||
// TODO: Log scope res was found in?
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func InitVarTable(table VarTable) {
|
func InitVarTable(table VarTable) {
|
||||||
if !SyncTablesWithOSEnviron {
|
if !SyncTablesWithOSEnviron {
|
||||||
return
|
return
|
||||||
|
|
@ -133,7 +130,10 @@ func DeleteVarTable(table VarTable) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
a
|
||||||
|
/* removes var from vartable
|
||||||
|
* if SyncTablesWithOSENviron is true, also unsets environment variable
|
||||||
|
*/
|
||||||
func RemoveVar(arg string, table VarTable) {
|
func RemoveVar(arg string, table VarTable) {
|
||||||
if SyncTablesWithOSEnviron {
|
if SyncTablesWithOSEnviron {
|
||||||
err := os.Unsetenv(arg)
|
err := os.Unsetenv(arg)
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
package util
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"gitlab.com/whom/shs/log"
|
"gitlab.com/whom/shs/log"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue