diff --git a/pkg/shsh/.parsers.go.swp b/.token.go.swp similarity index 79% rename from pkg/shsh/.parsers.go.swp rename to .token.go.swp index 38eb4f4..a658897 100644 Binary files a/pkg/shsh/.parsers.go.swp and b/.token.go.swp differ diff --git a/cmd/shsh/shsh.go b/cmd/shsh/shsh.go index ef87a6c..ddc4e0f 100644 --- a/cmd/shsh/shsh.go +++ b/cmd/shsh/shsh.go @@ -9,6 +9,6 @@ import ( func main() { scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { - PrintSExpression(Lex(scanner.Text())) + shsh.PrintSExpression(shsh.Lex(scanner.Text())) } } diff --git a/pkg/shsh/debug.go b/debug.go similarity index 62% rename from pkg/shsh/debug.go rename to debug.go index 290720e..d6bc4b8 100644 --- a/pkg/shsh/debug.go +++ b/debug.go @@ -6,9 +6,9 @@ import ( ) func FmtToken(arg *Token) string { - suffix := "" - if arg.next != nil { - suffix = "->" + suffix := "->" + if arg.next == nil { + suffix = "" } switch arg.tag { @@ -37,6 +37,10 @@ func GetTagAsStr(tag token_t) string { } func PrintSExpression(arg *Token) { + if arg == nil { + return //TODO: Handle error here? + } + var lists TokenStack; lists.Push(arg) @@ -47,10 +51,20 @@ loop: return } - for iter := i; iter != nil; iter = i.next { + for iter := i; iter != nil; iter = iter.next { + if iter.tag == LIST { + lists.Push(iter._inner.(*Token)) + constructor.WriteString(FmtToken(&Token{ + next: iter.next, + tag: STRING, + position: iter.position, + _inner: "[LIST]"})) + continue + } + constructor.WriteString(FmtToken(iter)) } - print(constructor.String()) + println(constructor.String()) goto loop } diff --git a/pkg/shsh/func_table.go b/func_table.go similarity index 100% rename from pkg/shsh/func_table.go rename to func_table.go diff --git a/pkg/shsh/stack.go b/stack.go similarity index 100% rename from pkg/shsh/stack.go rename to stack.go diff --git a/pkg/shsh/token.go b/token.go similarity index 55% rename from pkg/shsh/token.go rename to token.go index 24805e1..4a954a2 100644 --- a/pkg/shsh/token.go +++ b/token.go @@ -21,15 +21,44 @@ type Token struct { } func Lex(input string) *Token { - ret := new(Token) + if len(input) == 0 { + return nil + } + + var ret *Token iter := &ret delim := ' ' var tok strings.Builder - iter_alloced := false is_list := false is_str := false is_num := true + tokenBuilder := func (pos int, tok string) { + *iter = new(Token) + (*iter).position = pos + + if is_list { + (*iter)._inner = Lex(tok) + (*iter).tag = LIST + is_list = false + + } else { + (*iter)._inner = tok + if is_str { + (*iter).tag = STRING + is_str = false + + } else if is_num { + (*iter).tag = NUMBER + + } else { + (*iter).tag = SYMBOL + } + } + + iter = &(*iter).next + } + for pos, char := range input { switch char { // TODO: User configurable delimiters @@ -41,43 +70,23 @@ func Lex(input string) *Token { delim = ')' case delim: - *iter = new(Token) - (*iter).position = pos - - if is_list { - (*iter)._inner = Lex(tok.String()) - is_list = false - (*iter)._inner = LIST - - } else { - (*iter)._inner = tok.String() - if is_str { - (*iter).tag = STRING - is_str = false - - } else if is_num { - (*iter).tag = NUMBER - - } else { - (*iter).tag = SYMBOL - } + delim = ' ' + if tok.Len() == 0 { + continue } - iter_alloced = true - delim = ' ' + tokenBuilder(pos, tok.String()) + tok.Reset() default: is_num = is_num && unicode.IsDigit(char) tok.WriteRune(char) } - - if iter_alloced { - iter = &((*iter).next) - iter_alloced = false - tok.Reset() - } } - // TODO: Throw parsing error here if there is leftover in tok + if tok.Len() > 0 { + tokenBuilder(len(input), tok.String()) + } + return ret } diff --git a/pkg/shsh/var_table.go b/var_table.go similarity index 100% rename from pkg/shsh/var_table.go rename to var_table.go