-
Notifications
You must be signed in to change notification settings - Fork 6
/
parser.c
115 lines (97 loc) · 1.86 KB
/
parser.c
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
105
106
107
108
109
110
111
112
113
114
115
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "base.h"
#include "symbol_table.h"
#include "parser.h"
/*
lisp_program -> atom|list
list -> "(" list_body ")"
list_body -> (atom|list)+
or expressed in a simpler fashion:
expr -> atom|list
list -> "(" expr+ ")"
*/
extern char *yytext;
extern int yylex();
static const char * lex(){
if (yylex() == 0) {
return nil;
}
return strdup(yytext);
}
static char *_sym;
static bool is_o(){
check_not_nil(_sym, "parse error");
return _sym[0]=='(';
}
static bool is_c(){
check_not_nil(_sym, "parse error %p", _sym);
return _sym[0]==')';
}
static bool is_sym(){
return !(is_o() || is_c());
}
static void match(const char * s){
if (strcmp(s, _sym)==0) {
_sym = (char *)lex();
}
else {
fprintf(stderr, "parse error");
exit(EXIT_FAILURE);
}
}
static object * atom_or_list();
static object * list_body(){
if (is_c())
return nil;
return cons(atom_or_list(), list_body());
}
static object * parse_list() {
match("(");
object * o;
o = list_body();
match(")");
return o;
}
static object * parse_atom() {
static object * o;
check_not_nil(_sym, "parse error");
if (strcmp(_sym, "nil")==0)
o = nil;
else
o = st_insert(_sym);
_sym = (char *)lex();
return o;
}
static object * atom_or_list(){
if (is_sym())
return parse_atom();
else if (is_o())
return parse_list();
else {
fprintf(stderr, "parse error\n");
exit(1);
}
}
static object * lisp_program(){
return atom_or_list();
}
static object * parse(){
_sym = (char *)lex();
return lisp_program();
}
extern FILE * yyin;
object * parse_string(char *s){
object *o;
const char * fn = "/tmp/tinylisp-123";
FILE * f = fopen(fn, "w");
fwrite(s, strlen(s), 1, f);
fclose(f);
FILE * tmp = yyin;
yyin = fopen(fn, "r");
o = parse();
fclose(yyin);
yyin = tmp;
return o;
}