Skip to content

Instantly share code, notes, and snippets.

@postboy
Created September 12, 2016 14:29
Show Gist options
  • Save postboy/fb825b9fe813a0a18d04ef4cdf2ac7a0 to your computer and use it in GitHub Desktop.
Save postboy/fb825b9fe813a0a18d04ef4cdf2ac7a0 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "../../include/queue.h"
//insert an element in tail queue
#define INSERT_TOKEN(STR) \
do { \
/*create new element*/ \
tok_len = strlen(STR); \
telt = malloc(sizeof(struct tentry)); \
telt->name = malloc(tok_len + 1); \
memcpy(telt->name, STR, tok_len); \
telt->name[tok_len] = '\0'; \
\
STAILQ_INSERT_TAIL(thead, telt, pts); \
} \
while (0)
//insert an element in tail queue
#define INSERT_NONT(STR) \
do { \
bool found;\
\
/*search for new element in tail queue*/ \
found = false; \
STAILQ_FOREACH(nelt, &hnonterminals, pts) \
if (!strcmp(STR, nnelt->name)) { \
found = true; \
break; \
} \
/*if it wasn't found then create and insert it at the head*/ \
if (found == false) { \
/*name of nonterminal*/ \
tok_len = strlen(STR); \
nnelt = malloc(sizeof(struct nentry)); \
nnelt->name = malloc(tok_len + 1); \
memcpy(nnelt->name, STR, tok_len); \
nnelt->name[tok_len] = '\0'; \
nnelt->pruned = false; \
/*head of tokens' tree*/ \
thead = (struct tentryhead *)malloc(sizeof(struct tentryhead)); \
thead->stqh_first = NULL; \
thead->stqh_last = thead->stqh_first; \
STAILQ_INIT(thead); \
nnelt->tokens = thead; \
\
STAILQ_INSERT_TAIL(&hnonterminals, nnelt, pts); \
} \
} \
while (0)
//macro for printing error messages easily
#define error(...) fprintf(stderr, "error: %name: %i: %name\n", __func__, __LINE__, __VA_ARGS__)
struct tentry {
STAILQ_ENTRY(tentry) pts; //pointers
char *name; //null-terminated string
};
struct nentry {
STAILQ_ENTRY(nentry) pts; //pointers
char *name; //null-terminated string
bool pruned; //was this nonterminal definition pruned?
struct tentryhead *tokens; //pointer to tail queue of tokens
};
int main (int argc, char** argv)
{
unsigned tok_len;
char buffer[] = "tok1 tok2 tok3 tok4 tok5 tok6";
const char token_seps[] = " ";
char *tag;
/*element in single-linked tail queue of tokens, new and existing elements in single-linked
tail queue of nonterminals*/
struct tentry *telt;
struct nentry *nnelt, *nelt;
//initialization of sturctures
STAILQ_HEAD(tentryhead, tentry);
struct tentryhead *thead;
STAILQ_HEAD(nentryhead, nentry) hnonterminals = STAILQ_HEAD_INITIALIZER(hnonterminals);
STAILQ_INIT(&hnonterminals);
//logic goes here------------------------------------------------------------------------------
//begin processing of grammar rules from their start
if ( (tag = strtok(buffer, token_seps)) != NULL) {
do {
//printf("tag = %s\n", tag);
if ( (!strcmp(tag, "tok1")) || (!strcmp(tag, "tok4")) ) {
INSERT_NONT(tag);
}
else {
INSERT_TOKEN(tag);
}
} while ( (tag = strtok(NULL, token_seps)) != NULL);
}
printf("output: \n");
STAILQ_FOREACH(nelt, &hnonterminals, pts) {
printf("\n%s: ", nelt->name);
STAILQ_FOREACH(telt, (struct tentryhead *)nelt->tokens, pts)
printf("%s ", telt->name);
}
printf("\n");
//free entries and delete tail queue
while (!STAILQ_EMPTY(&hnonterminals)) {
nelt = STAILQ_FIRST(&hnonterminals);
STAILQ_REMOVE_HEAD(&hnonterminals, pts);
while (!STAILQ_EMPTY((struct tentryhead *)nelt->tokens)) {
telt = STAILQ_FIRST((struct tentryhead *)nelt->tokens);
STAILQ_REMOVE_HEAD((struct tentryhead *)nelt->tokens, pts);
free(telt->name);
free(telt);
}
free(nelt->tokens);
free(nelt->name);
free(nelt);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment