misc/kforth: Start command processing.
This commit is contained in:
		
							parent
							
								
									0a010e4527
								
							
						
					
					
						commit
						14dc525084
					
				
							
								
								
									
										6
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										6
									
								
								Makefile
								
								
								
								
							| 
						 | 
				
			
			@ -3,6 +3,8 @@ CXXFLAGS :=	-std=$(CXXSTD) -Wall -Werror -g -O0
 | 
			
		|||
OBJS :=		linux/io.o	\
 | 
			
		||||
		io.o		\
 | 
			
		||||
		parser.o	\
 | 
			
		||||
		word.o		\
 | 
			
		||||
		dict.o		\
 | 
			
		||||
		kforth.o
 | 
			
		||||
TARGET :=	kforth
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -13,3 +15,7 @@ $(TARGET): $(OBJS)
 | 
			
		|||
 | 
			
		||||
clean:
 | 
			
		||||
	rm -f $(OBJS) $(TARGET)
 | 
			
		||||
 | 
			
		||||
install: $(TARGET)
 | 
			
		||||
	cp $(TARGET) ~/bin
 | 
			
		||||
	chmod 0755 ~/bin/$(TARGET)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,178 @@
 | 
			
		|||
#include "defs.h"
 | 
			
		||||
#include "dict.h"
 | 
			
		||||
#include "stack.h"
 | 
			
		||||
#include "system.h"
 | 
			
		||||
#include "word.h"
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
add(System *sys)
 | 
			
		||||
{
 | 
			
		||||
	KF_INT	a = 0;
 | 
			
		||||
	KF_INT	b = 0;
 | 
			
		||||
	if (!sys->dstack.pop(&a)) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if (!sys->dstack.pop(&b)) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	a += b;
 | 
			
		||||
	return sys->dstack.push(a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
sub(System *sys)
 | 
			
		||||
{
 | 
			
		||||
	KF_INT	a = 0;
 | 
			
		||||
	KF_INT	b = 0;
 | 
			
		||||
	if (!sys->dstack.pop(&a)) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if (!sys->dstack.pop(&b)) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	b -= a;
 | 
			
		||||
	return sys->dstack.push(b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
mul(System *sys)
 | 
			
		||||
{
 | 
			
		||||
	KF_INT	a = 0;
 | 
			
		||||
	KF_INT	b = 0;
 | 
			
		||||
	if (!sys->dstack.pop(&a)) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if (!sys->dstack.pop(&b)) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	b *= a;
 | 
			
		||||
	return sys->dstack.push(b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
div(System *sys)
 | 
			
		||||
{
 | 
			
		||||
	KF_INT	a = 0;
 | 
			
		||||
	KF_INT	b = 0;
 | 
			
		||||
	if (!sys->dstack.pop(&a)) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if (!sys->dstack.pop(&b)) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	b *= a;
 | 
			
		||||
	return sys->dstack.push(b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
swap(System *sys)
 | 
			
		||||
{
 | 
			
		||||
	KF_INT	a = 0;
 | 
			
		||||
	KF_INT	b = 0;
 | 
			
		||||
	if (!sys->dstack.pop(&a)) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if (!sys->dstack.pop(&b)) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if (!sys->dstack.push(a)) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return sys->dstack.push(b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
rot(System *sys)
 | 
			
		||||
{
 | 
			
		||||
	KF_INT	a = 0;
 | 
			
		||||
	KF_INT	b = 0;
 | 
			
		||||
	KF_INT	c = 0;
 | 
			
		||||
	if (!sys->dstack.pop(&a)) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if (!sys->dstack.pop(&b)) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if (!sys->dstack.pop(&c)) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if (!sys->dstack.push(b)) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if (!sys->dstack.push(a)) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return sys->dstack.push(c);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: print multiple per line
 | 
			
		||||
static bool
 | 
			
		||||
definitions(System *sys)
 | 
			
		||||
{
 | 
			
		||||
	Word	*cursor = dict;
 | 
			
		||||
	char	 buf[MAX_TOKEN_LENGTH];
 | 
			
		||||
	size_t	 buflen = 0;
 | 
			
		||||
	
 | 
			
		||||
	while (cursor != nullptr) {
 | 
			
		||||
		cursor->getname(buf, &buflen);
 | 
			
		||||
		sys->interface->wrln(buf, buflen);
 | 
			
		||||
		cursor = cursor->next();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
init_dict()
 | 
			
		||||
{
 | 
			
		||||
	dict = new Builtin((const char *)"DEFINITIONS", 11, dict, definitions);
 | 
			
		||||
	dict = new Builtin((const char *)"+", 1, dict, add);
 | 
			
		||||
	dict = new Builtin((const char *)"-", 1, dict, sub);
 | 
			
		||||
	dict = new Builtin((const char *)"*", 1, dict, mul);
 | 
			
		||||
	dict = new Builtin((const char *)"/", 1, dict, div);
 | 
			
		||||
	dict = new Builtin((const char *)"SWAP", 4, dict, swap);
 | 
			
		||||
	dict = new Builtin((const char *)"ROT", 3, dict, rot);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
LOOKUP
 | 
			
		||||
lookup(struct Token *token, System *sys)
 | 
			
		||||
{
 | 
			
		||||
	Word	*cursor = dict;
 | 
			
		||||
	KF_INT	 n;
 | 
			
		||||
	
 | 
			
		||||
	if (parse_num(token, &n)) {
 | 
			
		||||
		if (sys->dstack.push(n)) {
 | 
			
		||||
			return LOOKUP_OK;
 | 
			
		||||
		}
 | 
			
		||||
		return LOOKUP_FAILED;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	while (cursor != nullptr) {
 | 
			
		||||
		if (cursor->match(token)) {
 | 
			
		||||
			if (cursor->eval(sys)) {
 | 
			
		||||
				return LOOKUP_OK;
 | 
			
		||||
			}
 | 
			
		||||
			return LOOKUP_FAILED;
 | 
			
		||||
		}
 | 
			
		||||
		cursor = cursor->next();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return LOOKUP_NOTFOUND;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
#ifndef __KF_DICT_H__
 | 
			
		||||
#define __KF_DICT_H__
 | 
			
		||||
 | 
			
		||||
#include "defs.h"
 | 
			
		||||
#include "parser.h"
 | 
			
		||||
#include "system.h"
 | 
			
		||||
#include "word.h"
 | 
			
		||||
 | 
			
		||||
static	Word	*dict = nullptr;
 | 
			
		||||
 | 
			
		||||
typedef enum _LOOKUP_ : uint8_t {
 | 
			
		||||
	LOOKUP_OK = 0,	     // Lookup executed properly.
 | 
			
		||||
	LOOKUP_NOTFOUND = 1, // The token isn't in the dictionary.
 | 
			
		||||
	LOOKUP_FAILED = 2    // The word failed to execute.
 | 
			
		||||
} LOOKUP;
 | 
			
		||||
 | 
			
		||||
void	init_dict(void);
 | 
			
		||||
LOOKUP	lookup(struct Token *, System *);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // __KF_DICT_H__
 | 
			
		||||
| 
						 | 
				
			
			@ -10,6 +10,7 @@ Contents:
 | 
			
		|||
   part-0x02
 | 
			
		||||
   part-0x03
 | 
			
		||||
   part-0x04
 | 
			
		||||
   part-0x05
 | 
			
		||||
 | 
			
		||||
Indices and tables
 | 
			
		||||
==================
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
Write You a Forth, 0x05
 | 
			
		||||
-----------------------
 | 
			
		||||
 | 
			
		||||
:date: 2018-02-24 12:23
 | 
			
		||||
:tags: wyaf, forth
 | 
			
		||||
 | 
			
		||||
Today I need to start actually doing things with tokens. This requires two
 | 
			
		||||
things:
 | 
			
		||||
 | 
			
		||||
1. Some idea of what a word is, and
 | 
			
		||||
2. A dictionary of words
 | 
			
		||||
 | 
			
		||||
I started taking some notes on this previously, and I think there are a few
 | 
			
		||||
kinds of words that are possible:
 | 
			
		||||
 | 
			
		||||
1. Numbers (e.g. defining a variable)
 | 
			
		||||
2. Built-in functions
 | 
			
		||||
3. Lambda functions (that is, user-defined functions).
 | 
			
		||||
 | 
			
		||||
Stage 1 really only needs to incorporate #2, so that's what I'll focus on for
 | 
			
		||||
now. However, to prepare for the future, I'm going to define a ``Word`` base
 | 
			
		||||
class and inherit from there. This interface is going to need to be
 | 
			
		||||
stack-aware, so what I've done is define a ``System`` struct in ``system.h``::
 | 
			
		||||
 | 
			
		||||
        #ifndef __KF_CORE_H__
 | 
			
		||||
        #define __KF_CORE_H__
 | 
			
		||||
        
 | 
			
		||||
        #include "defs.h"
 | 
			
		||||
        #include "stack.h"
 | 
			
		||||
        
 | 
			
		||||
        typedef struct _System {
 | 
			
		||||
                Stack<KF_INT>        dstack;
 | 
			
		||||
        } System;
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
        #endif // __KF_CORE_H__
 | 
			
		||||
 | 
			
		||||
This will let me later add in support for the return stack and other things
 | 
			
		||||
that might be useful. Other ideas: adding something like an ``errno``
 | 
			
		||||
equivalent to indicate the last error, and storing a dictionary of words. This
 | 
			
		||||
will need some restructuring, though. Anyways, this works for now.
 | 
			
		||||
 | 
			
		||||
The Word interface
 | 
			
		||||
^^^^^^^^^^^^^^^^^^
 | 
			
		||||
 | 
			
		||||
Now I can start defining a Word.h.
 | 
			
		||||
							
								
								
									
										10
									
								
								io.cc
								
								
								
								
							
							
						
						
									
										10
									
								
								io.cc
								
								
								
								
							| 
						 | 
				
			
			@ -6,7 +6,7 @@
 | 
			
		|||
static constexpr size_t	nbuflen = 11;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
write_num(IO &interface, KF_INT n)
 | 
			
		||||
write_num(IO *interface, KF_INT n)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	// TODO(kyle): make the size of the buffer depend on the size of
 | 
			
		||||
| 
						 | 
				
			
			@ -17,8 +17,12 @@ write_num(IO &interface, KF_INT n)
 | 
			
		|||
	bool neg = n < 0;
 | 
			
		||||
 | 
			
		||||
	if (n < 0) {
 | 
			
		||||
		interface.wrch('-');
 | 
			
		||||
		interface->wrch('-');
 | 
			
		||||
		n = ~n;
 | 
			
		||||
		if (n == 0) {
 | 
			
		||||
			neg = false;
 | 
			
		||||
			n++;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (n != 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -30,5 +34,5 @@ write_num(IO &interface, KF_INT n)
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	uint8_t buflen = nbuflen - i % nbuflen;
 | 
			
		||||
	interface.wrbuf(buf+i, buflen);
 | 
			
		||||
	interface->wrbuf(buf+i, buflen);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								io.h
								
								
								
								
							
							
						
						
									
										2
									
								
								io.h
								
								
								
								
							| 
						 | 
				
			
			@ -21,7 +21,7 @@ public:
 | 
			
		|||
	virtual void	wrln(char *buf, size_t len) = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void	write_num(IO &, KF_INT);
 | 
			
		||||
void	write_num(IO *, KF_INT);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // __KF_IO_H__
 | 
			
		||||
							
								
								
									
										85
									
								
								kforth.cc
								
								
								
								
							
							
						
						
									
										85
									
								
								kforth.cc
								
								
								
								
							| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
#include "dict.h"
 | 
			
		||||
#include "io.h"
 | 
			
		||||
#include "parser.h"
 | 
			
		||||
#include "stack.h"
 | 
			
		||||
#include "system.h"
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -11,33 +12,33 @@
 | 
			
		|||
 | 
			
		||||
static char     ok[] = "ok.\n";
 | 
			
		||||
static char	bye[] = "bye";
 | 
			
		||||
 | 
			
		||||
// dstack is the data stack.
 | 
			
		||||
static Stack<KF_INT>	dstack;
 | 
			
		||||
static System	sys;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
write_dstack(IO &interface)
 | 
			
		||||
write_dstack()
 | 
			
		||||
{
 | 
			
		||||
	KF_INT	tmp;
 | 
			
		||||
	interface.wrch('<');
 | 
			
		||||
	for (size_t i = 0; i < dstack.size(); i++) {
 | 
			
		||||
	sys.interface->wrch('<');
 | 
			
		||||
	for (size_t i = 0; i < sys.dstack.size(); i++) {
 | 
			
		||||
		if (i > 0) {
 | 
			
		||||
			interface.wrch(' ');
 | 
			
		||||
			sys.interface->wrch(' ');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dstack.get(i, tmp);
 | 
			
		||||
		write_num(interface, tmp);
 | 
			
		||||
		sys.dstack.get(i, tmp);
 | 
			
		||||
		write_num(sys.interface, tmp);
 | 
			
		||||
	}
 | 
			
		||||
	interface.wrch('>');
 | 
			
		||||
	sys.interface->wrch('>');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
parser(IO &interface, const char *buf, const size_t buflen)
 | 
			
		||||
parser(const char *buf, const size_t buflen)
 | 
			
		||||
{
 | 
			
		||||
	static size_t		offset = 0;
 | 
			
		||||
	static struct Token	token;
 | 
			
		||||
	static PARSE_RESULT	result = PARSE_FAIL;
 | 
			
		||||
	static LOOKUP		lresult = LOOKUP_FAILED;
 | 
			
		||||
	static bool		stop = false;
 | 
			
		||||
 | 
			
		||||
	offset = 0;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -46,50 +47,66 @@ parser(IO &interface, const char *buf, const size_t buflen)
 | 
			
		|||
	token.length = 0;
 | 
			
		||||
 | 
			
		||||
	while ((result = parse_next(buf, buflen, &offset, &token)) == PARSE_OK) {
 | 
			
		||||
		interface.wrbuf((char *)"token: ", 7);
 | 
			
		||||
		interface.wrbuf(token.token, token.length);
 | 
			
		||||
		interface.wrln((char *)".", 1);
 | 
			
		||||
 | 
			
		||||
		if (!parse_num(&token, dstack)) {
 | 
			
		||||
			interface.wrln((char *)"failed to parse numeric", 23);
 | 
			
		||||
		lresult = lookup(&token, &sys);
 | 
			
		||||
		switch (lresult) {
 | 
			
		||||
		case LOOKUP_OK:
 | 
			
		||||
			continue;
 | 
			
		||||
		case LOOKUP_NOTFOUND:
 | 
			
		||||
			sys.interface->wrln((char *)"word not found", 15);
 | 
			
		||||
			stop = true;
 | 
			
		||||
			break;
 | 
			
		||||
		case LOOKUP_FAILED:
 | 
			
		||||
			sys.interface->wrln((char *)"execution failed", 17);
 | 
			
		||||
			stop = true;
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			sys.interface->wrln((char *)"*** the world is broken ***", 27);
 | 
			
		||||
			exit(1);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
		if (stop) {
 | 
			
		||||
			stop = false;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		// Temporary hack until the interpreter is working further.
 | 
			
		||||
		if (match_token(token.token, token.length, bye, 3)) {
 | 
			
		||||
			interface.wrln((char *)"Goodbye!", 8);
 | 
			
		||||
			sys.interface->wrln((char *)"Goodbye!", 8);
 | 
			
		||||
			exit(0);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (result) {
 | 
			
		||||
	case PARSE_OK:
 | 
			
		||||
		return false;
 | 
			
		||||
	case PARSE_EOB:
 | 
			
		||||
		interface.wrbuf(ok, 4);
 | 
			
		||||
		sys.interface->wrbuf(ok, 4);
 | 
			
		||||
		return true;
 | 
			
		||||
	case PARSE_LEN:
 | 
			
		||||
		interface.wrln((char *)"parse error: token too long", 27);
 | 
			
		||||
		sys.interface->wrln((char *)"parse error: token too long", 27);
 | 
			
		||||
		return false;
 | 
			
		||||
	case PARSE_FAIL:
 | 
			
		||||
		interface.wrln((char *)"parser failure", 14);
 | 
			
		||||
		sys.interface->wrln((char *)"parser failure", 14);
 | 
			
		||||
		return false;
 | 
			
		||||
	default:
 | 
			
		||||
		interface.wrln((char *)"*** the world is broken ***", 27);
 | 
			
		||||
		sys.interface->wrln((char *)"*** the world is broken ***", 27);
 | 
			
		||||
		exit(1);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
interpreter(IO &interface)
 | 
			
		||||
interpreter()
 | 
			
		||||
{
 | 
			
		||||
	static size_t buflen = 0;
 | 
			
		||||
	static char linebuf[81];
 | 
			
		||||
 | 
			
		||||
	while (true) {
 | 
			
		||||
		write_dstack(interface);
 | 
			
		||||
		interface.wrch('\n');
 | 
			
		||||
		interface.wrch('?');
 | 
			
		||||
		interface.wrch(' ');
 | 
			
		||||
		buflen = interface.rdbuf(linebuf, 80, true, '\n');
 | 
			
		||||
		parser(interface, linebuf, buflen);
 | 
			
		||||
		write_dstack();
 | 
			
		||||
		sys.interface->wrch('\n');
 | 
			
		||||
		sys.interface->wrch('?');
 | 
			
		||||
		sys.interface->wrch(' ');
 | 
			
		||||
		buflen = sys.interface->rdbuf(linebuf, 80, true, '\n');
 | 
			
		||||
		parser(linebuf, buflen);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -99,10 +116,12 @@ const size_t	bannerlen = 19;
 | 
			
		|||
int
 | 
			
		||||
main(void)
 | 
			
		||||
{
 | 
			
		||||
	init_dict();
 | 
			
		||||
#ifdef __linux__
 | 
			
		||||
	Console interface;
 | 
			
		||||
	sys.interface = &interface;
 | 
			
		||||
#endif
 | 
			
		||||
	interface.wrbuf(banner, bannerlen);
 | 
			
		||||
	interpreter(interface);
 | 
			
		||||
	sys.interface->wrbuf(banner, bannerlen);
 | 
			
		||||
	interpreter();
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -25,6 +25,9 @@ Console::rdbuf(char *buf, size_t len, bool stopat, char stopch)
 | 
			
		|||
 | 
			
		||||
	while (n < len) {
 | 
			
		||||
		ch = this->rdch();
 | 
			
		||||
		if (ch == 0x04) {
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (stopat && stopch == ch) {
 | 
			
		||||
			break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										33
									
								
								parser.cc
								
								
								
								
							
							
						
						
									
										33
									
								
								parser.cc
								
								
								
								
							| 
						 | 
				
			
			@ -19,7 +19,22 @@ match_token(const char *a, const size_t alen,
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return memcmp(a, b, alen) == 0;
 | 
			
		||||
	for (size_t i = 0; i < alen; i++) {
 | 
			
		||||
		if (a[i] == b[i]) {
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		if ((a[i] ^ 0x20) == b[i]) {
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		if (a[i] == (b[i] ^ 0x20)) {
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PARSE_RESULT
 | 
			
		||||
| 
						 | 
				
			
			@ -72,9 +87,9 @@ parse_next(const char *buf, const size_t length, size_t *offset,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
bool
 | 
			
		||||
parse_num(struct Token *token, Stack<KF_INT> &s)
 | 
			
		||||
parse_num(struct Token *token, KF_INT *n)
 | 
			
		||||
{
 | 
			
		||||
	KF_INT	n = 0;
 | 
			
		||||
	KF_INT	tmp = 0;
 | 
			
		||||
	uint8_t i = 0;
 | 
			
		||||
	bool    sign = false;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -83,6 +98,9 @@ parse_num(struct Token *token, Stack<KF_INT> &s)
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	if (token->token[i] == '-') {
 | 
			
		||||
		if (token->length == 1) {
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		i++;
 | 
			
		||||
		sign = true;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -96,14 +114,15 @@ parse_num(struct Token *token, Stack<KF_INT> &s)
 | 
			
		|||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		n *= 10;
 | 
			
		||||
		n += (uint8_t)(token->token[i] - '0');
 | 
			
		||||
		tmp *= 10;
 | 
			
		||||
		tmp += (uint8_t)(token->token[i] - '0');
 | 
			
		||||
		i++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (sign) {
 | 
			
		||||
		n *= -1;
 | 
			
		||||
		tmp *= -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return s.push(n);
 | 
			
		||||
	*n = tmp;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								parser.h
								
								
								
								
							
							
						
						
									
										2
									
								
								parser.h
								
								
								
								
							| 
						 | 
				
			
			@ -21,7 +21,7 @@ PARSE_RESULT	parse_next(const char *, const size_t, size_t *, struct Token *);
 | 
			
		|||
 | 
			
		||||
// TODO(kyle): investigate a better return value, e.g. to differentiate between
 | 
			
		||||
// stack failures and parse failures.
 | 
			
		||||
bool		parse_num(struct Token *, Stack<KF_INT> &);
 | 
			
		||||
bool		parse_num(struct Token *, KF_INT *);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // __KF_PARSER_H__
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										10
									
								
								stack.h
								
								
								
								
							
							
						
						
									
										10
									
								
								stack.h
								
								
								
								
							| 
						 | 
				
			
			@ -7,9 +7,10 @@ template <typename T>
 | 
			
		|||
class Stack {
 | 
			
		||||
public:
 | 
			
		||||
        bool   push(T val);
 | 
			
		||||
	bool   pop(T &val);
 | 
			
		||||
	bool   pop(T *val);
 | 
			
		||||
	bool   get(size_t, T &);
 | 
			
		||||
	size_t size(void) { return this->arrlen; };
 | 
			
		||||
	size_t size(void) { return this->arrlen; }
 | 
			
		||||
	void   clear(void) { this->arrlen = 0; }
 | 
			
		||||
private:
 | 
			
		||||
	T arr[STACK_SIZE];
 | 
			
		||||
	size_t arrlen;
 | 
			
		||||
| 
						 | 
				
			
			@ -31,14 +32,15 @@ Stack<T>::push(T val)
 | 
			
		|||
// pop returns false if there was a stack underflow.
 | 
			
		||||
template <typename T>
 | 
			
		||||
bool
 | 
			
		||||
Stack<T>::pop(T &val)
 | 
			
		||||
Stack<T>::pop(T *val)
 | 
			
		||||
{
 | 
			
		||||
	if (this->arrlen == 0) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	val = this->arr[this->arrlen - 1];
 | 
			
		||||
	*val = this->arr[this->arrlen - 1];
 | 
			
		||||
	this->arrlen--;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// get returns false on invalid bounds.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
#ifndef __KF_CORE_H__
 | 
			
		||||
#define __KF_CORE_H__
 | 
			
		||||
 | 
			
		||||
#include "defs.h"
 | 
			
		||||
#include "io.h"
 | 
			
		||||
#include "stack.h"
 | 
			
		||||
 | 
			
		||||
typedef struct _System {
 | 
			
		||||
	Stack<KF_INT>	 dstack;
 | 
			
		||||
	IO		*interface;
 | 
			
		||||
} System;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // __KF_CORE_H__
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
#include "defs.h"
 | 
			
		||||
#include "parser.h"
 | 
			
		||||
#include "system.h"
 | 
			
		||||
#include "word.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Builtin::Builtin(const char *name, size_t namelen, Word *head, bool (*target)(System *))
 | 
			
		||||
	: prev(head), fun(target)
 | 
			
		||||
{
 | 
			
		||||
	memcpy(this->name, name, namelen);
 | 
			
		||||
	this->namelen = namelen;
 | 
			
		||||
}
 | 
			
		||||
	
 | 
			
		||||
bool
 | 
			
		||||
Builtin::eval(System *sys)
 | 
			
		||||
{
 | 
			
		||||
	return this->fun(sys);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Word *
 | 
			
		||||
Builtin::next()
 | 
			
		||||
{
 | 
			
		||||
	return this->prev;
 | 
			
		||||
}
 | 
			
		||||
	
 | 
			
		||||
bool
 | 
			
		||||
Builtin::match(struct Token *token)
 | 
			
		||||
{
 | 
			
		||||
	return match_token(this->name, this->namelen, token->token, token->length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
Builtin::getname(char *buf, size_t *buflen)
 | 
			
		||||
{
 | 
			
		||||
	memcpy(buf, this->name, this->namelen);
 | 
			
		||||
	*buflen = namelen;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
#ifndef __KF_WORD_H__
 | 
			
		||||
#define __KF_WORD_H__
 | 
			
		||||
 | 
			
		||||
#include "defs.h"
 | 
			
		||||
#include "parser.h"
 | 
			
		||||
#include "stack.h"
 | 
			
		||||
#include "system.h"
 | 
			
		||||
 | 
			
		||||
class Word {
 | 
			
		||||
public:
 | 
			
		||||
	virtual ~Word() {};
 | 
			
		||||
 | 
			
		||||
	virtual bool  eval(System *) = 0;
 | 
			
		||||
	virtual Word *next(void) = 0;
 | 
			
		||||
	virtual bool  match(struct Token *) = 0;
 | 
			
		||||
	virtual void  getname(char *, size_t *) = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class Builtin : public Word {
 | 
			
		||||
public:
 | 
			
		||||
	~Builtin() {};
 | 
			
		||||
	Builtin(const char *name, size_t namelen, Word *head, bool (*fun)(System *));
 | 
			
		||||
	
 | 
			
		||||
	bool  eval(System *);
 | 
			
		||||
	Word *next(void);
 | 
			
		||||
	bool  match(struct Token *);
 | 
			
		||||
	void  getname(char *, size_t *);
 | 
			
		||||
	
 | 
			
		||||
private:
 | 
			
		||||
	char		 name[MAX_TOKEN_LENGTH];
 | 
			
		||||
	size_t		 namelen;
 | 
			
		||||
	Word		*prev;
 | 
			
		||||
	bool		(*fun)(System *);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // __KF_WORD_H__
 | 
			
		||||
		Loading…
	
		Reference in New Issue