ast package full godoc

This commit is contained in:
Aidan 2020-07-18 14:40:35 -07:00
parent 956044cfae
commit fec3550702
No known key found for this signature in database
GPG key ID: 327711E983899316
7 changed files with 68 additions and 26 deletions

View file

@ -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

View file

@ -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))

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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"