[RFC PATCH] parser: implement octal and hex literals
Export this patch
---
I'm not sure whether returning 0 in the case that none of the base
prefixes match is appropriate. If it's not, what's the better way to
handle that error?
parser/arithm.c | 58 +++++++++++++++++++++++++++++++++++++++++++------
test/arithm.sh | 3 +++
2 files changed, 54 insertions(+), 7 deletions(-)
diff --git a/parser/arithm.c b/parser/arithm.c
index cfd49e2..85c0602 100644
--- a/parser/arithm.c
+++ b/parser/arithm.c
@@ -53,18 +53,62 @@ static bool parse_str(struct mrsh_parser *parser, const char *str) {
return true;
}
+static bool isoctal(char c)
+{
+ return (unsigned)c - '0' < 8;
+}
+
static size_t peek_literal(struct mrsh_parser *parser) {
+ enum { DEC, OCT, HEX } base = DEC;
size_t i = 0;
- while (true) {
- parser_peek(parser, NULL, i + 1);
- char c = parser->buf.data[i];
- // TODO: 0x, 0b prefixes
- if (!isdigit(c)) {
- break;
+ parser_peek(parser, NULL, i + 1);
+ char c = parser->buf.data[i];
+ if (c == '0') {
+ parser_peek(parser, NULL, i + 2);
+ c = parser->buf.data[i + 1];
+ if (isoctal(c)) {
+ base = OCT;
+ i += 1;
+ } else if (c == 'x' || c == 'X') {
+ base = HEX;
+ i += 2;
+ } else {
+ return 0;
}
+ }
- ++i;
+ switch (base) {
+ case DEC:
+ while (true) {
+ parser_peek(parser, NULL, i + 1);
+ char c = parser->buf.data[i];
+ if (!isdigit(c)) {
+ break;
+ }
+ ++i;
+ }
+ break;
+ case OCT:
+ while (true) {
+ parser_peek(parser, NULL, i + 1);
+ c = parser->buf.data[i];
+ if (!isoctal(c)) {
+ break;
+ }
+ ++i;
+ }
+ break;
+ case HEX:
+ while (true) {
+ parser_peek(parser, NULL, i + 1);
+ c = parser->buf.data[i];
+ if (!isxdigit(c)) {
+ break;
+ }
+ ++i;
+ }
+ break;
}
return i;
diff --git a/test/arithm.sh b/test/arithm.sh
index 7cc9df5..1a0abb0 100644
--- a/test/arithm.sh
+++ b/test/arithm.sh
@@ -44,6 +44,9 @@ echo "\$a+2 =" $(($a+2))
# Assignments
a=0
+echo "(a=042) =" $((a=042)) "->" $a
+echo "(a=0x42af) =" $((a=0x42af)) "->" $a
+echo "(a=0X42AF) =" $((a=0X42AF)) "->" $a
echo "(a=42) =" $((a=42)) "->" $a
echo "(a+=1) =" $((a+=1)) "->" $a
echo "(a-=4) =" $((a-=4)) "->" $a
--
2.35.1