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
95
96
97
98
99
|
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "lr-parser.c"
#include "bin/a.c" // generated
// these should come from a generated
// header file by the parser generator
#include "parts/symbol.h"
enum symbol {
PLUS, MINUS, TIMES,
LPAREN, RPAREN,
NUM, END_INPUT,
EP, E, T,
SYMBOLS_END,
};
static struct token {
symbol s;
int v;
} tok;
static inline int issep(char c)
{
return isspace(c) || c == '\0' || c == '(' || c == ')' || c == '+' || c == '-' || c == '*';;
}
static inline int tillsep(char *str)
{
size_t i = 0;
while(!issep(str[i++]));
return i-1;
}
static inline char *substring(char *str, size_t sub_end)
{
static char sub[128];
if(sub_end+1 > sizeof(sub)) return NULL;
sub[sub_end] = '\0';
return memcpy(sub, str, sub_end);
}
static char *next_token(char *str)
{
size_t off = 0;
char c0 = str[0];
if(c0 == '\0') tok.s = END_INPUT;
if(isspace(c0)) return next_token(str+1);
else {
off = tillsep(str);
if(off == 0) { // sep
switch(str[off++]) {
case '(': tok.s = LPAREN; break;
case ')': tok.s = RPAREN; break;
case '-': tok.s = MINUS; break;
case '+': tok.s = PLUS; break;
case '*': tok.s = TIMES; break;
}
} else if(c0 >= '0' && c0 <= '9') { // num
tok.s = NUM;
tok.v = atoi(substring(str, off));
}
}
return str+off;
}
static char *input;
symbol token_sym(struct token *t) { return t->s; }
int token_val(struct token *t) { return t->v; }
struct token *toklist_eat()
{
static struct token t;
t = tok;
input = next_token(input);
return &t;
}
struct token *toklist_peek() { return &tok; }
int main(int argc, char **argv)
{
if(argc != 2) return 1;
input = next_token(argv[1]);
int value;
if(lr_parser(&value)) return 1;
printf("INPUT: '%s'\n", argv[1]);
printf("OUTPUT: %d\n", value);
return 0;
}
|