readme-thing/node.c

243 lines
5.3 KiB
C

#include <stdio.h>
#include <string.h>
#include "node.h"
#define STRING_BUFF_SIZE 1024
static char stringBuff[STRING_BUFF_SIZE];
Node* parseHeader(Token** firstToken);
Node* parseCodeBlock(Token** firstToken);
Node*
ParseNodes(Token* firstToken)
{
printf("ParseNodes() start\n");
Node* firstNode = NULL;
Token* currentToken = firstToken;
Node* prevNode = NULL;
printf("ParseNodes() loop\n");
while (1) {
Node* currentNode = NULL;
switch (currentToken->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 firstNode;
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 (firstNode == NULL) {
firstNode = currentNode;
}
prevNode = currentNode;
}
return firstNode;
}
Node*
parseHeader(Token** startToken)
{
Token* t = *startToken;
// Count the number of TT_HASH tokens
int count = 1;
while (t->next != NULL && t->next->type == TT_HASH)
{
count++;
t = t->next;
}
if (t->next == NULL)
{
printf("Header missing text");
return NULL;
}
t = t->next;
// Trim leading whitespace
while (t->next != NULL && t->type == TT_WHITESPACE)
{
t = t->next;
}
if (t->next == NULL)
{
printf("Header missing text");
return NULL;
}
Token* end = t;
int len = 0;
// find header text size
while (end->type != TT_NEWLINE && end->type != TT_EOF) {
len += end->length;
end = end->next;
}
char* strbuff = malloc(len+1);
strbuff[0] = '\0';
while(t != end) {
strncat(strbuff, t->literal, t->length);
t = t->next;
}
*startToken = t;
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(Token** startToken)
{
// find closing ticks
int tlen = 0; // number of tokens
int clen = 0; // number of characters
Token* t = *startToken;
t = t->next; // skip past the opening triple backtick
// skip the first newline
if (t->type == TT_NEWLINE) {
t = t->next;
}
while (t->next != NULL && t->type != TT_TRIPLEBACKTICK) {
if (t->next->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 += t->length;
t = t->next;
}
t = *startToken;
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;
t = t->next; // skip past the opening triple backtick
// skip the first newline
if (t->type == TT_NEWLINE) {
t = t->next;
}
for(i = 0; i < tlen; i++) {
strncat(strbuff, t->literal, t->length);
t = t->next;
}
// skip past closing triple backtick
*startToken = t->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;
}
}