mirror of
https://github.com/sigmasternchen/libparcival
synced 2025-03-15 11:58:53 +00:00
now generating tree for template
This commit is contained in:
parent
3519c014e8
commit
e01841c1eb
6 changed files with 313 additions and 16 deletions
24
src/common.c
Normal file
24
src/common.c
Normal 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
7
src/common.h
Normal 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
|
90
src/parser.y
90
src/parser.y
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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
137
src/tree.c
Normal 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
44
src/tree.h
Normal 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
|
Loading…
Reference in a new issue