aoc-2023/c/include/parse.c

92 lines
2.1 KiB
C

/* This parsing library aims to imitate how Elm parses strings.
In contrast to Elm, however, this function makes use of the side-effects that
C brings, allowing for impurity and a lack of need to return values.
Instead, every parser merely returns a boolean that expresses whether it had
parsed successfully.
*/
#include <parse.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const bool DEBUG = false;
/* Parse a single char and fetch the result.
*/
bool parse_char(char *text, int *cursor, char *c) {
int length = strlen(text);
if (DEBUG) printf("Parsing a char : ");
if (*cursor == length) {
if (DEBUG) printf("Reached end of string [FAIL]\n");
return false;
}
*c = text[*cursor];
*cursor = *cursor + 1;
if (DEBUG) printf("%c [Success]\n", *c);
return true;
}
/* Parse an integer.
*/
bool parse_int(char *text, int *cursor, int *output) {
int is_negative = parse_token(text, cursor, "-");
if (DEBUG) printf("Parsing int : ");
int answer = 0;
char c = text[*cursor];
if (c < '0' || c > '9') {
if (DEBUG) printf("%c [FAIL]\n", c);
return false;
}
do
{
if (DEBUG) printf("%c", c);
answer = (answer * 10) + (c - '0');
*cursor = *cursor + 1;
c = text[*cursor];
}
while (c >= '0' && c <= '9');
if (DEBUG) printf(" [Success ]\n");
if (is_negative) {
answer = -1 * answer;
}
*output = answer;
return true;
}
/* Parse a token of text.
*/
bool parse_token(char *text, int *cursor, char *token) {
int length = strlen(token), text_length = strlen(text);
if (DEBUG) printf("Parsing token \"%s\" : ", token);
if (text_length - *cursor < length) {
if (DEBUG) printf("Token too long, won't fit. [FAIL]\n");
return false;
}
for (int i = 0; i < length; i++) {
if (DEBUG) printf("%c", text[*cursor + i]);
if (text[*cursor + i] != token[i]) {
if (DEBUG) printf(" [FAIL]\n");
*cursor = *cursor + i;
return false;
}
}
if (DEBUG) printf(" [Success]\n");
*cursor = *cursor + length;
return true;
}