void test_tok(void) {
TESTBEGIN("tok");
- assert_tok(" test tokens with, line / * + - , ; $1",
- {"test", "tokens", "with", ",", "line", "/", "*", "+", "-", ",",
- ";", "$1", NULL});
+ assert_tok(
+ " test tokens with, line / * + - , ; $1 = == != > < >= <=",
+ {"test", "tokens", "with", ",", "line", "/", "*", "+", "-", ",",
+ ";", "$1", "=", "==", "!=", ">", "<", ">=", "<=", NULL});
assert_tokuntil(" this is a, test for tok , until", ',',
{"this is a", "test for tok ", "until", NULL});
assert((expected_rc) == rc); \
}
-
-#define ASSERT_TOTOK(expected_val, expected_rc, token) \
+#define ASSERT_TOTOK(expected_val, expected_rc, token) \
{ \
int rc = 0; \
struct ulas_tok tok = ulas_totok((token), strlen(token), &rc); \
assert((expected_rc) == rc); \
- assert(tok.type == (expected_val)); \
+ assert(tok.type == (expected_val)); \
free(tok.val.strv); \
}
ASSERT_UNEXPECTED_TOTOK(-1, "1symbol123");
- // generic tokens with no value
+ // generic tokens with no value
ASSERT_TOTOK(ULAS_EQ, 0, "==");
+ ASSERT_TOTOK(ULAS_NEQ, 0, "!=");
ASSERT_TOTOK('=', 0, "=");
ASSERT_TOTOK('+', 0, "+");
+ ASSERT_TOTOK('!', 0, "!");
TESTEND("totok");
}
char c = line[i];
switch (c) {
- case ',':
case '+':
case '-':
case '*':
case '/':
+ case '~':
+ case '|':
+ case '&':
+ case '%':
+ case '(':
+ case ')':
+ case '[':
+ case ']':
+ case ',':
case '\\':
case ULAS_TOK_COMMENT:
if (WELD_TOKISTERM) {
dst->buf[write++] = line[i++];
dst->buf[write++] = line[i++];
goto tokdone;
+ case '=':
+ case '<':
+ case '!':
+ case '>':
+ if (line[i + 1] == '=') {
+ dst->buf[write] = line[i];
+ i++;
+ write++;
+ }
+ dst->buf[write] = line[i];
+ write++;
+ break;
default:
if (isspace(line[i])) {
goto tokdone;
unsigned char first = buf[0];
buf++;
- switch (first) {
- case '+':
- case '-':
- case '*':
- case '/':
- case '~':
- case '|':
- case '&':
- case '%':
- case '(':
- case ')':
- case '[':
- case ']':
- case ',':
- case ';':
+ if (n == 1) {
// single char tokens
tok.type = first;
- goto end;
- case '"':
- // string
- tok.type = ULAS_STR;
-
- // FIXME: this likely mallocs a few extra bytes
- // but honestly its probably fine
- tok.val.strv = malloc(n * sizeof(char) + 1);
- memset(tok.val.strv, 0, n);
-
- long i = 0;
- while (*buf && *buf != '\"') {
- if (*buf == '\\') {
+ } else {
+ switch (first) {
+ case '"':
+ // string
+ tok.type = ULAS_STR;
+
+ // FIXME: this likely mallocs a few extra bytes
+ // but honestly its probably fine
+ tok.val.strv = malloc(n * sizeof(char) + 1);
+ memset(tok.val.strv, 0, n);
+
+ long i = 0;
+ while (*buf && *buf != '\"') {
+ if (*buf == '\\') {
+ buf++;
+ tok.val.strv[i] = ulas_unescape(*buf, rc);
+ } else {
+ tok.val.strv[i] = *buf;
+ }
+ i++;
buf++;
- tok.val.strv[i] = ulas_unescape(*buf, rc);
- } else {
- tok.val.strv[i] = *buf;
}
- i++;
- buf++;
- }
- tok.val.strv[i] = '\0';
+ tok.val.strv[i] = '\0';
- if (*buf != '\"') {
- *rc = -1;
- ULASERR("Unterminated string sequence\n");
- goto end;
- }
- buf++;
- break;
- case '=':
- if (*buf == '=') {
- tok.type = ULAS_EQ;
- buf++;
- } else {
- tok.type = first;
- }
- break;
- case '!':
- if (*buf == '=') {
- tok.type = ULAS_NEQ;
+ if (*buf != '\"') {
+ *rc = -1;
+ ULASERR("Unterminated string sequence\n");
+ goto end;
+ }
buf++;
- } else {
- tok.type = first;
- }
- break;
- default:
- if (isdigit(first)) {
- // integer
- tok.type = ULAS_INT;
-
- // 0b prefix is not supported in strtol... so we implement it by hand
- if (*buf == 'b') {
+ break;
+ case '=':
+ if (*buf == '=') {
+ tok.type = ULAS_EQ;
buf++;
- tok.val.intv = (int)strtol(buf, &buf, 2);
- } else {
- tok.val.intv = (int)strtol(buf - 1, &buf, 0);
}
- } else if (first == '\'') {
- tok.type = ULAS_INT;
- if (*buf == '\\') {
+ break;
+ case '!':
+ if (*buf == '=') {
+ tok.type = ULAS_NEQ;
buf++;
- tok.val.intv = ulas_unescape(*buf, rc);
- } else {
- tok.val.intv = (int)*buf;
}
- buf++;
- if (*buf != '\'') {
+ break;
+ case '<':
+ if (*buf == '=') {
+ tok.type = ULAS_LTEQ;
+ buf++;
+ }
+ break;
+ case '>':
+ if (*buf == '=') {
+ tok.type = ULAS_GTEQ;
+ buf++;
+ }
+ break;
+ default:
+ if (isdigit(first)) {
+ // integer
+ tok.type = ULAS_INT;
+
+ // 0b prefix is not supported in strtol... so we implement it by hand
+ if (*buf == 'b') {
+ buf++;
+ tok.val.intv = (int)strtol(buf, &buf, 2);
+ } else {
+ tok.val.intv = (int)strtol(buf - 1, &buf, 0);
+ }
+ } else if (first == '\'') {
+ tok.type = ULAS_INT;
+ if (*buf == '\\') {
+ buf++;
+ tok.val.intv = ulas_unescape(*buf, rc);
+ } else {
+ tok.val.intv = (int)*buf;
+ }
+ buf++;
+ if (*buf != '\'') {
+ *rc = -1;
+ ULASERR("Unterminated character sequence\n");
+ goto end;
+ }
+ buf++;
+ break;
+ } else if (ulas_isname(buf - 1, n)) {
+ // literal token
+ // we resolve it later, will need to malloc here for now
+ tok.type = ULAS_SYMBOL;
+ tok.val.strv = strndup(buf - 1, n);
+ buf += n - 1;
+ } else {
+ ULASERR("Unexpected token: %s\n", buf);
*rc = -1;
- ULASERR("Unterminated character sequence\n");
goto end;
}
- buf++;
break;
- } else if (ulas_isname(buf - 1, n)) {
- // literal token
- // we resolve it later, will need to malloc here for now
- tok.type = ULAS_SYMBOL;
- tok.val.strv = strndup(buf - 1, n);
- buf += n - 1;
- } else {
- ULASERR("Unexpected token: %s\n", buf);
- *rc = -1;
- goto end;
}
- break;
}
end: