aboutsummaryrefslogtreecommitdiff
path: root/demos/sample-files/calc-skeleton.c
blob: b0cbf00f4b42b908dc4b825eeff0439275bd73fa (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
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;
}