From b6551fda77163f74983688409aaf0c13c8186bec Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Tue, 15 Nov 2011 14:29:34 -0800 Subject: 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. --- parser.y | 82 +++++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 24 deletions(-) (limited to 'parser.y') 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 UNTIL COLL OUTPUT REPEAT REP SINGLE FIRST LAST EMPTY DEFINE %token TRY CATCH FINALLY %token ERRTOK /* deliberately not used in grammar */ +%token HASH_BACKSLASH %token 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; -- cgit v1.2.3