Browse Source

Add source of chapter 07

T. Meissner 7 months ago
parent
commit
0605f5e195
2 changed files with 132 additions and 0 deletions
  1. 13
    0
      chapter_07/Makefile
  2. 119
    0
      chapter_07/lispy.c

+ 13
- 0
chapter_07/Makefile View File

@@ -0,0 +1,13 @@
1
+MPC_DIR := ../mpc
2
+
3
+
4
+all: lispy
5
+
6
+
7
+%: %.c
8
+	cc -std=c11 -Wall $@.c ${MPC_DIR}/mpc.c -ledit -o $@
9
+
10
+
11
+.PHONY: clean
12
+clean:
13
+	rm -rf lispy

+ 119
- 0
chapter_07/lispy.c View File

@@ -0,0 +1,119 @@
1
+#include <stdio.h>
2
+#include <stdlib.h>
3
+#include "../mpc/mpc.h"
4
+
5
+
6
+/* If we are on Windows compile these functions */
7
+#ifdef _WIN32
8
+#include <string.h>
9
+#include <assert.h>
10
+
11
+static char buffer[2048];
12
+
13
+/* Fake readline function */
14
+char* readline(char* prompt) {
15
+    fputs(prompt, stdout);
16
+    fgets(buffer, 2048, stdin);
17
+    char* cpy = malloc(strlen(buffer)+1);
18
+    assert(cpy != NULL)
19
+    strcpy(cpy, buffer);
20
+    cpy[strlen(cpy)-1] = '\0';
21
+    return cpy;
22
+}
23
+
24
+/* Fake add_history function */
25
+void add_history(char* unused) {}
26
+
27
+/* Otherwise include the editline headers
28
+   could use __APPLE__ for detection of OSX */
29
+#else
30
+#include <editline/readline.h>
31
+#endif
32
+
33
+
34
+/* Use operator string to see which operation to perform */
35
+long eval_op(long x, char* op, long y) {
36
+    if (strcmp(op, "+") == 0) {return x + y;}
37
+    if (strcmp(op, "-") == 0) {return x - y;}
38
+    if (strcmp(op, "*") == 0) {return x * y;}
39
+    if (strcmp(op, "/") == 0) {return x / y;}
40
+    return 0;
41
+}
42
+
43
+
44
+long eval(mpc_ast_t* t) {
45
+
46
+    /* If tagged as number return it directly */
47
+    if (strstr(t->tag, "number")) {
48
+        return atoi(t->contents);
49
+    }
50
+
51
+    /* The operator is always second child */
52
+    char* op = t->children[1]->contents;
53
+
54
+    /* We store the third children in x */
55
+    long x = eval(t->children[2]);
56
+
57
+    /* Iterate the remaining children and combining */
58
+    unsigned int i = 3;
59
+    while (strstr(t->children[i]->tag, "expr")) {
60
+        x = eval_op(x, op, eval(t->children[i]));
61
+        i++;
62
+    }
63
+
64
+    return x;
65
+}
66
+
67
+
68
+int main(int argc, char const *argv[])
69
+{
70
+    /* Create some parsers */
71
+    mpc_parser_t* Number = mpc_new("number");
72
+    mpc_parser_t* Operator = mpc_new("operator");
73
+    mpc_parser_t* Expr = mpc_new("expr");
74
+    mpc_parser_t* Lispy = mpc_new("lispy");
75
+
76
+    /* Define them with the following language */
77
+    mpca_lang(MPCA_LANG_DEFAULT,
78
+        "                                                       \
79
+            number   : /-?[0-9]+/ ;                             \
80
+            operator : '+' | '-' | '*' | '/' ;                  \
81
+            expr     : <number> | '(' <operator> <expr>+ ')' ;  \
82
+            lispy    : /^/ <operator> <expr>+ /$/ ;             \
83
+        ",
84
+        Number, Operator, Expr, Lispy);
85
+
86
+    /* Print version and exit information */
87
+    puts("Lispy version 0.0.0.0.3");
88
+    puts("Press Ctrl+c to exit\n");
89
+
90
+    /* In a never ending loop */
91
+    while (1) {
92
+        /* Output our prompt and get input */
93
+        char* input = readline("lispy> ");
94
+
95
+        /* Add input to history */
96
+        add_history(input);
97
+
98
+        /* Attempt to parse the user input */
99
+        mpc_result_t r;
100
+        if (mpc_parse("<stdin>", input, Lispy, &r)) {
101
+            /* On success evaluate the user input */
102
+            long result = eval(r.output);
103
+            printf("%li\n", result);
104
+            mpc_ast_delete(r.output);
105
+        } else {
106
+            /* Otherwise print the error */
107
+            mpc_err_print(r.error);
108
+            mpc_err_delete(r.error);
109
+        }
110
+
111
+        /* Free retrieved input */
112
+        free(input);
113
+    }
114
+
115
+    /* Undefine and delete our parsers */
116
+    mpc_cleanup(4, Number, Operator, Expr, Lispy);
117
+
118
+    return 0;
119
+}