summaryrefslogtreecommitdiffstats
path: root/parser.y
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2011-11-15 14:29:34 -0800
committerKaz Kylheku <kaz@kylheku.com>2011-11-15 14:29:34 -0800
commitb6551fda77163f74983688409aaf0c13c8186bec (patch)
tree690b7abd40236f6ef5e168e84a0a4c6eeeb2d2c2 /parser.y
parent9ae8fe9b48cd8e56816225e467f8882c8313d876 (diff)
downloadtxr-b6551fda77163f74983688409aaf0c13c8186bec.tar.gz
txr-b6551fda77163f74983688409aaf0c13c8186bec.tar.bz2
txr-b6551fda77163f74983688409aaf0c13c8186bec.zip
Changing read syntax for character literals, because we are going to
need the single quote in the Lisp way for suppressing evaluation, eventually. I'm going with a Scheme-compatible syntax for character literals. It has a richer repertoire of standard character names than Common Lisp, and has a x convention for coding characters in hex. * lib.c (obj_print): Print characters in a Scheme-like way. * parser.h (end_of_char): New function declared. * parser.l (grammar): Implement rules for #\ syntax, with involving new HASH_BACKSLASH token. (end_of_regex): Enhancement: added check that end_of_regex is called in correct state, like the one in end_of_char. (end_of_char): New function. * parser.y (repeat_rep_helper, o_elems_transform, define_transform, lit_char_helper): Functions changed to static. (rl): Function moved down, past the grammar section. (HASH_BACKSLASH): New terminal symbol. (chrlit): Grammar redesigned. (char_from_name): New function. * txr.1: Character syntax documented.
Diffstat (limited to 'parser.y')
-rw-r--r--parser.y82
1 files changed, 58 insertions, 24 deletions
diff --git a/parser.y b/parser.y
index 3c0823e3..9089004c 100644
--- a/parser.y
+++ b/parser.y
@@ -43,21 +43,15 @@
int yylex(void);
void yyerror(const char *);
-val repeat_rep_helper(val sym, val main, val parts);
-val o_elems_transform(val output_form);
-val define_transform(val define_form);
-val lit_char_helper(val litchars);
+static val repeat_rep_helper(val sym, val main, val parts);
+static val o_elems_transform(val output_form);
+static val define_transform(val define_form);
+static val lit_char_helper(val litchars);
+static val rl(val form, val lineno);
+static wchar_t char_from_name(wchar_t *name);
static val parsed_spec;
-static val rl(val form, val lineno)
-{
- sethash(form_to_ln_hash, form, lineno);
- pushhash(ln_to_forms_hash, lineno, form);
- return form;
-}
-
-
%}
%union {
@@ -73,6 +67,7 @@ static val rl(val form, val lineno)
%token <lineno> UNTIL COLL OUTPUT REPEAT REP SINGLE FIRST LAST EMPTY DEFINE
%token <lineno> TRY CATCH FINALLY
%token <lineno> ERRTOK /* deliberately not used in grammar */
+%token <lineno> HASH_BACKSLASH
%token <num> NUMBER
@@ -110,7 +105,7 @@ static val rl(val form, val lineno)
spec : clauses { parsed_spec = $1; }
| /* empty */ { parsed_spec = nil; }
- | error '\n' { parsed_spec = nil;
+ | error '\n' { parsed_spec = nil;
if (errors >= 8)
YYABORT;
yyerrok;
@@ -699,13 +694,16 @@ strlit : '"' '"' { $$ = null_string; }
yybadtoken(yychar, lit("string literal")); }
;
-chrlit : '\'' '\'' { $$ = nil;
- yyerror("empty character literal"); }
- | '\'' litchars '\'' { $$ = car($2);
- if (cdr($2))
- yyerror("multiple characters in "
- "character literal"); }
- | '\'' error { $$ = nil;
+chrlit : HASH_BACKSLASH IDENT { wchar_t ch = char_from_name($2);
+ val str = string_own($2);
+ end_of_char();
+ if (ch == L'!')
+ { yyerrorf(lit("unknown character name: ~a"),
+ str, nao); }
+ $$ = chr(ch); }
+ | HASH_BACKSLASH LITCHAR { $$ = chr($2);
+ end_of_char(); }
+ | HASH_BACKSLASH error { $$ = nil;
yybadtoken(yychar,
lit("character literal")); }
;
@@ -733,7 +731,7 @@ litchars : LITCHAR { $$ = cons(chr($1), nil); }
%%
-val repeat_rep_helper(val sym, val main, val parts)
+static val repeat_rep_helper(val sym, val main, val parts)
{
val single_parts = nil;
val first_parts = nil;
@@ -762,7 +760,7 @@ val repeat_rep_helper(val sym, val main, val parts)
last_parts, empty_parts, nao);
}
-val o_elems_transform(val o_elems)
+static val o_elems_transform(val o_elems)
{
list_collect_decl(o_elems_out, ptail);
val iter;
@@ -786,7 +784,7 @@ val o_elems_transform(val o_elems)
return o_elems_out;
}
-val define_transform(val define_form)
+static val define_transform(val define_form)
{
val sym = first(define_form);
val args = second(define_form);
@@ -825,7 +823,7 @@ val define_transform(val define_form)
return define_form;
}
-val lit_char_helper(val litchars)
+static val lit_char_helper(val litchars)
{
val ret = nil;
@@ -844,6 +842,42 @@ val lit_char_helper(val litchars)
return ret;
}
+static val rl(val form, val lineno)
+{
+ sethash(form_to_ln_hash, form, lineno);
+ pushhash(ln_to_forms_hash, lineno, form);
+ return form;
+}
+
+static wchar_t char_from_name(wchar_t *name)
+{
+ static struct {
+ wchar_t *name;
+ wchar_t ch;
+ } map[] = {
+ { L"nul", 0 },
+ { L"alarm", L'\a' },
+ { L"backspace", L'\b' },
+ { L"tab", L'\t' },
+ { L"linefeed", L'\n' },
+ { L"newline", L'\n' },
+ { L"vtab", L'\v' },
+ { L"page", L'\f' },
+ { L"return", L'\r' },
+ { L"esc", 27 },
+ { L"space", L' ' },
+ { 0, 0 },
+ };
+ int i;
+
+ for (i = 0; map[i].name; i++) {
+ if (wcscmp(map[i].name, name) == 0)
+ return map[i].ch;
+ }
+
+ return L'!'; /* code meaning not found */
+}
+
val get_spec(void)
{
return parsed_spec;