File: ast.c

package info (click to toggle)
datatype99 1.6.4-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 476 kB
  • sloc: ansic: 1,071; sh: 43; makefile: 6
file content (54 lines) | stat: -rw-r--r-- 1,270 bytes parent folder | download | duplicates (2)
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
/*
 * Let us have a simple arithmetical language, consisting of:
 *
 *  1) Constants of double;
 *  2) Expressions: either expr1 (+ | - | * | /) expr2 or a constant.
 *
 *
 * A sum type can be used to represent the hierarchical structure of ASTs, and pattern matching is a
 * technique to evaluate them.
 */

#include <datatype99.h>

#include <stdio.h>

// clang-format off
datatype(
    Expr,
    (Const, double),
    (Add, Expr *, Expr *),
    (Sub, Expr *, Expr *),
    (Mul, Expr *, Expr *),
    (Div, Expr *, Expr *)
);
// clang-format on

double eval(const Expr *expr) {
    match(*expr) {
        of(Const, number) return *number;
        of(Add, lhs, rhs) return eval(*lhs) + eval(*rhs);
        of(Sub, lhs, rhs) return eval(*lhs) - eval(*rhs);
        of(Mul, lhs, rhs) return eval(*lhs) * eval(*rhs);
        of(Div, lhs, rhs) return eval(*lhs) / eval(*rhs);
    }

    // Invalid input (no such variant).
    return -1;
}

#define EXPR(expr)       ((Expr *)(Expr[]){expr})
#define OP(lhs, op, rhs) op(EXPR(lhs), EXPR(rhs))

int main(void) {
    // 53 + ((155 / 5) - 113)
    Expr expr = OP(Const(53), Add, OP(OP(Const(155), Div, Const(5)), Sub, Const(113)));

    /*
     * Output:
     * -29.000000
     */
    printf("%f\n", eval(&expr));

    return 0;
}