Skip to content

Instantly share code, notes, and snippets.

@benthepoet
Created March 27, 2019 13:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benthepoet/0048c73e63ae48c3c20609c35f484ee0 to your computer and use it in GitHub Desktop.
Save benthepoet/0048c73e63ae48c3c20609c35f484ee0 to your computer and use it in GitHub Desktop.
Recursive S-expression parsing
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sprite.h"
#define GAME_FILE "config/game.lisp"
enum NodeType {
LIST = 0,
SYMBOL = 1
};
struct Node {
enum NodeType type;
struct Node *next;
union {
struct Node *list;
char *symbol;
};
};
void free_node(struct Node *node);
struct Node *parse_expr(FILE *fp, struct Node *head, struct Node *tail);
int main(int argc, char *argv[]) {
FILE *fp;
fp = fopen(GAME_FILE, "r");
struct Node *root = parse_expr(fp, NULL, NULL);
fclose(fp);
free_node(root);
return 0;
}
void free_node(struct Node *node) {
struct Node *tmp;
while (node != NULL) {
tmp = node;
if (node->type == SYMBOL) {
free(node->symbol);
node->symbol = NULL;
}
if (node->type == LIST) {
free_node(node->list);
}
node = node->next;
free(tmp);
tmp = NULL;
}
}
struct Node *parse_expr(FILE *fp, struct Node *head, struct Node *tail) {
struct Node *node;
int c;
char buffer[32];
while ((c = fgetc(fp)) != EOF) {
if (c == '(') {
node = calloc(1, sizeof(struct Node));
node->type = LIST;
node->list = parse_expr(fp, NULL, NULL);
if (head == NULL) {
return parse_expr(fp, node, node);
} else {
tail->next = node;
return parse_expr(fp, head, node);
}
}
else if (c == ')') {
break;
}
else if (!isspace(c)) {
ungetc(c, fp);
if (c == '"') {
fscanf(fp, "\"%31[^\"]\"", buffer);
} else {
fscanf(fp, "%31[^() \t\n\v\f\r]", buffer);
}
node = calloc(1, sizeof(struct Node));
node->type = SYMBOL;
node->symbol = calloc(strlen(buffer), sizeof(char));
strcpy(node->symbol, buffer);
if (head == NULL) {
return parse_expr(fp, node, node);
} else {
tail->next = node;
return parse_expr(fp, head, node);
}
}
}
return head;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment