@@ -126,6 +126,10 @@ static bool is_following_digit(mp_lexer_t *lex) {
126126 return unichar_isdigit (lex -> chr1 );
127127}
128128
129+ static bool is_following_odigit (mp_lexer_t * lex ) {
130+ return lex -> chr1 >= '0' && lex -> chr1 <= '7' ;
131+ }
132+
129133// TODO UNICODE include unicode characters in definition of identifiers
130134static bool is_head_of_identifier (mp_lexer_t * lex ) {
131135 return is_letter (lex ) || lex -> chr0 == '_' ;
@@ -275,6 +279,32 @@ static const char *tok_kw[] = {
275279 NULL ,
276280};
277281
282+ static int hex_digit (unichar c ) {
283+ // c is assumed to be hex digit
284+ int n = c - '0' ;
285+ if (n > 9 ) {
286+ n &= ~('a' - 'A' );
287+ n -= ('A' - ('9' + 1 ));
288+ }
289+ return n ;
290+ }
291+
292+ // This is called with CUR_CHAR() before first hex digit, and should return with
293+ // it pointing to last hex digit
294+ static bool get_hex (mp_lexer_t * lex , int num_digits , uint * result ) {
295+ uint num = 0 ;
296+ while (num_digits -- != 0 ) {
297+ next_char (lex );
298+ unichar c = CUR_CHAR (lex );
299+ if (!unichar_isxdigit (c )) {
300+ return false;
301+ }
302+ num = (num << 4 ) + hex_digit (c );
303+ }
304+ * result = num ;
305+ return true;
306+ }
307+
278308static void mp_lexer_next_token_into (mp_lexer_t * lex , mp_token_t * tok , bool first_token ) {
279309 // skip white space and comments
280310 bool had_physical_newline = false;
@@ -439,12 +469,34 @@ static void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
439469 case 'v' : c = 0x0b ; break ;
440470 case 'f' : c = 0x0c ; break ;
441471 case 'r' : c = 0x0d ; break ;
442- // TODO \ooo octal
443- case 'x' : // TODO \xhh
444- case 'N' : // TODO \N{name} only in strings
445- case 'u' : // TODO \uxxxx only in strings
446- case 'U' : // TODO \Uxxxxxxxx only in strings
447- default : break ; // TODO error message
472+ case 'x' :
473+ {
474+ uint num ;
475+ if (!get_hex (lex , 2 , & num )) {
476+ // TODO error message
477+ assert (0 );
478+ }
479+ c = num ;
480+ break ;
481+ }
482+ case 'N' : break ; // TODO \N{name} only in strings
483+ case 'u' : break ; // TODO \uxxxx only in strings
484+ case 'U' : break ; // TODO \Uxxxxxxxx only in strings
485+ default :
486+ if (c >= '0' && c <= '7' ) {
487+ // Octal sequence, 1-3 chars
488+ int digits = 3 ;
489+ int num = c - '0' ;
490+ while (is_following_odigit (lex ) && -- digits != 0 ) {
491+ next_char (lex );
492+ num = num * 8 + (CUR_CHAR (lex ) - '0' );
493+ }
494+ c = num ;
495+ } else {
496+ // TODO error message
497+ assert (0 );
498+ }
499+ break ;
448500 }
449501 if (c != MP_LEXER_CHAR_EOF ) {
450502 vstr_add_char (& lex -> vstr , c );
0 commit comments