diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2011-11-15 14:29:34 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2011-11-15 14:29:34 -0800 |
commit | b6551fda77163f74983688409aaf0c13c8186bec (patch) | |
tree | 690b7abd40236f6ef5e168e84a0a4c6eeeb2d2c2 /parser.y | |
parent | 9ae8fe9b48cd8e56816225e467f8882c8313d876 (diff) | |
download | txr-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.y | 82 |
1 files changed, 58 insertions, 24 deletions
@@ -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; |