Skip to content

Instantly share code, notes, and snippets.

@skeeto
Created July 14, 2024 17:59
Show Gist options
  • Save skeeto/b46b4ee3411b05f3af6c4320b2fe82a1 to your computer and use it in GitHub Desktop.
Save skeeto/b46b4ee3411b05f3af6c4320b2fe82a1 to your computer and use it in GitHub Desktop.
// Ref: https://old.reddit.com/r/C_Programming/comments/1e30ce8/
#include <stddef.h>
#include <stdio.h>
#define S(s) (str){s, sizeof(s)-1}
typedef struct {
char *data;
ptrdiff_t len;
} str;
static str span(char *beg, char *end)
{
str r = {0};
r.data = beg;
r.len = beg ? end - beg : 0;
return r;
}
typedef enum { TOK_EOF, TOK_DATA, TOK_OR, TOK_AND } tok;
typedef struct {
str token;
str input;
tok type;
} result;
static result parse(str input)
{
result r = {0};
if (!input.len) {
return r;
}
r.type = TOK_DATA;
char *beg = input.data;
char *cut = beg;
char *end = input.data + input.len;
for (int ands = 0; cut < end; cut++) {
switch (*cut) {
case '|': if (cut == beg) {
r.type = TOK_OR;
cut++; // consume |
}
goto done;
case '&': switch (ands) {
case 0: ands = 1;
break;
case 1: cut--; // back off to first &
if (cut == beg) {
r.type = TOK_AND;
cut += 2; // consume &&
}
goto done;
}
break;
default : ands = 0;
}
}
done:
r.token = span(beg, cut);
r.input = span(cut, end);
return r;
}
int main(void)
{
result r = {0};
r.input = S("Hello, I am | a && human");
for (;;) {
r = parse(r.input);
if (r.type == TOK_EOF) break;
printf("%-4s = \"%.*s\"\n",
(char *[]){"EOF", "DATA", "OR", "AND"}[r.type],
(int)r.token.len, r.token.data);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment