From f8884c494c66951b5874b2b587004649c80a39eb Mon Sep 17 00:00:00 2001 From: CPunch Date: Mon, 18 Jan 2021 19:42:15 -0600 Subject: [PATCH] Added Hexadecimal encoding and binary encoding to numbers using '0x' and '0b' --- src/clex.c | 31 +++++++++++++++++++++++++++++-- src/clex.h | 2 ++ src/cparse.c | 12 ++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/clex.c b/src/clex.c index 230d177..5d00652 100644 --- a/src/clex.c +++ b/src/clex.c @@ -245,10 +245,37 @@ CToken parseString(CLexState *state) { return makeToken(state, TOKEN_STRING); } -CToken parseNumber(CLexState *state) { +bool isHex(char c) { + return isNumerical(c) || ('A' <= c && 'F' >= c) || ('a' <= c && 'f' >= c); +} + +CToken parseNumber(CLexState *state) { + switch (peek(state)) { + case 'x': // hexadecimal number + next(state); + + while (isHex(peek(state))) + next(state); + + return makeToken(state, TOKEN_HEXNUMBER); + case 'b': // binary number + next(state); + + while (peek(state) == '0' || peek(state) == '1') + next(state); + + return makeToken(state, TOKEN_BINNUMBER); + default: + if (!isNumerical(peek(state))) + return makeError(state, "Unrecognized number encoding!"); + // if it is a number, fall through and parse normally + } + + // consume number - while (isNumerical(peek(state))) + while (isNumerical(peek(state))) { next(state); + } if (peek(state) == '.' && isNumerical(peekNext(state))) { next(state); // consume '.' diff --git a/src/clex.h b/src/clex.h index 23e4728..552b3c7 100644 --- a/src/clex.h +++ b/src/clex.h @@ -40,6 +40,8 @@ typedef enum { TOKEN_IDENTIFIER, TOKEN_STRING, // token.start is heap allocated and separate from the source string! TOKEN_NUMBER, + TOKEN_HEXNUMBER, + TOKEN_BINNUMBER, TOKEN_NIL, TOKEN_TRUE, TOKEN_FALSE, diff --git a/src/cparse.c b/src/cparse.c index 4639c34..dc63485 100644 --- a/src/cparse.c +++ b/src/cparse.c @@ -407,6 +407,16 @@ static void number(CParseState *pstate, bool canAssign, Precedence prec) { writeConstant(pstate, cosmoV_newNumber(num)); } +static void hexnumber(CParseState *pstate, bool canAssign, Precedence prec) { + cosmo_Number num = strtol(pstate->previous.start + 2, NULL, 16); // +2 to skip the '0x' + writeConstant(pstate, cosmoV_newNumber(num)); +} + +static void binnumber(CParseState *pstate, bool canAssign, Precedence prec) { + cosmo_Number num = strtol(pstate->previous.start + 2, NULL, 2); // +2 to skip the '0b' + writeConstant(pstate, cosmoV_newNumber(num)); +} + static void string(CParseState *pstate, bool canAssign, Precedence prec) { CObjString *strObj = cosmoO_takeString(pstate->state, pstate->previous.start, pstate->previous.length); writeConstant(pstate, cosmoV_newObj((CObj*)strObj)); @@ -922,6 +932,8 @@ ParseRule ruleTable[] = { [TOKEN_IDENTIFIER] = {variable, NULL, PREC_NONE}, [TOKEN_STRING] = {string, NULL, PREC_NONE}, [TOKEN_NUMBER] = {number, NULL, PREC_NONE}, + [TOKEN_HEXNUMBER] = {hexnumber, NULL, PREC_NONE}, + [TOKEN_BINNUMBER] = {binnumber, NULL, PREC_NONE}, [TOKEN_NIL] = {literal, NULL, PREC_NONE}, [TOKEN_TRUE] = {literal, NULL, PREC_NONE}, [TOKEN_FALSE] = {literal, NULL, PREC_NONE},