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); printf("%li", object->number.i64);
break; break;
case TYPE_STRING: 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; break;
} }

View file

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

View file

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