remove special-case : ; from parser
This commit is contained in:
		
							
								
								
									
										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")
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user