lac : e854b7bfb0163c7ab22a56a471cd8c2c1ec639ba
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: lac_on_error({
121: ParseFree(parser, free);
122: yylex_destroy(yyscan);
123: _throw();
124: });
125:
126: while((v = yylex(&lr, yyscan)) != -1) {
127: Parse(parser, v, lr, cb);
128: }
129: Parse(parser, ENDPARSE, lr, cb);
130:
131: lac_off_error();
132:
133: ParseFree(parser, free);
134: yylex_destroy(yyscan);
135: }
136:
137: lreg_t sexpr_parse_string(char *s, lreg_t (*fn)(lreg_t,void*), void *opq)
138: {
139: yyscan_t yyscan;
140: struct parse_cb cb;
141:
142: cb.fn = fn;
143: cb.opq = opq;
144: cb.res = NIL;
145:
146: yylex_init(&yyscan);
147: yy_scan_string(s, yyscan);
148:
149: _sexpr_parse(yyscan, &cb);
150: return cb.res;
151: }
152:
153: lreg_t sexpr_parse_file(FILE *f, lreg_t (*fn)(lreg_t,void*), void *opq)
154: {
155: yyscan_t yyscan;
156: struct parse_cb cb;
157:
158: cb.fn = fn;
159: cb.opq = opq;
160: cb.res = NIL;
161:
162: yylex_init(&yyscan);
163: yyset_in(f, yyscan);
164:
165: _sexpr_parse(yyscan, &cb);
166: return cb.res;
167: }
168:
169:
170: /*
171: * Print
172: */
173:
174: static void sexpr_print_cons(FILE *f, lreg_t lr, const char *h)
175: {
176: lreg_t a = car(lr);
177: lreg_t d = cdr(lr);
178:
179: printf(h);
180: sexpr_fprint(f, a);
181:
182: if (d == NIL) {
183: fprintf(f, ")");
184: return;
185: }
186:
187: if (lreg_raw_type(d) == LREG_CONS)
188: sexpr_print_cons(f, d, " ");
189: else
190: {
191: fprintf(f, " . ");
192: sexpr_fprint(f, cdr(lr));
193: fprintf(f, ")");
194: }
195: }
196:
197: void sexpr_fprint(FILE *f, lreg_t lr)
198: {
199: switch ( lreg_type(lr) )
200: {
201: case LREG_NIL:
202: fprintf(f, "()");
203: break;
204: case LREG_SYMBOL:
205: fprintf(f, "%s", (char *)lreg_raw_ptr(lr));
206: break;
207: case LREG_STRING:
208: fprintf(f, "\"%s\"", (char *)lreg_raw_ptr(lr));
209: break;
210: case LREG_CONS:
211: sexpr_print_cons(f, lr, "(");
212: break;
213: case LREG_MACRO:
214: fprintf(f, "<#MACRO>");
215: break;
216: case LREG_LAMBDA:
217: fprintf(f, "<#LAMBDA>");
218: break;
219: case LREG_LLPROC:
220: fprintf(f, "<#LLPROC>");
221: break;
222: default:
223: if ( !lac_extty_print(f, lr) )
224: fprintf(f, "<??? %d>",(int)lreg_type(lr));
225: }
226: return;
227: }
Generated by git2html.