diff options
Diffstat (limited to 'src/parse.cff')
| -rw-r--r-- | src/parse.cff | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/src/parse.cff b/src/parse.cff index 0843ccf..25a2617 100644 --- a/src/parse.cff +++ b/src/parse.cff @@ -1,5 +1,7 @@ +import "mem.hff"; +import "util.hff"; import "vec.hff"; -import "all.hff"; +import "cffc.hff"; /////////// // Lexer // @@ -164,6 +166,15 @@ fn str2keyword(s *const u8) int { return -1; } +fn xdigit2num(c u8) int { + switch { + case isdigit(c); return c - '0'; + case c >= 'a' and c <= 'f'; return (c - 'a') + 10; + case c >= 'A' and c <= 'F'; return (c - 'A') + 10; + } + return -1; +} + fn readnumber(s *const u8) Option<Tok> { let c u8 #?, acc = 0u64, @@ -198,8 +209,7 @@ fn readnumber(s *const u8) Option<Tok> { accf = accf + ((c - '0') * fmul); fmul *= 0.1; } else { - c = tolower(c); - acc = (acc * base) + (c <= '9' ? c - '0' : (c - 'a') + 10); + acc = (acc * base) + xdigit2num(c); } } @@ -323,6 +333,13 @@ fn lex(P *Parser) Tok { case 'r'; str->push('\r'); case 't'; str->push('\t'); case 'v'; str->push('\v'); case 'f'; str->push('\f'); case '0'; str->push('\0'); + case 'x'; + let x0 = xdigit2num(chr(P)), + x1 = xdigit2num(chr(P)); + if x0 < 0 or x1 < 0 { + fatal(P, P.tokloc, "not a hex byte escape sequence"); + } + str->push((x0 << 4) | x1); case else fatal(P, P.tokloc, "unknown escape sequence '\\%c'", c); } |