aboutsummaryrefslogtreecommitdiff
path: root/demos/sample-files/calc-skeleton.c
blob: ad4aba9525454d692a2758d0f5dc7435740c6187 (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
100
101
102
103
104
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <ctype.h>

// generated
#include "bin/calc.h"
#include "bin/calc.c"

#include "parts/grammar.h"
#include "parts/precedence.h"
#include "parts/toklist.h"
static struct token {
    symbol s;
    int v;
} tok;

static char *next_token(char *str);

symbol token_sym(struct token *t) { return t->s; }
intptr_t token_val(struct token *t) { return (intptr_t)t->v; }

static char *input;

struct token *toklist_eat()
{
    static struct token t;
    t = tok;
    input = next_token(input);
    return &t;
}

struct token *toklist_peek() { return &tok; }

#include "lr-parser.c"

int main(int argc, char **argv)
{
    if(argc != 2) return 1;

    input = next_token(argv[1]);

    intptr_t value;
    if(lr_parser(&value)) return 1;

    printf("INPUT: '%s'\n", argv[1]);
    printf("OUTPUT: %jd\n", value);

    return 0;
}

// LEXER

static inline int issep(char c)
{
    return isspace(c) || c == '\0' || c == '(' || c == ')' || c == '+' || c == '-' || c == '*' || 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;
            case '>': tok.s = MORE; break;
            case '<': tok.s = LESS; break;
            case '=': tok.s = EQUA; break;
            case '?': tok.s = QMARK; break;
            case ':': tok.s = COLON; break;
            }
        } else if(c0 >= '0' && c0 <= '9') { // num
            tok.s = NUM;
            tok.v = atoi(substring(str, off));
        }
    }

    return str+off;
}