It builds
This commit is contained in:
parent
7aa80376bb
commit
7e175dec95
7 changed files with 52 additions and 45 deletions
|
|
@ -0,0 +1,14 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"os"
|
||||||
|
"shsh"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
|
for scanner.Scan() {
|
||||||
|
PrintSExpression(Lex(scanner.Text()))
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
|
@ -2,6 +2,7 @@ package shsh
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func FmtToken(arg *Token) string {
|
func FmtToken(arg *Token) string {
|
||||||
|
|
@ -12,11 +13,11 @@ func FmtToken(arg *Token) string {
|
||||||
|
|
||||||
switch arg.tag {
|
switch arg.tag {
|
||||||
case LIST:
|
case LIST:
|
||||||
return sprintf("(%s, List @ %p, %d)%s", "LIST", arg._inner,
|
return fmt.Sprintf("(%s, List @ %p, %d)%s", "LIST", arg._inner,
|
||||||
arg.position, suffix)
|
arg.position, suffix)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return sprintf("(%s, %s, %d)%s", GetTagAsStr(arg.tag), arg._inner,
|
return fmt.Sprintf("(%s, %s, %d)%s", GetTagAsStr(arg.tag), arg._inner,
|
||||||
arg.position, suffix)
|
arg.position, suffix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -32,26 +33,24 @@ func GetTagAsStr(tag token_t) string {
|
||||||
case SYMBOL:
|
case SYMBOL:
|
||||||
return "SYMBOL"
|
return "SYMBOL"
|
||||||
}
|
}
|
||||||
|
return "UNKNOWN"
|
||||||
}
|
}
|
||||||
|
|
||||||
func PrintSExpression(arg *Token) {
|
func PrintSExpression(arg *Token) {
|
||||||
var lists Stack;
|
var lists TokenStack;
|
||||||
lists.push(arg)
|
lists.Push(arg)
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
var constructor strings.Builder
|
var constructor strings.Builder
|
||||||
i := lists.pop()
|
i := lists.Pop()
|
||||||
if i == nil {
|
if i == nil {
|
||||||
goto done
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for (iter := i; iter != nil; iter = i.next {
|
for iter := i; iter != nil; iter = i.next {
|
||||||
constructor.WriteString(FmtToken(iter))
|
constructor.WriteString(FmtToken(iter))
|
||||||
}
|
}
|
||||||
|
|
||||||
print(constructor.String())
|
print(constructor.String())
|
||||||
goto loop
|
goto loop
|
||||||
|
|
||||||
done:
|
|
||||||
// TODO: Perhaps print some debug analytics here
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,9 @@
|
||||||
package shsh
|
package shsh
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Operation func(*Token) *Token
|
type Operation func(*Token) *Token
|
||||||
|
|
||||||
type Function struct {
|
type Function struct {
|
||||||
func operation
|
function Operation
|
||||||
timesCalled int
|
timesCalled int
|
||||||
args int
|
args int
|
||||||
}
|
}
|
||||||
|
|
@ -26,7 +22,7 @@ func ParseFunction(target *Function, args *Token) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
i := target.args
|
i := target.args
|
||||||
for iter = &args; *iter; iter = &(*iter.next) {
|
for iter := &args; *iter != nil; iter = &((*iter).next) {
|
||||||
i -= 1
|
i -= 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,11 +40,11 @@ func CallFunction(target *Function, args *Token) *Token {
|
||||||
}
|
}
|
||||||
|
|
||||||
target.timesCalled += 1
|
target.timesCalled += 1
|
||||||
return target.operation(args)
|
return target.function(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetFunction(string arg) *Function {
|
func GetFunction(arg string) *Function {
|
||||||
target, ok := GlobalFuncTable[arg]
|
target, ok := (*GlobalFuncTable)[arg]
|
||||||
if !ok {
|
if !ok {
|
||||||
// TODO: hook into stdlib exec call
|
// TODO: hook into stdlib exec call
|
||||||
;
|
;
|
||||||
|
|
|
||||||
|
|
@ -2,21 +2,21 @@ package shsh
|
||||||
|
|
||||||
type TokenStack struct {
|
type TokenStack struct {
|
||||||
buffer []*Token
|
buffer []*Token
|
||||||
int capacity
|
capacity int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stack) 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stack) Pop() *Token {
|
func (s *TokenStack) Pop() *Token {
|
||||||
if s.capacity <= 0 {
|
if s.capacity <= 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
s.capacity--
|
s.capacity--
|
||||||
res := *s.buffer[len(*s.buffer) - 1]
|
res := s.buffer[len(s.buffer) - 1]
|
||||||
*s = *s.buffer[ :len(*s) - 1]
|
s.buffer = s.buffer[:len(s.buffer) - 1]
|
||||||
return ret
|
return res
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package shsh;
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
type token_t int
|
type token_t int
|
||||||
|
|
@ -15,7 +16,7 @@ const (
|
||||||
type Token struct {
|
type Token struct {
|
||||||
next *Token
|
next *Token
|
||||||
tag token_t
|
tag token_t
|
||||||
int position
|
position int
|
||||||
_inner interface{}
|
_inner interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -25,9 +26,9 @@ func Lex(input string) *Token {
|
||||||
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_str := false
|
||||||
is_num = true
|
is_num := true
|
||||||
|
|
||||||
for pos, char := range input {
|
for pos, char := range input {
|
||||||
switch char {
|
switch char {
|
||||||
|
|
@ -41,24 +42,24 @@ func Lex(input string) *Token {
|
||||||
|
|
||||||
case delim:
|
case delim:
|
||||||
*iter = new(Token)
|
*iter = new(Token)
|
||||||
*iter.position = pos
|
(*iter).position = pos
|
||||||
|
|
||||||
if is_list {
|
if is_list {
|
||||||
*iter._inner = Lex(tok.String())
|
(*iter)._inner = Lex(tok.String())
|
||||||
is_list = false
|
is_list = false
|
||||||
*iter._inner = LIST
|
(*iter)._inner = LIST
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
*iter._inner = tok.String()
|
(*iter)._inner = tok.String()
|
||||||
if is_string {
|
if is_str {
|
||||||
*iter.tag = STRING
|
(*iter).tag = STRING
|
||||||
is_str = false
|
is_str = false
|
||||||
|
|
||||||
} else if is_num {
|
} else if is_num {
|
||||||
*iter.tag = NUMBER
|
(*iter).tag = NUMBER
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
*iter.tag = SYMBOL
|
(*iter).tag = SYMBOL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,12 +67,12 @@ func Lex(input string) *Token {
|
||||||
delim = ' '
|
delim = ' '
|
||||||
|
|
||||||
default:
|
default:
|
||||||
is_num = is_num && IsDigit(char)
|
is_num = is_num && unicode.IsDigit(char)
|
||||||
tok.WriteRune(char)
|
tok.WriteRune(char)
|
||||||
}
|
}
|
||||||
|
|
||||||
if iter_alloced {
|
if iter_alloced {
|
||||||
iter = &(*iter.next)
|
iter = &((*iter).next)
|
||||||
iter_alloced = false
|
iter_alloced = false
|
||||||
tok.Reset()
|
tok.Reset()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,5 @@
|
||||||
package shsh
|
package shsh
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type VarTable map[string]*Token
|
type VarTable map[string]*Token
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -13,9 +9,10 @@ var (
|
||||||
// Library represents variables defined in inner scope
|
// Library represents variables defined in inner scope
|
||||||
// It is assumed library is ordered from innermost scope to outermost scope
|
// It is assumed library is ordered from innermost scope to outermost scope
|
||||||
func GetVar(arg string, library []VarTable) *Token {
|
func GetVar(arg string, library []VarTable) *Token {
|
||||||
for dict, scope := library {
|
for scope, dict := range library {
|
||||||
val, ok := dict[arg]
|
val, ok := dict[arg]
|
||||||
if ok {
|
if ok {
|
||||||
|
scope = scope // TEMP LINE
|
||||||
// TODO: maybe log which scope it was found in?
|
// TODO: maybe log which scope it was found in?
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue