Wow! finished function table, almost finished with lexing as a whole
This commit is contained in:
parent
bb070592a6
commit
8643824bb6
5 changed files with 97 additions and 116 deletions
BIN
pkg/shsh/.token.go.swp
Normal file
BIN
pkg/shsh/.token.go.swp
Normal file
Binary file not shown.
58
pkg/shsh/func_table.go
Normal file
58
pkg/shsh/func_table.go
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
package shsh
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Operation func(*Token) *Token
|
||||||
|
|
||||||
|
type Function struct {
|
||||||
|
func operation
|
||||||
|
timesCalled int
|
||||||
|
args int
|
||||||
|
}
|
||||||
|
|
||||||
|
type FuncTable map[string]*Function
|
||||||
|
|
||||||
|
var (
|
||||||
|
GlobalFuncTable *FuncTable
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: Currently only checks arg list length
|
||||||
|
func ParseFunction(target *Function, args *Token) bool {
|
||||||
|
// HANDLE EXEC
|
||||||
|
if target.args < 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
i := target.args
|
||||||
|
for iter = &args; *iter; iter = &(*iter.next) {
|
||||||
|
i -= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if i != 0 {
|
||||||
|
// log error here?
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func CallFunction(target *Function, args *Token) *Token {
|
||||||
|
if !ParseFunction(target, args) {
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
|
||||||
|
target.timesCalled += 1
|
||||||
|
return target.operation(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetFunction(string arg) *Function {
|
||||||
|
target, ok := GlobalFuncTable[arg]
|
||||||
|
if !ok {
|
||||||
|
// TODO: hook into stdlib exec call
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
package shsh
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"unicode"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* LIST: a list of elements
|
|
||||||
* OPERAND: a string or number
|
|
||||||
* OPERATOR: an entry in a symtable
|
|
||||||
* OPERATION: a list starting with an operator
|
|
||||||
*/
|
|
||||||
type parse_tag int
|
|
||||||
const (
|
|
||||||
LIST_T parse_tag = iota
|
|
||||||
SYMBOL_T parse_tag = iota
|
|
||||||
OPERAND_T parse_tag = iota
|
|
||||||
OPERATION_T parse_tag = iota
|
|
||||||
)
|
|
||||||
|
|
||||||
func Parse(arg *Token) {
|
|
||||||
switch arg.tag {
|
|
||||||
case LIST_T:
|
|
||||||
for i := arg; i; i = i.next {
|
|
||||||
Parse(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
if list_is_operation(arg) {
|
|
||||||
arg.tag = OPERATION_T
|
|
||||||
}
|
|
||||||
|
|
||||||
case OPERAND_T:
|
|
||||||
if string_is_symbol(arg._inner) {
|
|
||||||
arg.tag = SYMBOL_T
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
;// TODO: Tag a parse error?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func string_delimiters_valid(arg string) bool {
|
|
||||||
delim := arg[0]
|
|
||||||
iter := 0
|
|
||||||
|
|
||||||
if delim != arg[len(arg) - 1] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, r := range arg {
|
|
||||||
if delim == r {
|
|
||||||
iter += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return iter == 2
|
|
||||||
}
|
|
||||||
|
|
||||||
func list_is_operation(arg *Token) bool {
|
|
||||||
// TODO: Rewrite after implementing a symbol table
|
|
||||||
//return ((*Token) arg._inner).tag == OPERATOR_T
|
|
||||||
}
|
|
||||||
|
|
||||||
// theres probly a way better way to do it.
|
|
||||||
func string_is_symbol(arg string) bool {
|
|
||||||
for _, r := range arg {
|
|
||||||
if !unicode.IsLetter(r) && r != '_' {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
package shsh
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type operation func(*Token) *Token
|
|
||||||
type symbol_tag int
|
|
||||||
const (
|
|
||||||
SYM_OPERATOR symbol_tag = iota,
|
|
||||||
SYM_VARIABLE symbol_tag = iota
|
|
||||||
)
|
|
||||||
|
|
||||||
type bucket struct {
|
|
||||||
symbol string
|
|
||||||
tag symbol_tag
|
|
||||||
_inner interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type sym_table []bucket
|
|
||||||
const initial_table_length 10
|
|
||||||
var (
|
|
||||||
global_sym_table sym_table
|
|
||||||
)
|
|
||||||
|
|
||||||
func extend_table() {}
|
|
||||||
|
|
||||||
// TODO: take in a table as a target, so that inner scopes can be appended to outer scopes
|
|
||||||
func set_variable(key string, val string) {}
|
|
||||||
func get_variable(arg string) string {}
|
|
||||||
func set_operator(key string, val operation) {}
|
|
||||||
func get_operator(arg string) operation {}
|
|
||||||
|
|
@ -4,24 +4,37 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type token_t int
|
||||||
|
const (
|
||||||
|
LIST token_t = iota
|
||||||
|
STRING token_t = iota
|
||||||
|
NUMBER token_t = iota
|
||||||
|
VARIABLE token_t = iota
|
||||||
|
FUNCTION token_t = iota
|
||||||
|
)
|
||||||
|
|
||||||
type Token struct {
|
type Token struct {
|
||||||
next *Token
|
next *Token
|
||||||
tag parse_tag
|
tag parse_tag
|
||||||
|
int position
|
||||||
_inner interface{}
|
_inner interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Lex(input string) Token {
|
func Lex(input string) *Token {
|
||||||
ret := new(Token)
|
ret := new(Token)
|
||||||
iter := &ret
|
iter := &ret
|
||||||
delim := ' '
|
delim := ' '
|
||||||
var tok strings.Builder
|
var tok strings.Builder
|
||||||
iter_alloced := false
|
iter_alloced := false
|
||||||
is_list = false;
|
is_list = false
|
||||||
|
is_str = false
|
||||||
|
is_num = true
|
||||||
|
|
||||||
for pos, char := range input {
|
for pos, char := range input {
|
||||||
switch char {
|
switch char {
|
||||||
// TODO: User configurable delimiters
|
// TODO: User configurable delimiters
|
||||||
case '\'', '"', '`':
|
case '\'', '"', '`':
|
||||||
|
is_str = true
|
||||||
delim = char
|
delim = char
|
||||||
case '(':
|
case '(':
|
||||||
is_list = true
|
is_list = true
|
||||||
|
|
@ -29,22 +42,41 @@ func Lex(input string) Token {
|
||||||
|
|
||||||
case delim:
|
case delim:
|
||||||
*iter = new(Token)
|
*iter = new(Token)
|
||||||
|
*iter.position = pos
|
||||||
|
|
||||||
if is_list {
|
if is_list {
|
||||||
// TODO: Pass a pointer out of Lex and store a pointer
|
// TODO: Pass a pointer out of Lex and store a pointer
|
||||||
*iter._inner = Lex(tok.String())
|
*iter._inner = Lex(tok.String())
|
||||||
*iter.tag = LIST_T
|
|
||||||
is_list = false
|
is_list = false
|
||||||
|
|
||||||
|
if (*iter._inner.tag == FUNCTION) {
|
||||||
|
*iter.tag = CALL
|
||||||
|
} else {
|
||||||
|
*iter.tag = LIST
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// TODO: Store a pointer to the contents of the stringbuilder
|
|
||||||
*iter._inner = tok.String()
|
*iter._inner = tok.String()
|
||||||
*iter.tag = OPERAND_T
|
if is_string {
|
||||||
|
*iter.tag = STRING
|
||||||
|
is_str = false
|
||||||
|
|
||||||
|
} else if is_num {
|
||||||
|
*iter.tag = NUMBER
|
||||||
|
|
||||||
|
} else if () {
|
||||||
|
// TODO: Detect VARIABLE
|
||||||
|
|
||||||
|
} else {
|
||||||
|
*iter.tag = FUNCTION
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iter_alloced = true
|
iter_alloced = true
|
||||||
delim = ' '
|
delim = ' '
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
is_num = is_num && IsDigit(char)
|
||||||
tok.WriteRune(char)
|
tok.WriteRune(char)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,10 +86,7 @@ func Lex(input string) Token {
|
||||||
tok.Reset()
|
tok.Reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func eval(Token *tree) *Token {
|
// TODO: Throw parsing error here if there is leftover in tok
|
||||||
// Find operations
|
return ret
|
||||||
// Simplify operations deepest first
|
|
||||||
// return tree of final Tokens
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue