summaryrefslogtreecommitdiff
path: root/parser.c
blob: 7e7a1c23c6bb1af0016ce344a76dc21ef3b3c52a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>

#include "parser.h"
#include "util.h"

typedef struct Cursor{
	const char *s;
	int l;
} Cursor;

typedef enum Tokentype{
	TT_EOF, //str=NULL, len=-1
	TT_SYMBOL,
	TT_WORD,
	TT_NUMBER,

	TT_ERR=-1 //str is an error description, len=-1
} Tokentype;

typedef struct Token{
	Tokentype type;
	const char *str; //pointer into source
	int len;
} Token;

#define SYMBOLCHARS "()[]"


static Token tt_make(Tokentype type,const char *str,int len){
	Token tok={type,str,len};
	return tok;
}

static Token tt_eof(void){
	return tt_make(TT_EOF,NULL,-1);
}

static Token tt_err(const char *errstr){
	return tt_make(TT_ERR,errstr,-1);
}


static void advance(Cursor *cursor,int n){
	assert(cursor->l>=n);
	cursor->s+=n;
	cursor->l-=n;
}

static bool iswordchar(char c){
	return strchr(SYMBOLCHARS,c)==NULL&&c>=33&&c<=126;
}

static Token nexttoken(Cursor *cursor){
	while(cursor->l>=1&&isspace(*cursor->s))advance(cursor,1);
	if(cursor->l==0)return tt_eof();

	if(strchr(SYMBOLCHARS,*cursor->s)!=NULL){
		advance(cursor,1);
		return tt_make(TT_SYMBOL,cursor->s-1,1);
	}

	if(isdigit(*cursor->s)||(cursor->l>=2&&cursor->s[0]=='-'&&isdigit(cursor->s[1]))){
		char *endp;
		strtod(cursor->s,&endp);
		assert(endp>cursor->s);
		int len=endp-cursor->s;
		advance(cursor,len);
		return tt_make(TT_NUMBER,cursor->s-len,len);
	}

	int i;
	for(i=0;i<cursor->l;i++){
		if(!iswordchar(cursor->s[i]))break;
	}
	if(i==0){
		return tt_err("Unrecognised character while looking for next token");
	}
	advance(cursor,i);
	return tt_make(TT_WORD,cursor->s-i,i);
}


static ParseRet parse_(Cursor *cursor){
	;
}


ParseRet parse(const char *source,int length){
	Cursor cursor={source,length};
	return parse_(&cursor);
}