1
0
Fork 0

Escape in strings

This commit is contained in:
Alex Kotov 2023-05-07 15:01:02 +04:00
parent 55dd616416
commit 4c7acd92f0
Signed by: kotovalexarian
GPG Key ID: 553C0EBBEB5D5F08
4 changed files with 45 additions and 15 deletions

View File

@ -655,7 +655,18 @@ struct Object *func_display(
printf("%li", object->number.i64);
break;
case TYPE_STRING:
printf("\"%s\"", object->s);
putchar('"');
for (char *str = object->s; *str; ++str) {
const char chr = *str;
if (chr == '\\') {
printf("\\\\");
} else if (chr == '\"') {
printf("\\\"");
} else {
putchar(chr);
}
}
putchar('"');
break;
}

View File

@ -354,6 +354,8 @@ void Lexer_lex(const Lexer self, const char chr)
if (chr == '"') {
token_finish(self);
token_start(self, STATE_STRING_END);
} else if (chr == '\\') {
self->state = STATE_STRING_ESCAPE;
} else {
token_putc(self, chr);
}
@ -389,5 +391,13 @@ void Lexer_lex(const Lexer self, const char chr)
assert(0);
}
break;
case STATE_STRING_ESCAPE:
if (chr == '\\' || chr == '"') {
token_putc(self, chr);
self->state = STATE_STRING_INSIDE;
} else {
assert(0);
}
break;
}
}

View File

@ -31,6 +31,7 @@ enum Lexer_State {
STATE_STRING_START,
STATE_STRING_INSIDE,
STATE_STRING_END,
STATE_STRING_ESCAPE,
};
typedef struct Lexer {

View File

@ -20,22 +20,30 @@
(assert-equal
(arcana/tokenize "#false")
(list (cons 'TOKEN_TAG "false")))
;(assert-equal
; (arcana/tokenize "\"\"")
; (list (cons 'TOKEN_STRING "\"\"")))
;(assert-equal
; (arcana/tokenize "\"qwe\"")
; (list (cons 'TOKEN_STRING "\"qwe\"")))
(assert-equal
(arcana/tokenize "\"\"")
(list (cons 'TOKEN_STRING "")))
(assert-equal
(arcana/tokenize "\"qwe\"")
(list (cons 'TOKEN_STRING "qwe")))
(assert-equal
(arcana/tokenize "(displayln \"qwe\")")
(list
(cons 'TOKEN_ROUND_OPEN "(")
(cons 'TOKEN_IDENT "displayln")
(cons 'TOKEN_STRING "qwe")
(cons 'TOKEN_ROUND_CLOSE ")")))
(assert-equal
(arcana/tokenize "(displayln (list 1))")
(list
(cons 'TOKEN_ROUND_OPEN "(")
(cons 'TOKEN_IDENT "displayln")
(cons 'TOKEN_ROUND_OPEN "(")
(cons 'TOKEN_IDENT "list")
(cons 'TOKEN_NUM "1")
(cons 'TOKEN_ROUND_CLOSE ")")
(cons 'TOKEN_ROUND_CLOSE ")")))
(list
(cons 'TOKEN_ROUND_OPEN "(")
(cons 'TOKEN_IDENT "displayln")
(cons 'TOKEN_ROUND_OPEN "(")
(cons 'TOKEN_IDENT "list")
(cons 'TOKEN_NUM "1")
(cons 'TOKEN_ROUND_CLOSE ")")
(cons 'TOKEN_ROUND_CLOSE ")")))
;;; arcana/typeof ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(assert-equal 'null (arcana/typeof '()))