mirror of
https://github.com/janet-lang/janet
synced 2024-09-28 23:10:40 +00:00
Add custom base option to number peg combinator.
Allows parsing custom bases without needed Janet specific prefixes.
This commit is contained in:
parent
4fd7470bbf
commit
9985f787eb
@ -394,12 +394,13 @@ tail:
|
|||||||
if (!result) return NULL;
|
if (!result) return NULL;
|
||||||
/* check number parsing */
|
/* check number parsing */
|
||||||
double x = 0.0;
|
double x = 0.0;
|
||||||
if (janet_scan_number(text, (int32_t)(result - text), &x)) return NULL;
|
int32_t base = (int32_t) rule[2];
|
||||||
|
if (janet_scan_number_base(text, (int32_t)(result - text), base, &x)) return NULL;
|
||||||
/* Specialized pushcap - avoid intermediate string creation */
|
/* Specialized pushcap - avoid intermediate string creation */
|
||||||
if (!s->has_backref && s->mode == PEG_MODE_ACCUMULATE) {
|
if (!s->has_backref && s->mode == PEG_MODE_ACCUMULATE) {
|
||||||
janet_buffer_push_bytes(s->scratch, text, (int32_t)(result - text));
|
janet_buffer_push_bytes(s->scratch, text, (int32_t)(result - text));
|
||||||
} else {
|
} else {
|
||||||
uint32_t tag = rule[2];
|
uint32_t tag = rule[3];
|
||||||
pushcap(s, janet_wrap_number(x), tag);
|
pushcap(s, janet_wrap_number(x), tag);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -983,9 +984,6 @@ static void spec_cap1(Builder *b, int32_t argc, const Janet *argv, uint32_t op)
|
|||||||
static void spec_capture(Builder *b, int32_t argc, const Janet *argv) {
|
static void spec_capture(Builder *b, int32_t argc, const Janet *argv) {
|
||||||
spec_cap1(b, argc, argv, RULE_CAPTURE);
|
spec_cap1(b, argc, argv, RULE_CAPTURE);
|
||||||
}
|
}
|
||||||
static void spec_capture_number(Builder *b, int32_t argc, const Janet *argv) {
|
|
||||||
spec_cap1(b, argc, argv, RULE_CAPTURE_NUM);
|
|
||||||
}
|
|
||||||
static void spec_accumulate(Builder *b, int32_t argc, const Janet *argv) {
|
static void spec_accumulate(Builder *b, int32_t argc, const Janet *argv) {
|
||||||
spec_cap1(b, argc, argv, RULE_ACCUMULATE);
|
spec_cap1(b, argc, argv, RULE_ACCUMULATE);
|
||||||
}
|
}
|
||||||
@ -996,6 +994,25 @@ static void spec_unref(Builder *b, int32_t argc, const Janet *argv) {
|
|||||||
spec_cap1(b, argc, argv, RULE_UNREF);
|
spec_cap1(b, argc, argv, RULE_UNREF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void spec_capture_number(Builder *b, int32_t argc, const Janet *argv) {
|
||||||
|
peg_arity(b, argc, 1, 3);
|
||||||
|
Reserve r = reserve(b, 4);
|
||||||
|
uint32_t base = 0;
|
||||||
|
if (argc >= 2) {
|
||||||
|
if (!janet_checktype(argv[1], JANET_NIL)) {
|
||||||
|
if (!janet_checkint(argv[1])) goto error;
|
||||||
|
base = (uint32_t) janet_unwrap_integer(argv[1]);
|
||||||
|
if (base < 2 || base > 36) goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint32_t tag = (argc == 3) ? emit_tag(b, argv[2]) : 0;
|
||||||
|
uint32_t rule = peg_compile1(b, argv[0]);
|
||||||
|
emit_3(r, RULE_CAPTURE_NUM, rule, base, tag);
|
||||||
|
return;
|
||||||
|
error:
|
||||||
|
peg_panicf(b, "expected integer between 2 and 36, got %v", argv[2]);
|
||||||
|
}
|
||||||
|
|
||||||
static void spec_reference(Builder *b, int32_t argc, const Janet *argv) {
|
static void spec_reference(Builder *b, int32_t argc, const Janet *argv) {
|
||||||
peg_arity(b, argc, 1, 2);
|
peg_arity(b, argc, 1, 2);
|
||||||
Reserve r = reserve(b, 3);
|
Reserve r = reserve(b, 3);
|
||||||
@ -1441,10 +1458,15 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
|
|||||||
if (rule[1] >= clen) goto bad;
|
if (rule[1] >= clen) goto bad;
|
||||||
i += 3;
|
i += 3;
|
||||||
break;
|
break;
|
||||||
|
case RULE_CAPTURE_NUM:
|
||||||
|
/* [rule, base, tag] */
|
||||||
|
if (rule[1] >= blen) goto bad;
|
||||||
|
op_flags[rule[1]] |= 0x01;
|
||||||
|
i += 4;
|
||||||
|
break;
|
||||||
case RULE_ACCUMULATE:
|
case RULE_ACCUMULATE:
|
||||||
case RULE_GROUP:
|
case RULE_GROUP:
|
||||||
case RULE_CAPTURE:
|
case RULE_CAPTURE:
|
||||||
case RULE_CAPTURE_NUM:
|
|
||||||
case RULE_UNREF:
|
case RULE_UNREF:
|
||||||
/* [rule, tag] */
|
/* [rule, tag] */
|
||||||
if (rule[1] >= blen) goto bad;
|
if (rule[1] >= blen) goto bad;
|
||||||
|
@ -247,14 +247,14 @@ static double convert(
|
|||||||
|
|
||||||
/* Scan a real (double) from a string. If the string cannot be converted into
|
/* Scan a real (double) from a string. If the string cannot be converted into
|
||||||
* and integer, return 0. */
|
* and integer, return 0. */
|
||||||
int janet_scan_number(
|
int janet_scan_number_base(
|
||||||
const uint8_t *str,
|
const uint8_t *str,
|
||||||
int32_t len,
|
int32_t len,
|
||||||
|
int32_t base,
|
||||||
double *out) {
|
double *out) {
|
||||||
const uint8_t *end = str + len;
|
const uint8_t *end = str + len;
|
||||||
int seenadigit = 0;
|
int seenadigit = 0;
|
||||||
int ex = 0;
|
int ex = 0;
|
||||||
int base = 10;
|
|
||||||
int seenpoint = 0;
|
int seenpoint = 0;
|
||||||
int foundexp = 0;
|
int foundexp = 0;
|
||||||
int neg = 0;
|
int neg = 0;
|
||||||
@ -278,6 +278,7 @@ int janet_scan_number(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check for leading 0x or digit digit r */
|
/* Check for leading 0x or digit digit r */
|
||||||
|
if (base == 0) {
|
||||||
if (str + 1 < end && str[0] == '0' && str[1] == 'x') {
|
if (str + 1 < end && str[0] == '0' && str[1] == 'x') {
|
||||||
base = 16;
|
base = 16;
|
||||||
str += 2;
|
str += 2;
|
||||||
@ -294,6 +295,12 @@ int janet_scan_number(
|
|||||||
if (base < 2 || base > 36) goto error;
|
if (base < 2 || base > 36) goto error;
|
||||||
str += 3;
|
str += 3;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If still base is 0, set to default (10) */
|
||||||
|
if (base == 0) {
|
||||||
|
base = 10;
|
||||||
|
}
|
||||||
|
|
||||||
/* Skip leading zeros */
|
/* Skip leading zeros */
|
||||||
while (str < end && (*str == '0' || *str == '.')) {
|
while (str < end && (*str == '0' || *str == '.')) {
|
||||||
@ -376,6 +383,13 @@ error:
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int janet_scan_number(
|
||||||
|
const uint8_t *str,
|
||||||
|
int32_t len,
|
||||||
|
double *out) {
|
||||||
|
return janet_scan_number_base(str, len, 0, out);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef JANET_INT_TYPES
|
#ifdef JANET_INT_TYPES
|
||||||
|
|
||||||
static int scan_uint64(
|
static int scan_uint64(
|
||||||
|
@ -1522,6 +1522,7 @@ JANET_API int janet_loop_fiber(JanetFiber *fiber);
|
|||||||
|
|
||||||
/* Number scanning */
|
/* Number scanning */
|
||||||
JANET_API int janet_scan_number(const uint8_t *str, int32_t len, double *out);
|
JANET_API int janet_scan_number(const uint8_t *str, int32_t len, double *out);
|
||||||
|
JANET_API int janet_scan_number_base(const uint8_t *str, int32_t len, int32_t base, double *out);
|
||||||
JANET_API int janet_scan_int64(const uint8_t *str, int32_t len, int64_t *out);
|
JANET_API int janet_scan_int64(const uint8_t *str, int32_t len, int64_t *out);
|
||||||
JANET_API int janet_scan_uint64(const uint8_t *str, int32_t len, uint64_t *out);
|
JANET_API int janet_scan_uint64(const uint8_t *str, int32_t len, uint64_t *out);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user