#include "sl_pp_token.h"
+static int
+_is_identifier_char(char c)
+{
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
+}
+
+
static int
_tokenise_identifier(struct sl_pp_context *context,
const char **pinput,
info->data.identifier = -1;
identifier[i++] = *input++;
- while ((*input >= 'a' && *input <= 'z') ||
- (*input >= 'A' && *input <= 'Z') ||
- (*input >= '0' && *input <= '9') ||
- (*input == '_')) {
+ while (_is_identifier_char(*input)) {
if (i >= sizeof(identifier) - 1) {
strcpy(context->error_msg, "out of memory");
return -1;
}
+/*
+ * Return the number of consecutive decimal digits in the input stream.
+ */
+static unsigned int
+_parse_float_digits(const char *input)
+{
+ unsigned int eaten = 0;
+
+ while (input[eaten] >= '0' && input[eaten] <= '9') {
+ eaten++;
+ }
+ return eaten;
+}
+
+
+/*
+ * Try to match one of the following patterns for the fractional part
+ * of a floating point number.
+ *
+ * digits . [digits]
+ * . digits
+ *
+ * Return 0 if the pattern could not be matched, otherwise the number
+ * of eaten characters from the input stream.
+ */
+static unsigned int
+_parse_float_frac(const char *input)
+{
+ unsigned int eaten;
+
+ if (input[0] == '.') {
+ eaten = _parse_float_digits(&input[1]);
+ if (eaten) {
+ return eaten + 1;
+ }
+ return 0;
+ }
+
+ eaten = _parse_float_digits(input);
+ if (eaten && input[eaten] == '.') {
+ unsigned int trailing;
+
+ trailing = _parse_float_digits(&input[eaten + 1]);
+ if (trailing) {
+ return eaten + trailing + 1;
+ }
+ return eaten + 1;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Try to match the following pattern for the exponential part
+ * of a floating point number.
+ *
+ * (e|E) [(+|-)] digits
+ *
+ * Return 0 if the pattern could not be matched, otherwise the number
+ * of eaten characters from the input stream.
+ */
+static unsigned int
+_parse_float_exp(const char *input)
+{
+ unsigned int eaten, digits;
+
+ if (input[0] != 'e' && input[0] != 'E') {
+ return 0;
+ }
+
+ if (input[1] == '-' || input[1] == '+') {
+ eaten = 2;
+ } else {
+ eaten = 1;
+ }
+
+ digits = _parse_float_digits(&input[eaten]);
+ if (!digits) {
+ return 0;
+ }
+
+ return eaten + digits;
+}
+
+
+/*
+ * Try to match one of the following patterns for a floating point number.
+ *
+ * fract [exp] [(f|F)]
+ * digits exp [(f|F)]
+ *
+ * Return 0 if the pattern could not be matched, otherwise the number
+ * of eaten characters from the input stream.
+ */
+static unsigned int
+_parse_float(const char *input)
+{
+ unsigned int eaten;
+
+ eaten = _parse_float_frac(input);
+ if (eaten) {
+ unsigned int exponent;
+
+ exponent = _parse_float_exp(&input[eaten]);
+ if (exponent) {
+ eaten += exponent;
+ }
+
+ if (input[eaten] == 'f' || input[eaten] == 'F') {
+ eaten++;
+ }
+
+ return eaten;
+ }
+
+ eaten = _parse_float_digits(input);
+ if (eaten) {
+ unsigned int exponent;
+
+ exponent = _parse_float_exp(&input[eaten]);
+ if (exponent) {
+ eaten += exponent;
+
+ if (input[eaten] == 'f' || input[eaten] == 'F') {
+ eaten++;
+ }
+
+ return eaten;
+ }
+ }
+
+ return 0;
+}
+
+
+static unsigned int
+_parse_hex(const char *input)
+{
+ unsigned int n;
+
+ if (input[0] != '0') {
+ return 0;
+ }
+
+ if (input[1] != 'x' && input[1] != 'X') {
+ return 0;
+ }
+
+ n = 2;
+ while ((input[n] >= '0' && input[n] <= '9') ||
+ (input[n] >= 'a' && input[n] <= 'f') ||
+ (input[n] >= 'A' && input[n] <= 'F')) {
+ n++;
+ }
+
+ if (n > 2) {
+ return n;
+ }
+
+ return 0;
+}
+
+
+static unsigned int
+_parse_oct(const char *input)
+{
+ unsigned int n;
+
+ if (input[0] != '0') {
+ return 0;
+ }
+
+ n = 1;
+ while ((input[n] >= '0' && input[n] <= '7')) {
+ n++;
+ }
+
+ return n;
+}
+
+
+static unsigned int
+_parse_dec(const char *input)
+{
+ unsigned int n = 0;
+
+ while ((input[n] >= '0' && input[n] <= '9')) {
+ n++;
+ }
+
+ return n;
+}
+
+
static int
_tokenise_number(struct sl_pp_context *context,
const char **pinput,
struct sl_pp_token_info *info)
{
const char *input = *pinput;
+ unsigned int eaten;
char number[256]; /* XXX: Remove this artifical limit. */
- unsigned int i = 0;
- info->token = SL_PP_NUMBER;
- info->data.number = -1;
-
- number[i++] = *input++;
- while ((*input >= '0' && *input <= '9') ||
- (*input >= 'a' && *input <= 'f') ||
- (*input >= 'A' && *input <= 'F') ||
- (*input == 'x') ||
- (*input == 'X') ||
- (*input == '+') ||
- (*input == '-') ||
- (*input == '.')) {
- if (i >= sizeof(number) - 1) {
- strcpy(context->error_msg, "out of memory");
- return -1;
+ eaten = _parse_float(input);
+ if (!eaten) {
+ eaten = _parse_hex(input);
+ if (!eaten) {
+ eaten = _parse_oct(input);
+ if (!eaten) {
+ eaten = _parse_dec(input);
+ }
}
- number[i++] = *input++;
}
- number[i++] = '\0';
+ if (!eaten || _is_identifier_char(input[eaten])) {
+ strcpy(context->error_msg, "expected a number");
+ return -1;
+ }
+
+ if (eaten > sizeof(number) - 1) {
+ strcpy(context->error_msg, "out of memory");
+ return -1;
+ }
+
+ memcpy(number, input, eaten);
+ number[eaten] = '\0';
+
+ info->token = SL_PP_NUMBER;
info->data.number = sl_pp_context_add_unique_str(context, number);
if (info->data.number == -1) {
return -1;
}
- *pinput = input;
+ *pinput = input + eaten;
return 0;
}