remove special-case : ; from parser
This commit is contained in:
parent
e5bb216f95
commit
7c76bc49af
17
builtins.go
17
builtins.go
@ -8,6 +8,23 @@ type Builtins struct{}
|
|||||||
// ErrExit is a special sentinel value to cease computation and quit
|
// ErrExit is a special sentinel value to cease computation and quit
|
||||||
var ErrExit = fmt.Errorf("exit requested")
|
var ErrExit = fmt.Errorf("exit requested")
|
||||||
|
|
||||||
|
// Colon sets the COMPILE/IMMEDIATE flag to COMPILE
|
||||||
|
func (b *Builtins) Colon(f *bool) func() error {
|
||||||
|
return func() error {
|
||||||
|
*f = false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Semicolon sets the COMPILE/IMMEDIATE flag back to IMMEDIATE and adds the defintion to the dictionary
|
||||||
|
func (b *Builtins) Semicolon(c *Context) func() error {
|
||||||
|
return func() error {
|
||||||
|
c.Dictionary.AddWord(c.Words[0], nil, c.Words[1:], false)
|
||||||
|
c.Immediate = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Eq compares TOS and NOS and puts -1 on the stack if they're equal, 0 otherwise.
|
// Eq compares TOS and NOS and puts -1 on the stack if they're equal, 0 otherwise.
|
||||||
func (b *Builtins) Eq(s *Stack) func() error {
|
func (b *Builtins) Eq(s *Stack) func() error {
|
||||||
return func() error {
|
return func() error {
|
||||||
|
24
eval.go
24
eval.go
@ -11,15 +11,15 @@ type Context struct {
|
|||||||
Dictionary Dictionary
|
Dictionary Dictionary
|
||||||
Stack *Stack
|
Stack *Stack
|
||||||
RStack *Stack
|
RStack *Stack
|
||||||
|
Immediate bool
|
||||||
|
Words []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Eval evaulates a given line, recursively descending into given words as needed
|
// Eval evaulates a given line, recursively descending into given words as needed
|
||||||
func (c *Context) Eval(line string) error {
|
func (c *Context) Eval(line string) error {
|
||||||
// state
|
// state
|
||||||
var word []byte
|
var word []byte
|
||||||
var words []string
|
|
||||||
var comment bool
|
var comment bool
|
||||||
immediate := true
|
|
||||||
|
|
||||||
for i := 0; i < len(line); i = i + 1 {
|
for i := 0; i < len(line); i = i + 1 {
|
||||||
switch line[i] {
|
switch line[i] {
|
||||||
@ -34,28 +34,16 @@ func (c *Context) Eval(line string) error {
|
|||||||
} else {
|
} else {
|
||||||
word = append(word, line[i])
|
word = append(word, line[i])
|
||||||
}
|
}
|
||||||
case ':', ';': // COMPILE/IMMEDIATE mode swapping
|
|
||||||
if len(word) == 0 {
|
|
||||||
if line[i] == ':' {
|
|
||||||
immediate = false
|
|
||||||
} else if line[i-1] == ' ' && line[i] == ';' {
|
|
||||||
c.Dictionary.AddWord(words[0], nil, words[1:], false)
|
|
||||||
word = []byte{}
|
|
||||||
immediate = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
word = append(word, line[i])
|
|
||||||
}
|
|
||||||
case ' ':
|
case ' ':
|
||||||
sword := strings.TrimSpace(string(word))
|
sword := strings.TrimSpace(string(word))
|
||||||
if !immediate { // continue building our subroutine if we're not in immediate mode...
|
if !c.Immediate { // continue building our subroutine if we're not in immediate mode...
|
||||||
if len(word) != 0 { // don't add empty words to our list
|
if len(word) != 0 { // don't add empty words to our list
|
||||||
// Was that a word we know?
|
// Was that a word we know?
|
||||||
w, _ := c.Dictionary.GetWord(sword)
|
w, _ := c.Dictionary.GetWord(sword)
|
||||||
// check if it's an IMMEDIATE mode toggle word
|
// check if it's an IMMEDIATE mode toggle word
|
||||||
immediate = w.Immediate
|
c.Immediate = w.Immediate
|
||||||
if !immediate {
|
if !c.Immediate {
|
||||||
words = append(words, sword)
|
c.Words = append(c.Words, sword)
|
||||||
word = []byte{}
|
word = []byte{}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
31
main.go
31
main.go
@ -13,12 +13,29 @@ func main() {
|
|||||||
rstack := Stack{values: []int{}}
|
rstack := Stack{values: []int{}}
|
||||||
|
|
||||||
dict := Dictionary{}
|
dict := Dictionary{}
|
||||||
|
|
||||||
|
c := Context{
|
||||||
|
Dictionary: dict,
|
||||||
|
Stack: &stack,
|
||||||
|
RStack: &rstack,
|
||||||
|
Immediate: true,
|
||||||
|
Words: []string{},
|
||||||
|
}
|
||||||
|
|
||||||
b := &Builtins{}
|
b := &Builtins{}
|
||||||
|
// word definitions
|
||||||
|
dict.AddWord(":", b.Colon(&c.Immediate), nil, false)
|
||||||
|
dict.AddWord(";", b.Semicolon(&c), nil, true)
|
||||||
|
// math
|
||||||
dict.AddWord("+", b.Add(&stack), nil, false)
|
dict.AddWord("+", b.Add(&stack), nil, false)
|
||||||
dict.AddWord("-", b.Sub(&stack), nil, false)
|
dict.AddWord("-", b.Sub(&stack), nil, false)
|
||||||
dict.AddWord("*", b.Mul(&stack), nil, false)
|
dict.AddWord("*", b.Mul(&stack), nil, false)
|
||||||
dict.AddWord("/", b.Div(&stack), nil, false)
|
dict.AddWord("/", b.Div(&stack), nil, false)
|
||||||
|
// output
|
||||||
dict.AddWord(".", b.Print(&stack), nil, false)
|
dict.AddWord(".", b.Print(&stack), nil, false)
|
||||||
|
dict.AddWord("EMIT", b.Emit(&stack), nil, false)
|
||||||
|
dict.AddWord("CR", b.CR(), nil, false)
|
||||||
|
// logic
|
||||||
dict.AddWord("=", b.Eq(&stack), nil, false)
|
dict.AddWord("=", b.Eq(&stack), nil, false)
|
||||||
dict.AddWord("0=", nil, []string{"0", "="}, false)
|
dict.AddWord("0=", nil, []string{"0", "="}, false)
|
||||||
dict.AddWord("<>", b.NEq(&stack), nil, false)
|
dict.AddWord("<>", b.NEq(&stack), nil, false)
|
||||||
@ -28,29 +45,25 @@ func main() {
|
|||||||
dict.AddWord("<=", b.LtEq(&stack), nil, false)
|
dict.AddWord("<=", b.LtEq(&stack), nil, false)
|
||||||
dict.AddWord("0<", nil, []string{"0", "<"}, false)
|
dict.AddWord("0<", nil, []string{"0", "<"}, false)
|
||||||
dict.AddWord("0>", nil, []string{"0", ">"}, false)
|
dict.AddWord("0>", nil, []string{"0", ">"}, false)
|
||||||
|
// stack manipulation
|
||||||
dict.AddWord("DUP", b.Dup(&stack), nil, false)
|
dict.AddWord("DUP", b.Dup(&stack), nil, false)
|
||||||
dict.AddWord("SWAP", b.Swap(&stack), nil, false)
|
dict.AddWord("SWAP", b.Swap(&stack), nil, false)
|
||||||
dict.AddWord("OVER", b.Over(&stack), nil, false)
|
dict.AddWord("OVER", b.Over(&stack), nil, false)
|
||||||
dict.AddWord("DROP", b.Drop(&stack), nil, false)
|
dict.AddWord("DROP", b.Drop(&stack), nil, false)
|
||||||
dict.AddWord("ROT", b.Rot(&stack), nil, false)
|
dict.AddWord("ROT", b.Rot(&stack), nil, false)
|
||||||
|
// debugging
|
||||||
dict.AddWord("WORDS", b.Words(dict), nil, false)
|
dict.AddWord("WORDS", b.Words(dict), nil, false)
|
||||||
dict.AddWord(".S", b.Debug(&stack), nil, false)
|
dict.AddWord(".S", b.Debug(&stack), nil, false)
|
||||||
dict.AddWord(".R", b.Debug(&rstack), nil, false)
|
dict.AddWord(".R", b.Debug(&rstack), nil, false)
|
||||||
dict.AddWord("EMIT", b.Emit(&stack), nil, false)
|
|
||||||
dict.AddWord("R>", b.RFrom(&stack, &rstack), nil, false)
|
dict.AddWord("R>", b.RFrom(&stack, &rstack), nil, false)
|
||||||
dict.AddWord(">R", b.ToR(&stack, &rstack), nil, false)
|
dict.AddWord(">R", b.ToR(&stack, &rstack), nil, false)
|
||||||
dict.AddWord("R@", b.RFetch(&stack, &rstack), nil, false)
|
dict.AddWord("R@", b.RFetch(&stack, &rstack), nil, false)
|
||||||
|
// branching
|
||||||
dict.AddWord("DO", b.Do(&stack, &rstack), nil, false)
|
dict.AddWord("DO", b.Do(&stack, &rstack), nil, false)
|
||||||
dict.AddWord("LOOP", b.Loop(&stack, &rstack), nil, false)
|
dict.AddWord("LOOP", b.Loop(&stack, &rstack), nil, false)
|
||||||
dict.AddWord("I", b.I(&stack, &rstack), nil, false)
|
dict.AddWord("I", b.I(&stack, &rstack), nil, false)
|
||||||
dict.AddWord("CR", b.CR(), nil, false)
|
// exit
|
||||||
dict.AddWord("QUIT", b.Quit(), nil, false)
|
dict.AddWord("BYE", b.Quit(), nil, false)
|
||||||
|
|
||||||
c := Context{
|
|
||||||
Dictionary: dict,
|
|
||||||
Stack: &stack,
|
|
||||||
RStack: &rstack,
|
|
||||||
}
|
|
||||||
|
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
fmt.Print("prosper")
|
fmt.Print("prosper")
|
||||||
|
Loading…
Reference in New Issue
Block a user