now generating tree for template

This commit is contained in:
overflowerror 2021-05-20 19:42:42 +02:00
parent 3519c014e8
commit e01841c1eb
6 changed files with 313 additions and 16 deletions

24
src/common.c Normal file
View file

@ -0,0 +1,24 @@
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include "common.h"
void _panic(const char* function, const char* format, ...) {
fprintf(stderr, "panic: %s: ", function);
va_list argptr;
va_start(argptr, format);
vfprintf(stderr, format, argptr);
va_end(argptr);
if (errno != 0) {
fprintf(stderr, ": %s", strerror(errno));
}
fprintf(stderr, "\n");
}

7
src/common.h Normal file
View file

@ -0,0 +1,7 @@
#ifndef COMMON_H
#define COMMON_H
void _panic(const char* f, const char* format, ...);
#define panic(...) _panic(__func__, __VA_ARGS__)
#endif

View file

@ -1,13 +1,38 @@
%{ %{
#include <stdlib.h>
#include <string.h>
#include <tree.h>
int yylex(); int yylex();
extern void yyerror(char*); extern void yyerror(char*);
%} %}
%token SECTION TEXT COMMA END %union {
struct tree tree;
struct params params;
char* text;
}
%type <tree> mainSection
%type <params> parameter
%type <params> parameters
%type <params> moreParameters
%type <text> statementHeader
%type <text> blockStatement
%type <text> statement
%type <text> output
%type <text> texts
%token <text> TEXT
%token SECTION COMMA END
%token PARAMS_BEGIN PARAMS_END %token PARAMS_BEGIN PARAMS_END
%token STATEMENT_BEGIN STATEMENT_END %token STATEMENT_BEGIN STATEMENT_END
%token OUTPUT_BEGIN OUTPUT_END %token OUTPUT_BEGIN OUTPUT_END
@ -25,33 +50,88 @@ metaSection: /* empty */
; ;
parameters: /* empty */ parameters: /* empty */
{
$$ = newParams();
}
| parameter moreParameters | parameter moreParameters
{
$$ = combineParams($1, $2);
}
; ;
parameter: TEXT texts parameter: TEXT TEXT
{
$$ = newParams();
addParam(&$$, $1, $2);
}
; ;
moreParameters: /* empty */ moreParameters: /* empty */
{
$$ = newParams();
}
| COMMA parameter moreParameters | COMMA parameter moreParameters
{
$$ = combineParams($2, $3);
}
; ;
metaStatement: statement metaStatement: statement
; ;
mainSection: /* empty */ mainSection: /* empty */
| TEXT mainSection {
| STATEMENT_BEGIN blockStatement STATEMENT_END mainSection $$ = newTree();
| OUTPUT_BEGIN output OUTPUT_END mainSection }
| mainSection TEXT
{
$$ = $1;
addNode(&$$, newTextNode($2));
}
| mainSection statementHeader mainSection statementEnd
{
$$ = $1;
addNode(&$$, newStatementNode($2, $3));
}
| mainSection OUTPUT_BEGIN output OUTPUT_END
{
$$ = $1;
addNode(&$$, newOutputNode($3));
}
;
statementHeader: STATEMENT_BEGIN blockStatement STATEMENT_END
{
$$ = $2;
}
;
statementEnd: STATEMENT_BEGIN END STATEMENT_END
; ;
blockStatement: statement blockStatement: statement
{
$$ = $1;
}
; ;
statement: TEXT texts statement: TEXT texts
{
$$ = combineStr($1, $2);
}
; ;
output: TEXT texts output: TEXT texts
{
$$ = combineStr($1, $2);
}
; ;
texts: /* empty */ texts: /* empty */
{
$$ = strdup("");
}
| TEXT texts | TEXT texts
{
$$ = combineStr($1, $2);
}

View file

@ -3,7 +3,7 @@ whitespace [\n\t\r ]
params_begin "{$" params_begin "{$"
params_end "$}" params_end "$}"
section "%%" section "%%"[\t ]*\n
statement_begin "{%" statement_begin "{%"
statement_end "%}" statement_end "%}"
@ -14,10 +14,12 @@ output_end "}}"
block_end_token "end" block_end_token "end"
block_end {whitespace}*{block_end_token}{whitespace}* block_end {whitespace}*{block_end_token}{whitespace}*
id [a-zA-Z_][a-zA-Z0-9_]*
type_prefixes "enum"|"struct" type_prefixes "enum"|"struct"
type_prefix {type_prefixes}{whitespace}+ type_prefix {type_prefixes}{whitespace}+
type_pointer {whitespace}*"*" type_pointer {whitespace}*"*"
type {type_prefix}?[a-zA-Z0-9_]+{type_pointer}? type {type_prefix}?{id}{type_pointer}?
%option noyywrap %option noyywrap
%option nounput %option nounput
@ -37,6 +39,9 @@ type {type_prefix}?[a-zA-Z0-9_]+{type_pointer}?
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <tree.h>
#include "y.tab.h" #include "y.tab.h"
@ -50,25 +55,25 @@ type {type_prefix}?[a-zA-Z0-9_]+{type_pointer}?
<INITIAL,META_SECTION>{whitespace}+ { /* ignore whitespaces */ } <INITIAL,META_SECTION>{whitespace}+ { /* ignore whitespaces */ }
<INITIAL,META_SECTION>. { fprintf(stderr, "error: raw text not allowed in meta section (line %d)\n", yylineno); exit(1); } <INITIAL,META_SECTION>. { fprintf(stderr, "error: raw text not allowed in meta section (line %d)\n", yylineno); exit(1); }
<PARAMS>{type} { return TEXT; } <PARAMS>{type} { yylval.text = strdup(yytext); return TEXT; }
<PARAMS>{id} { yylval.text = strdup(yytext); return TEXT; }
<PARAMS>{params_end} { BEGIN(META_SECTION); return PARAMS_END; } <PARAMS>{params_end} { BEGIN(META_SECTION); return PARAMS_END; }
<PARAMS>"," { return COMMA; } <PARAMS>"," { return COMMA; }
<PARAMS>{whitespace}+ { /* ignore whitespaces */ } <PARAMS>{whitespace}+ { /* ignore whitespaces */ }
<PARAMS>"$" { return TEXT; /* catch $ as text */ }
<PARAMS>. { fprintf(stderr, "error: illegal token '%s' in parameter block (line %d)\n", yytext, yylineno); exit(1); } <PARAMS>. { fprintf(stderr, "error: illegal token '%s' in parameter block (line %d)\n", yytext, yylineno); exit(1); }
<STATEMENT>[^%e]+ { return TEXT; } <STATEMENT>[^%e]+ { yylval.text = strdup(yytext); return TEXT; }
<STATEMENT>{block_end} { return END; } <STATEMENT>{block_end} { return END; }
<STATEMENT>"%" { return TEXT; /* catch % as text */ } <STATEMENT>"%" { yylval.text = strdup(yytext); return TEXT; /* catch % as text */ }
<STATEMENT>"e" { return TEXT; /* catch e as text */ } <STATEMENT>"e" { yylval.text = strdup(yytext); return TEXT; /* catch e as text */ }
<STATEMENT>{statement_end} { if (isMetaSection) BEGIN(META_SECTION); else BEGIN(MAIN_SECTION); return STATEMENT_END; } <STATEMENT>{statement_end} { if (isMetaSection) BEGIN(META_SECTION); else BEGIN(MAIN_SECTION); return STATEMENT_END; }
<MAIN_SECTION>{params_begin} { fprintf(stderr, "warning: parameter block not allowed in main section (line %d); assuming to be text\n", yylineno); return TEXT; } <MAIN_SECTION>{params_begin} { fprintf(stderr, "warning: parameter block not allowed in main section (line %d); assuming to be text\n", yylineno); yylval.text = strdup(yytext); return TEXT; }
<MAIN_SECTION>{statement_begin} { BEGIN(STATEMENT); return STATEMENT_BEGIN; } <MAIN_SECTION>{statement_begin} { BEGIN(STATEMENT); return STATEMENT_BEGIN; }
<MAIN_SECTION>{output_begin} { BEGIN(OUTPUT); return OUTPUT_BEGIN; } <MAIN_SECTION>{output_begin} { BEGIN(OUTPUT); return OUTPUT_BEGIN; }
<MAIN_SECTION>. { return TEXT; } <MAIN_SECTION>. { yylval.text = strdup(yytext); return TEXT; }
<OUTPUT>[^}]+ { return TEXT; } <OUTPUT>[^}]+ { yylval.text = strdup(yytext); return TEXT; }
<OUTPUT>{output_end} { BEGIN(MAIN_SECTION); return OUTPUT_END; } <OUTPUT>{output_end} { BEGIN(MAIN_SECTION); return OUTPUT_END; }
<OUTPUT>"}" { return TEXT; /* catch } as text */ } <OUTPUT>"}" { yylval.text = strdup(yytext); return TEXT; /* catch } as text */ }

137
src/tree.c Normal file
View file

@ -0,0 +1,137 @@
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "tree.h"
char* combineStr(char* s1, char* s2) {
if (s1 == NULL || s2 == NULL) {
panic("argument is NULL");
}
char* s3 = malloc(strlen(s1) + strlen(s2) + 1);
strcpy(s3, s1);
strcat(s3, s2);
free(s1);
free(s2);
return s3;
}
struct node newTextNode(char* text) {
return (struct node) {
.type = TEXT_NODE,
.value.text = text
};
}
struct node newStatementNode(char* stm, struct tree tree) {
struct tree* _tree = malloc(sizeof(struct tree));
if (_tree == NULL) {
panic("malloc");
}
memcpy(_tree, &tree, sizeof(struct tree));
return (struct node) {
.type = STATEMENT_NODE,
.statement = stm,
.value.tree = _tree
};
}
struct node newOutputNode(char* text) {
return (struct node) {
.type = OUTPUT_NODE,
.value.text = text
};
}
struct tree newTree() {
return (struct tree) {
.kids = NULL,
.kidsno = 0
};
}
void addNode(struct tree* tree, struct node node) {
void* tmp = realloc(tree->kids, (sizeof (struct node)) * (tree->kidsno + 1));
if (tmp == NULL) {
panic("realloc");
}
tree->kids = tmp;
tree->kids[tree->kidsno++] = node;
}
struct tree combineTree(struct tree t1, struct tree t2) {
struct tree t = {
.kidsno = t1.kidsno + t2.kidsno
};
t.kids = malloc(sizeof(struct node) * t.kidsno);
if (t.kids == NULL) {
panic("malloc");
}
if (t1.kids != NULL) {
memcpy(t.kids, t1.kids, t1.kidsno * sizeof(struct node));
free(t1.kids);
}
if (t2.kids != NULL) {
memcpy(t.kids + t1.kidsno, t2.kids, t2.kidsno * sizeof(struct node));
free(t2.kids);
}
return t;
}
struct params newParams() {
return (struct params) {
.types = NULL,
.names = NULL,
.no = 0
};
}
void addParam(struct params* params, char* type, char* name) {
void* tmp;
tmp = realloc(params->types, sizeof(char*) * (params->no + 1));
if (tmp == NULL) {
panic("realloc");
}
params->types = tmp;
tmp = realloc(params->names, sizeof(char*) * (params->no + 1));
if (tmp == NULL) {
panic("realloc");
}
params->names = tmp;
params->types[params->no] = type;
params->names[params->no] = name;
params->no++;
}
struct params combineParams(struct params p1, struct params p2) {
struct params p = {
.no = p1.no + p2.no
};
p.types = malloc(sizeof(char*) * p.no);
if (p.types == NULL) {
panic("malloc");
}
p.names = malloc(sizeof(char*) * p.no);
if (p.names == NULL) {
panic("malloc");
}
memcpy(p.types, p1.types, p1.no * sizeof(char*));
memcpy(p.types + p1.no, p2.types, p2.no * sizeof(char*));
memcpy(p.names, p1.names, p1.no * sizeof(char*));
memcpy(p.names + p1.no, p2.names, p2.no * sizeof(char*));
return p;
}

44
src/tree.h Normal file
View file

@ -0,0 +1,44 @@
#ifndef TREE_H_
#define TREE_H_
char* combineStr(char*, char*);
#define TEXT_NODE (0)
#define STATEMENT_NODE (1)
#define OUTPUT_NODE (2)
struct node {
int type;
char* statement;
union {
struct tree* tree;
char* text;
} value;
};
struct tree {
struct node* kids;
size_t kidsno;
};
struct node newTextNode(char*);
struct node newStatementNode(char*, struct tree);
struct node newOutputNode(char*);
struct tree newTree();
void addNode(struct tree*, struct node);
struct tree combineTree(struct tree, struct tree);
struct params {
char** types;
char** names;
size_t no;
};
struct params newParams();
void addParam(struct params*, char*, char*);
struct params combineParams(struct params, struct params);
#endif