first working version with minimal syntax (check test.nhtml)
This commit is contained in:
parent
7a9a3ca64a
commit
a4674d7eee
8
Makefile
8
Makefile
@ -1,8 +1,10 @@
|
||||
OBJ:= main.o
|
||||
OBJ:= html.o main.o
|
||||
OUTPUT:=nhtmlc
|
||||
|
||||
debug: CXXFLAGS = -g
|
||||
debug: CFLAGS = -g
|
||||
all: debug
|
||||
|
||||
debug: CXXFLAGS = -g -DDEBUG
|
||||
debug: CFLAGS = -g -DDEBUG
|
||||
debug: $(OBJ)
|
||||
gcc $(OBJ) -g -o $(OUTPUT)
|
||||
|
||||
|
210
main.c
210
main.c
@ -2,6 +2,12 @@
|
||||
#include <stdlib.h> // needs: realloc, malloc, free
|
||||
#include <string.h> // needs: strcmp, memcpy
|
||||
#include <errno.h>
|
||||
#include <ctype.h> // needs: isspace
|
||||
|
||||
#include <getopt.h> // needs: getopt_long
|
||||
|
||||
#include "html.h" // needs: html_escaped
|
||||
|
||||
typedef struct {
|
||||
char * c_str;
|
||||
size_t len;
|
||||
@ -23,6 +29,7 @@ int string_append(string_t *str, char c) {
|
||||
str->c_str[str->len-1] = c;
|
||||
str->c_str[str->len] = 0; // make sure
|
||||
str->len++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void string_destroy(string_t s) {
|
||||
@ -62,6 +69,8 @@ attr_t * attr_set_find(attr_set_t *set, const char * name) {
|
||||
|
||||
// Append new Attribute to set
|
||||
int attr_set_append(attr_set_t * set, attr_t *new_entry) {
|
||||
if (new_entry->name.c_str== NULL) return -1; // reject empty entries
|
||||
|
||||
// search first
|
||||
attr_t * new_ptr = attr_set_find(set, new_entry->name.c_str);
|
||||
if (new_ptr != NULL) {
|
||||
@ -84,15 +93,90 @@ int attr_set_append(attr_set_t * set, attr_t *new_entry) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void attr_reset(attr_t * attr) {
|
||||
memset(attr, 0, sizeof(attr_t));
|
||||
}
|
||||
|
||||
int strip(FILE * stream) {
|
||||
int current = 0;
|
||||
while((current = fgetc(stream)) != EOF) {
|
||||
if (!isspace(current))
|
||||
break;
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
int parse_attr(FILE * stream, attr_set_t * output) {
|
||||
fprintf(stderr, "stub: parse_attr\n");
|
||||
return 0;
|
||||
attr_t current_attr = {};
|
||||
#ifdef DEBUG
|
||||
printf("parse_attr\n");
|
||||
#endif
|
||||
int buffer = 0;
|
||||
unsigned char isKey = 1;
|
||||
|
||||
while((buffer = fgetc(stream)) != EOF) {
|
||||
// parse key=value pairs
|
||||
// check for delim
|
||||
//if (buffer == ' ' || buffer == '\t' || buffer == '\n'){
|
||||
if (isspace(buffer)) {
|
||||
attr_set_append(output, ¤t_attr);
|
||||
#ifdef DEBUG
|
||||
printf("parsed attr: %s=%s\n", current_attr.name.c_str, current_attr.value);
|
||||
#endif
|
||||
// reset attribute
|
||||
attr_reset(¤t_attr);
|
||||
isKey = 1;
|
||||
continue;
|
||||
}
|
||||
if (buffer == '=') {
|
||||
isKey = 0;
|
||||
continue;
|
||||
} else
|
||||
if (buffer == ']') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (isKey) {
|
||||
string_append(¤t_attr.name, buffer);
|
||||
} else {
|
||||
string_append(¤t_attr.value, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// append last attribute
|
||||
attr_set_append(output, ¤t_attr);
|
||||
|
||||
//memset(output, 0, sizeof(attr_set_t));
|
||||
return strip(stream);
|
||||
}
|
||||
|
||||
int parse_text(FILE * stream, FILE * output) {
|
||||
// STUB
|
||||
fprintf(stderr, "stub: parse_text\n");
|
||||
return 0;
|
||||
#ifdef DEBUG
|
||||
printf("parse text\n");
|
||||
#endif
|
||||
int buffer = 0;
|
||||
char escaped = 0;
|
||||
|
||||
while((buffer = fgetc(stream)) != EOF) {
|
||||
if (!escaped && buffer == '\\') {
|
||||
escaped = 1;
|
||||
continue;
|
||||
}
|
||||
if (!escaped && buffer == '"') {
|
||||
break;
|
||||
}
|
||||
escaped = 0;
|
||||
|
||||
if (html_escape(buffer, output)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fputc(buffer, output);
|
||||
}
|
||||
|
||||
//fprintf(stderr, "stub: parse_text\n");
|
||||
return strip(stream);
|
||||
}
|
||||
|
||||
typedef struct node {
|
||||
@ -102,7 +186,10 @@ typedef struct node {
|
||||
|
||||
|
||||
// write out node
|
||||
void print_node(node_t * node, FILE * output) {
|
||||
void open_node(node_t * node, FILE * output) {
|
||||
// check for empty node (text mostly)
|
||||
if (!node->name.c_str) return;
|
||||
|
||||
// start by writing tag
|
||||
fputc('<', output);
|
||||
|
||||
@ -113,43 +200,99 @@ void print_node(node_t * node, FILE * output) {
|
||||
size_t i = 0;
|
||||
attr_t * current = node->attributes.arr;
|
||||
for (; i < node->attributes.len; i++,current++) {
|
||||
if (current->value.c_str)
|
||||
fprintf(output, " %s=\"%s\"", current->name.c_str, current->value.c_str);
|
||||
else {
|
||||
fputc(' ', output);
|
||||
fputs(current->name.c_str, output);
|
||||
}
|
||||
}
|
||||
|
||||
// close tag
|
||||
fputc('>', output);
|
||||
}
|
||||
|
||||
int print_tag(FILE * stream, FILE * output) {
|
||||
node_t new_node;
|
||||
int buffer = 0;
|
||||
|
||||
while ((buffer = fgetc(stream)) != EOF) {
|
||||
switch(buffer) {
|
||||
case '[': // parse attributes
|
||||
if (parse_attr(stream, &new_node.attributes) != -1) {
|
||||
fprintf(stderr, "could not parse attributes: %d", -1);
|
||||
return -1;
|
||||
void close_node(node_t * node, FILE * output) {
|
||||
if (node->name.c_str) {
|
||||
fprintf(output, "</%s>", node->name.c_str);
|
||||
}
|
||||
}
|
||||
|
||||
int readName(FILE *stream, node_t *node) {
|
||||
int current = strip(stream);
|
||||
if (current == EOF) {
|
||||
return current;
|
||||
}
|
||||
|
||||
do {
|
||||
if (current == '{' || current == '[') {
|
||||
break;
|
||||
case '"':
|
||||
// raw text
|
||||
parse_text(stream, output);
|
||||
}
|
||||
|
||||
if (current == ' ' || current == '\t' || current == '\n') {
|
||||
current = strip(stream);
|
||||
break;
|
||||
default:
|
||||
if (buffer != ' ' && buffer != '\t' && buffer != '\n') {
|
||||
string_append(&new_node.name, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string_append(&node->name, current);
|
||||
} while((current = fgetc(stream)) != EOF);
|
||||
|
||||
return 0;
|
||||
return current;
|
||||
}
|
||||
|
||||
|
||||
enum node_type {
|
||||
NODE_SELFCLOSING,
|
||||
NODE_TEXT,
|
||||
NODE_TAG
|
||||
};
|
||||
|
||||
int parse_node(int current, FILE * stream, FILE * output) {
|
||||
if (current == '"') {
|
||||
return parse_text(stream, output);
|
||||
}
|
||||
|
||||
// normal node
|
||||
node_t current_node = {};
|
||||
string_append(¤t_node.name, current);
|
||||
current = readName(stream, ¤t_node);
|
||||
if (current == EOF) {
|
||||
goto done;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("parse_node: %s\n", current_node.name.c_str);
|
||||
#endif
|
||||
if (current == '[') {
|
||||
current = parse_attr(stream, ¤t_node.attributes);
|
||||
}
|
||||
|
||||
if (current != '{') {
|
||||
// tag is selfclosing
|
||||
open_node(¤t_node, output);
|
||||
return current;
|
||||
}
|
||||
current = strip(stream);
|
||||
|
||||
open_node(¤t_node, output);
|
||||
while(current != '}' && current != EOF) {
|
||||
current = parse_node(current, stream, output);
|
||||
}
|
||||
|
||||
close_node(¤t_node, output);
|
||||
done:
|
||||
return strip(stream);
|
||||
}
|
||||
|
||||
int main(int argc, char ** args) {
|
||||
//getopt_long(argc, args, NULL, NULL, NULL);
|
||||
|
||||
char * filename= NULL;
|
||||
for(;argc != 1; --argc) {
|
||||
FILE * output = fopen("a.html", "w");
|
||||
if (output == NULL) {
|
||||
fprintf(stderr, "could not create output file\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(;argc > 1; --argc) {
|
||||
filename = args[argc-1];
|
||||
printf("starting conversion of %s\n", filename);
|
||||
|
||||
@ -160,16 +303,19 @@ int main(int argc, char ** args) {
|
||||
continue;
|
||||
}
|
||||
|
||||
while(!feof(handle)) {
|
||||
if (print_tag(handle, stdout) != 0) {
|
||||
fprintf(stderr, "error during parsing of node\n");
|
||||
break;
|
||||
}
|
||||
int current = strip(handle);
|
||||
|
||||
while((current = parse_node(current, handle, output)) != EOF) {
|
||||
// if () {
|
||||
// fprintf(stderr, "error during parsing of node\n");
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
|
||||
fclose(handle);
|
||||
}
|
||||
|
||||
fclose(output);
|
||||
printf("done compiling\n");
|
||||
return 0;
|
||||
}
|
||||
|
36
test.nhtml
36
test.nhtml
@ -1,12 +1,28 @@
|
||||
div {
|
||||
"hi i'm raw text"
|
||||
"I'm raw text too :)"
|
||||
"Including \"escaping\""
|
||||
}
|
||||
h1 {
|
||||
div {
|
||||
"Another, but bigger font"
|
||||
"Adding a
|
||||
new line adds a <br/> :)"
|
||||
!DOCTYPE[html]
|
||||
head {
|
||||
title { "was geht" }
|
||||
meta[charset=utf-8]
|
||||
}
|
||||
body {
|
||||
h1 { "Alle Meine Endchen schwimmen auf dem See" }
|
||||
p {
|
||||
"Alle meine Entchen schwimmen auf dem See,
|
||||
schwimmen auf dem See,
|
||||
Köpfchen in das Wasser, Schwänzchen in die Höh'."
|
||||
}
|
||||
p {
|
||||
"Alle meine Täubchen gurren auf dem Dach,
|
||||
gurren auf dem Dach,
|
||||
eins fliegt in die Lüfte, fliegen alle nach."
|
||||
}
|
||||
p {
|
||||
"Alle meine Hühner scharren in dem Stroh,
|
||||
scharren in dem Stroh,
|
||||
finden sie ein Körnchen, sind sie alle froh."
|
||||
}
|
||||
p {
|
||||
"Alle meine Gänschen watscheln durch den Grund,
|
||||
watscheln durch den Grund,
|
||||
suchen in dem Tümpel, werden kugelrund."
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user