lac : 38a14842379bc1cf15c57f53ae0c5a8265eb3912
1: /*
2: lac -- a lisp interpreter
3: Copyright (C) 2010 Gianluca Guida
4:
5: This program is free software; you can redistribute it and/or modify
6: it under the terms of the GNU General Public License as published by
7: the Free Software Foundation; either version 2 of the License, or
8: (at your option) any later version.
9:
10: This program is distributed in the hope that it will be useful,
11: but WITHOUT ANY WARRANTY; without even the implied warranty of
12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13: GNU General Public License for more details.
14:
15: You should have received a copy of the GNU General Public License along
16: with this program; if not, write to the Free Software Foundation, Inc.,
17: 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18: */
19:
20: %{
21: #define YYSTYPE lreg_t
22:
23: #include <ctype.h>
24: #include <strings.h>
25:
26: #include <lac.h>
27: #include "sexpr.h"
28: #include "private.h"
29: %}
30:
31: %option noyywrap
32: %option reentrant
33: %option bison-bridge
34:
35: WHITESPACE [\ \t\n]
36: DIGIT [0-9]
37: HEXDIGIT [0-9a-fA-F]
38: ALPHA [A-Za-z]
39: SP_INIT [#\*/:<=>?^_~!$%&+-]
40: SPECIAL [\*/:<=>?^_~!$%&+-.]
41: SIGN [+|-]
42:
43: %%
44:
45: ;(.)*
46: {WHITESPACE}
47:
48: {SIGN}?{DIGIT}+ {
49: intptr_t n;
50:
51: errno = 0;
52: n = strtol(yytext, (char **)NULL, 10);
53: *yylval = lac_extty_box(LREG_INTEGER, (void *)n, 0);
54: return INTEGER;
55: }
56:
57: (#x|0x){HEXDIGIT}+ {
58: intptr_t n;
59:
60: errno = 0;
61: n = strtol(yytext+2, (char **)NULL, 16);
62: if ( errno == ERANGE )
63: raise_exception("Integer overflow in input", NIL);
64: *yylval = lac_extty_box(LREG_INTEGER, (void *)n, 0);
65: return INTEGER;
66: }
67:
68: (NIL|nil) {
69: *yylval = NIL;
70: return NIHIL;
71: }
72:
73: \"[^\"]*\" {
74: size_t len = strlen(yytext);
75: char *s = lac_alloc(len - 1);
76: memcpy(s, yytext+1, len - 2);
77: *yylval = lreg_raw(s, LREG_STRING);
78: return STRING;
79: }
80:
81: (({DIGIT}+({SPECIAL}|{ALPHA}))|{ALPHA}|{SP_INIT})({SPECIAL}|{ALPHA}|{DIGIT})* {
82: int i;
83: size_t len = strlen(yytext);
84: char *s = lac_alloc(len + 1);
85: for (i = 0; i < len; i++)
86: *(s+i) = toupper((int)*(yytext+i));
87: *yylval = intern_symbol(s);
88: return SYMBOL;
89: }
90:
91: ,@ { return COMMA_AT; }
92:
93: \' { return QUOTE; }
94:
95: ` { return QUASI; }
96:
97: , { return COMMA; }
98:
99: \( { return OPAREN; }
100:
101: \) { return CPAREN; }
102:
103: \. { return DOT; }
104:
105: <<EOF>> { return -1; }
106:
107: . { return -1; }
108:
109:
110: %%
111:
112: static void _sexpr_parse(yyscan_t yyscan, struct parse_cb *cb)
113: {
114: int v;
115: lreg_t lr;
116: void *parser;
117:
118: parser = ParseAlloc(malloc);
119:
120: while((v = yylex(&lr, yyscan)) != -1) {
121: Parse(parser, v, lr, cb);
122: }
123: Parse(parser, ENDPARSE, lr, cb);
124:
125: /* XXX: ON EXCEPTION, destroy parser and retrow. */
126:
127: ParseFree(parser, free);
128: yylex_destroy(yyscan);
129: }
130:
131: lreg_t sexpr_parse_string(char *s, lreg_t (*fn)(lreg_t,void*), void *opq)
132: {
133: yyscan_t yyscan;
134: struct parse_cb cb;
135:
136: cb.fn = fn;
137: cb.opq = opq;
138: cb.res = NIL;
139:
140: yylex_init(&yyscan);
141: yy_scan_string(s, yyscan);
142:
143: _sexpr_parse(yyscan, &cb);
144: return cb.res;
145: }
146:
147: lreg_t sexpr_parse_file(FILE *f, lreg_t (*fn)(lreg_t,void*), void *opq)
148: {
149: yyscan_t yyscan;
150: struct parse_cb cb;
151:
152: cb.fn = fn;
153: cb.opq = opq;
154: cb.res = NIL;
155:
156: yylex_init(&yyscan);
157: yyset_in(f, yyscan);
158:
159: _sexpr_parse(yyscan, &cb);
160: return cb.res;
161: }
162:
163:
164: /*
165: * Print
166: */
167:
168: static void sexpr_print_cons(FILE *f, lreg_t lr, const char *h)
169: {
170: lreg_t a = car(lr);
171: lreg_t d = cdr(lr);
172:
173: printf(h);
174: sexpr_fprint(f, a);
175:
176: if (d == NIL) {
177: fprintf(f, ")");
178: return;
179: }
180:
181: if (lreg_raw_type(d) == LREG_CONS)
182: sexpr_print_cons(f, d, " ");
183: else
184: {
185: fprintf(f, " . ");
186: sexpr_fprint(f, cdr(lr));
187: fprintf(f, ")");
188: }
189: }
190:
191: void sexpr_fprint(FILE *f, lreg_t lr)
192: {
193: switch ( lreg_type(lr) )
194: {
195: case LREG_NIL:
196: fprintf(f, "()");
197: break;
198: case LREG_SYMBOL:
199: fprintf(f, "%s", (char *)lreg_raw_ptr(lr));
200: break;
201: case LREG_STRING:
202: fprintf(f, "\"%s\"", (char *)lreg_raw_ptr(lr));
203: break;
204: case LREG_CONS:
205: sexpr_print_cons(f, lr, "(");
206: break;
207: case LREG_MACRO:
208: fprintf(f, "<#MACRO>");
209: break;
210: case LREG_LAMBDA:
211: fprintf(f, "<#LAMBDA>");
212: break;
213: case LREG_LLPROC:
214: fprintf(f, "<#LLPROC>");
215: break;
216: default:
217: if ( !lac_extty_print(f, lr) )
218: fprintf(f, "<??? %d>",(int)lreg_type(lr));
219: }
220: return;
221: }
Generated by git2html.