readme-thing/node.c

242 lines
5.4 KiB
C

#include <stdio.h>
#include <string.h>
#include "node.h"
#define STRING_BUFF_SIZE 1024
static char stringBuff[STRING_BUFF_SIZE];
Node* parseHeader(TokenList** list);
Node* parseCodeBlock(TokenList** list);
Node*
ParseNodes(TokenList* list)
{
printf("ParseNodes() start\n");
Node* first = NULL;
TokenList* currentToken = list;
Node* prevNode = NULL;
printf("ParseNodes() loop\n");
while (1) {
Node* currentNode = NULL;
switch (currentToken->token->type) {
case TT_NEWLINE:
break;
case TT_HASH:
// start of header
currentNode = parseHeader(&currentToken);
break;
case TT_TRIPLEBACKTICK:
currentNode = parseCodeBlock(&currentToken);
break;
case TT_EOF:
printf("EOF found\n");
return first;
default: // paragraph start?
break;
}
if (currentToken->next == NULL) {
printf("currentToken->next == NULL\n");
break;
}
currentToken = currentToken->next;
if (currentNode == NULL)
continue;
if (prevNode != NULL) {
prevNode->next = currentNode;
}
if (first == NULL) {
first = currentNode;
}
prevNode = currentNode;
}
return first;
}
Node*
parseHeader(TokenList** list)
{
TokenList* l = *list;
// Count the number of TT_HASH tokens
int count = 1;
while (l->next != NULL && l->next->token->type == TT_HASH)
{
count++;
l = l->next;
}
if (l->next == NULL)
{
printf("Header missing text");
return NULL;
}
l = l->next;
// Trim leading whitespace
while (l->next != NULL && l->token->type == TT_WHITESPACE)
{
l = l->next;
}
if (l->next == NULL)
{
printf("Header missing text");
return NULL;
}
TokenList* end = l;
int len = 0;
// find header text size
while (end->token->type != TT_NEWLINE && end->token->type != TT_EOF) {
len += end->token->length;
end = end->next;
}
char* strbuff = malloc(len+1);
strbuff[0] = '\0';
while(l != end) {
strncat(strbuff, l->token->literal, l->token->length);
l = l->next;
}
*list = l;
printf("header hash count: %d\ntext: '%s'\n", count, stringBuff);
HeaderNode* retval = malloc(sizeof(HeaderNode));
switch(count) {
case 1:
retval->type = NT_Header1;
break;
case 2:
retval->type = NT_Header2;
break;
case 3:
retval->type = NT_Header3;
break;
default:
retval->type = NT_Header4;
break;
}
retval->next = NULL;
retval->rawText = strbuff;
return (Node*)retval;
}
Node*
parseCodeBlock(TokenList** list)
{
TokenList* l = *list;
// find closing ticks
int tlen = 0; // number of tokens
int clen = 0; // number of characters
l = l->next; // skip past the opening triple backtick
// skip the first newline
if (l->token->type == TT_NEWLINE) {
l = l->next;
}
while (l->next != NULL && l->next->token->type != TT_TRIPLEBACKTICK) {
if (l->next->token->type == TT_EOF) {
printf("premature EOF");
ErrorNode* err = malloc(sizeof(ErrorNode));
err->type = NT_Error;
err->next = NULL;
err->error = "premature EOF searching for closing triple backtick";
return (Node*)err;
}
tlen++;
clen += l->token->length;
l = l->next;
}
l = *list;
printf("codeblock token length: %d\n", tlen);
printf("codeblock char length: %d\n", clen);
printf("malloc(%ld)\n", sizeof(char)*clen+1);
char* strbuff = malloc(sizeof(char)*clen+1);
strbuff[0] = '\0';
int i;
l = l->next; // skip past the opening triple backtick
// skip the first newline
if (l->token->type == TT_NEWLINE) {
l = l->next;
}
for(i = 0; i < tlen; i++) {
strncat(strbuff, l->token->literal, l->token->length);
l = l->next;
}
// skip past closing triple backtick
*list = l->next;
printf("malloc(%ld)\n", sizeof(CodeBlockNode));
CodeBlockNode* ret = malloc(sizeof(CodeBlockNode));
ret->type = NT_BlockCode;
ret->rawText = strbuff;
ret->next = NULL;
return (Node*)ret;
}
char*
NodeTypeString(NodeType t)
{
switch(t) {
case NT_Header1:
return "NT_Header1";
case NT_Header2:
return "NT_Header2";
case NT_Header3:
return "NT_Header3";
case NT_Header4:
return "NT_Header4";
case NT_Paragraph:
return "NT_Paragraph";
case NT_UnorderedList:
return "NT_UnorderedList";
case NT_OrderedList:
return "NT_OrderedList";
case NT_InlineCode:
return "NT_InlineCode";
case NT_BlockCode:
return "NT_BlockCode";
case NT_BlockQuote:
return "NT_BlockQuote";
case NT_Bold:
return "NT_Bold";
case NT_Underline:
return "NT_Underline";
case NT_Error:
return "NT_Error";
default:
snprintf(stringBuff, 1000, "unknown NodeType: %d", t);
return stringBuff;
}
}