$:unquote takes three arguments (term and left and right quotes.)
Cat's Eye Technologies
11 years ago
102 | 102 |
}
|
103 | 103 |
}
|
104 | 104 |
|
105 | |
struct term *tamsin_unquote(const struct term *q) {
|
106 | |
if (q->atom[0] == '"' || q->atom[0] == '\'') {
|
|
105 |
struct term *tamsin_unquote(const struct term *q,
|
|
106 |
const struct term *l, const struct term *r) {
|
|
107 |
if (q->size < 1 || l->size != 1 || r->size != 1) {
|
|
108 |
struct term *result = term_new_from_cstring("bad terms for unquote");
|
|
109 |
ok = 0;
|
|
110 |
return result;
|
|
111 |
}
|
|
112 |
if (q->atom[0] == l->atom[0] && q->atom[q->size-1] == r->atom[0]) {
|
|
113 |
ok = 1;
|
107 | 114 |
return term_new(q->atom + 1, q->size - 2);
|
|
115 |
} else {
|
|
116 |
struct term *result = term_new_from_cstring("term '");
|
|
117 |
result = term_concat(result, q);
|
|
118 |
result = term_concat(result, term_new_from_cstring(
|
|
119 |
"' is not quoted with '"
|
|
120 |
));
|
|
121 |
result = term_concat(result, l);
|
|
122 |
result = term_concat(result, term_new_from_cstring("' and '"));
|
|
123 |
result = term_concat(result, r);
|
|
124 |
result = term_concat(result, &APOS);
|
|
125 |
ok = 0;
|
|
126 |
return result;
|
108 | 127 |
}
|
109 | |
return term_new(q->atom, q->size);
|
110 | 128 |
}
|
111 | 129 |
|
112 | 130 |
struct term *tamsin_mkterm_r(struct term *t, const struct term *list) {
|
121 | 121 |
void tamsin_alnum(struct scanner *);
|
122 | 122 |
void tamsin_upper(struct scanner *);
|
123 | 123 |
void tamsin_startswith(struct scanner *, const char *);
|
124 | |
struct term *tamsin_unquote(const struct term *);
|
|
124 |
struct term *tamsin_unquote(const struct term *,
|
|
125 |
const struct term *, const struct term *);
|
125 | 126 |
struct term *tamsin_mkterm(const struct term *, const struct term *);
|
126 | 127 |
|
127 | 128 |
|
6 | 6 |
prod = expr.
|
7 | 7 |
}
|
8 | 8 |
|
9 | |
* module-level updatable variables.
|
10 | 9 |
* including files, library files should be **handled by the implementation**
|
11 | 10 |
* document, too, the implementation-dependent nature of input and output
|
12 | |
* EOF and nil are the same? it would make sense... call it `end`?
|
13 | |
* regex-like shortcuts: `\w` for "word", `\s` for "whitespace", etc.
|
14 | |
* `$.unquote` should take left and right quotes to expect
|
15 | 11 |
* define a stringify-repr operation on terms
|
16 | 12 |
* stronger tests for scanner, parser: dump all falderal testbodies to files
|
17 | 13 |
* `emit` alongside `print`.
|
|
20 | 16 |
|
21 | 17 |
### lower-priority/experimental ###
|
22 | 18 |
|
|
19 |
* regex-like shortcuts: `\w` for "word", `\s` for "whitespace", etc.
|
|
20 |
* EOF and nil are the same? it would make sense... call it `end`?
|
|
21 |
* module-level updatable variables.
|
23 | 22 |
* tests for failing when utf8 scanner hits badly-encoded utf8
|
24 | 23 |
* numeric values... somehow. number('65') = #65. decode(ascii, 'A') = #65.
|
25 | 24 |
* tell/rewind the implicit buffer -- for VM's etc
|
964 | 964 |
| main = $:mkterm(atom, list(a, list(b, list(c, nil)))).
|
965 | 965 |
= atom(a, b, c)
|
966 | 966 |
|
967 | |
Here's `$:unquote`, which takes a term which begins and ends with a
|
968 | |
quote symbol (TODO: should be the given quote symbol) and returns
|
969 | |
the contents.
|
970 | |
|
971 | |
| main = $:unquote('"hello"').
|
|
967 |
Here's `$:unquote`, which takes three terms, X, L and R, where L and R
|
|
968 |
must be one-character atoms. If X begins with L and ends with R then
|
|
969 |
the contents in-between will be returned as an atom. Otherwise fails.
|
|
970 |
|
|
971 |
| main = $:unquote('"hello"', '"', '"').
|
972 | 972 |
= hello
|
|
973 |
|
|
974 |
| main = $:unquote('(hello)', '(', ')').
|
|
975 |
= hello
|
|
976 |
|
|
977 |
| main = $:unquote('(hello)', '(', '"').
|
|
978 |
? term '(hello)' is not quoted with '(' and '"'
|
973 | 979 |
|
974 | 980 |
`:foo` always means production `foo` in the current module.
|
975 | 981 |
|
49 | 49 |
(("←" | "<-") & texpr → T & return set(V, T)
|
50 | 50 |
| return call(prodref('$', return), list(V, nil)))
|
51 | 51 |
| sq_string → T &
|
52 | |
$:unquote(T) → T &
|
|
52 |
$:unquote(T, '\'', '\'') → T &
|
53 | 53 |
return call(prodref('$', return), list(T, nil))
|
54 | 54 |
| prodref → P &
|
55 | 55 |
L ← nil &
|
|
70 | 70 |
| variable.
|
71 | 71 |
atom = word
|
72 | 72 |
| sq_string → T &
|
73 | |
$:unquote(T).
|
|
73 |
$:unquote(T, '\'', '\'').
|
74 | 74 |
|
75 | 75 |
terminal = terminal0 → T & return call(prodref('$', expect), list(T, nil)).
|
76 | |
terminal0 = dq_string → T & $:unquote(T) → T & T
|
|
76 |
terminal0 = dq_string → T & $:unquote(T, '"', '"') → T & T
|
77 | 77 |
| ("«" | "<<") & texpr → T & ("»" | ">>") & T.
|
78 | 78 |
|
79 | 79 |
prodref = M ← '' & [modref → M & ":"] & word → P & return prodref(M, P).
|
49 | 49 |
(("←" | "<-") & texpr → T & return set(V, T)
|
50 | 50 |
| return call(prodref('$', return), list(V, nil)))
|
51 | 51 |
| sq_string → T &
|
52 | |
$:unquote(T) → T &
|
|
52 |
$:unquote(T, '\'', '\'') → T &
|
53 | 53 |
return call(prodref('$', return), list(T, nil))
|
54 | 54 |
| prodref → P &
|
55 | 55 |
L ← nil &
|
|
70 | 70 |
| variable.
|
71 | 71 |
atom = word
|
72 | 72 |
| sq_string → T &
|
73 | |
$:unquote(T).
|
|
73 |
$:unquote(T, '\'', '\'').
|
74 | 74 |
|
75 | 75 |
terminal = terminal0 → T & return call(prodref('$', expect), list(T, nil)).
|
76 | |
terminal0 = dq_string → T & $:unquote(T) → T & T
|
|
76 |
terminal0 = dq_string → T & $:unquote(T, '"', '"') → T & T
|
77 | 77 |
| ("«" | "<<") & texpr → T & ("»" | ">>") & T.
|
78 | 78 |
|
79 | 79 |
prodref = M ← '' & [modref → M & ":"] & word → P & return prodref(M, P).
|
38 | 38 |
'print': [Variable('X')],
|
39 | 39 |
'return': [Variable('X')],
|
40 | 40 |
'startswith': [Variable('X')],
|
41 | |
'unquote': [Variable('X')],
|
|
41 |
'unquote': [Variable('X'), Variable('L'), Variable('R')],
|
42 | 42 |
'mkterm': [Variable('T'), Variable('L')],
|
43 | 43 |
}.get(name, [])
|
44 | 44 |
return [Production('$.%s' % name, 0, formals, [], None)]
|
238 | 238 |
self.emit('tamsin_startswith(scanner, term_flatten(temp)->atom);')
|
239 | 239 |
elif name == 'unquote':
|
240 | 240 |
self.emit_term(args[0], "temp")
|
241 | |
self.emit('result = tamsin_unquote(temp);')
|
242 | |
self.emit('ok = 1;')
|
|
241 |
self.emit_term(args[1], "lquote")
|
|
242 |
self.emit_term(args[2], "rquote")
|
|
243 |
self.emit('result = tamsin_unquote(temp, lquote, rquote);')
|
243 | 244 |
elif name == 'mkterm':
|
244 | 245 |
self.emit_term(args[0], "temp_atom")
|
245 | 246 |
self.emit_term(args[1], "temp_list")
|
167 | 167 |
else:
|
168 | 168 |
return (False, Atom("expected '%s, found '%s'" %
|
169 | 169 |
(bindings['X'], self.scanner.peek())))
|
170 | |
elif name == '$.unquote': # TODO this is definitely a bodge
|
|
170 |
elif name == '$.unquote':
|
171 | 171 |
x = str(bindings['X'])
|
172 | |
if (x.startswith(('"', "'"))):
|
|
172 |
if (x.startswith((str(bindings['L']),)) and
|
|
173 |
x.endswith((str(bindings['R']),))):
|
173 | 174 |
return (True, Atom(x[1:-1]))
|
174 | 175 |
else:
|
175 | |
return (True, bindings['X'])
|
176 | |
elif name == '$.mkterm': # TODO another categorical bodge
|
|
176 |
return (False, Atom("term '%s' is not quoted with '%s' and '%s'" %
|
|
177 |
(bindings['X'], bindings['L'], bindings['R'])))
|
|
178 |
elif name == '$.mkterm':
|
177 | 179 |
t = bindings['T']
|
178 | 180 |
l = bindings['L']
|
179 | 181 |
contents = []
|