git @ Cat's Eye Technologies Tamsin / 9a03b72
$:unquote takes three arguments (term and left and right quotes.) Cat's Eye Technologies 11 years ago
9 changed file(s) with 53 addition(s) and 26 deletion(s). Raw diff Collapse all Expand all
102102 }
103103 }
104104
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;
107114 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;
108127 }
109 return term_new(q->atom, q->size);
110128 }
111129
112130 struct term *tamsin_mkterm_r(struct term *t, const struct term *list) {
121121 void tamsin_alnum(struct scanner *);
122122 void tamsin_upper(struct scanner *);
123123 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 *);
125126 struct term *tamsin_mkterm(const struct term *, const struct term *);
126127
127128
66 prod = expr.
77 }
88
9 * module-level updatable variables.
109 * including files, library files should be **handled by the implementation**
1110 * 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
1511 * define a stringify-repr operation on terms
1612 * stronger tests for scanner, parser: dump all falderal testbodies to files
1713 * `emit` alongside `print`.
2016
2117 ### lower-priority/experimental ###
2218
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.
2322 * tests for failing when utf8 scanner hits badly-encoded utf8
2423 * numeric values... somehow. number('65') = #65. decode(ascii, 'A') = #65.
2524 * tell/rewind the implicit buffer -- for VM's etc
964964 | main = $:mkterm(atom, list(a, list(b, list(c, nil)))).
965965 = atom(a, b, c)
966966
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"', '"', '"').
972972 = hello
973
974 | main = $:unquote('(hello)', '(', ')').
975 = hello
976
977 | main = $:unquote('(hello)', '(', '"').
978 ? term '(hello)' is not quoted with '(' and '"'
973979
974980 `:foo` always means production `foo` in the current module.
975981
4949 (("←" | "<-") & texpr → T & return set(V, T)
5050 | return call(prodref('$', return), list(V, nil)))
5151 | sq_string → T &
52 $:unquote(T) → T &
52 $:unquote(T, '\'', '\'') → T &
5353 return call(prodref('$', return), list(T, nil))
5454 | prodref → P &
5555 L ← nil &
7070 | variable.
7171 atom = word
7272 | sq_string → T &
73 $:unquote(T).
73 $:unquote(T, '\'', '\'').
7474
7575 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
7777 | ("«" | "<<") & texpr → T & ("»" | ">>") & T.
7878
7979 prodref = M ← '' & [modref → M & ":"] & word → P & return prodref(M, P).
4949 (("←" | "<-") & texpr → T & return set(V, T)
5050 | return call(prodref('$', return), list(V, nil)))
5151 | sq_string → T &
52 $:unquote(T) → T &
52 $:unquote(T, '\'', '\'') → T &
5353 return call(prodref('$', return), list(T, nil))
5454 | prodref → P &
5555 L ← nil &
7070 | variable.
7171 atom = word
7272 | sq_string → T &
73 $:unquote(T).
73 $:unquote(T, '\'', '\'').
7474
7575 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
7777 | ("«" | "<<") & texpr → T & ("»" | ">>") & T.
7878
7979 prodref = M ← '' & [modref → M & ":"] & word → P & return prodref(M, P).
3838 'print': [Variable('X')],
3939 'return': [Variable('X')],
4040 'startswith': [Variable('X')],
41 'unquote': [Variable('X')],
41 'unquote': [Variable('X'), Variable('L'), Variable('R')],
4242 'mkterm': [Variable('T'), Variable('L')],
4343 }.get(name, [])
4444 return [Production('$.%s' % name, 0, formals, [], None)]
238238 self.emit('tamsin_startswith(scanner, term_flatten(temp)->atom);')
239239 elif name == 'unquote':
240240 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);')
243244 elif name == 'mkterm':
244245 self.emit_term(args[0], "temp_atom")
245246 self.emit_term(args[1], "temp_list")
167167 else:
168168 return (False, Atom("expected '%s, found '%s'" %
169169 (bindings['X'], self.scanner.peek())))
170 elif name == '$.unquote': # TODO this is definitely a bodge
170 elif name == '$.unquote':
171171 x = str(bindings['X'])
172 if (x.startswith(('"', "'"))):
172 if (x.startswith((str(bindings['L']),)) and
173 x.endswith((str(bindings['R']),))):
173174 return (True, Atom(x[1:-1]))
174175 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':
177179 t = bindings['T']
178180 l = bindings['L']
179181 contents = []