aboutsummaryrefslogtreecommitdiff
path: root/src/parse.cff
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse.cff')
-rw-r--r--src/parse.cff23
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);
}