mirror of
https://github.com/sigmasternchen/libparcival
synced 2025-03-15 03:48:55 +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();
|
||||
|
||||
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 STATEMENT_BEGIN STATEMENT_END
|
||||
%token OUTPUT_BEGIN OUTPUT_END
|
||||
|
@ -25,33 +50,88 @@ metaSection: /* empty */
|
|||
;
|
||||
|
||||
parameters: /* empty */
|
||||
{
|
||||
$$ = newParams();
|
||||
}
|
||||
| parameter moreParameters
|
||||
{
|
||||
$$ = combineParams($1, $2);
|
||||
}
|
||||
;
|
||||
|
||||
parameter: TEXT texts
|
||||
parameter: TEXT TEXT
|
||||
{
|
||||
$$ = newParams();
|
||||
addParam(&$$, $1, $2);
|
||||
}
|
||||
;
|
||||
|
||||
moreParameters: /* empty */
|
||||
{
|
||||
$$ = newParams();
|
||||
}
|
||||
| COMMA parameter moreParameters
|
||||
{
|
||||
$$ = combineParams($2, $3);
|
||||
}
|
||||
;
|
||||
|
||||
metaStatement: statement
|
||||
;
|
||||
|
||||
mainSection: /* empty */
|
||||
| TEXT mainSection
|
||||
| STATEMENT_BEGIN blockStatement STATEMENT_END mainSection
|
||||
| OUTPUT_BEGIN output OUTPUT_END mainSection
|
||||
{
|
||||
$$ = newTree();
|
||||
}
|
||||
| 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
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
statement: TEXT texts
|
||||
{
|
||||
$$ = combineStr($1, $2);
|
||||
}
|
||||
;
|
||||
|
||||
output: TEXT texts
|
||||
{
|
||||
$$ = combineStr($1, $2);
|
||||
}
|
||||
;
|
||||
|
||||
texts: /* empty */
|
||||
{
|
||||
$$ = strdup("");
|
||||
}
|
||||
| TEXT texts
|
||||
{
|
||||
$$ = combineStr($1, $2);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ whitespace [\n\t\r ]
|
|||
params_begin "{$"
|
||||
params_end "$}"
|
||||
|
||||
section "%%"
|
||||
section "%%"[\t ]*\n
|
||||
|
||||
statement_begin "{%"
|
||||
statement_end "%}"
|
||||
|
@ -14,10 +14,12 @@ output_end "}}"
|
|||
block_end_token "end"
|
||||
block_end {whitespace}*{block_end_token}{whitespace}*
|
||||
|
||||
id [a-zA-Z_][a-zA-Z0-9_]*
|
||||
|
||||
type_prefixes "enum"|"struct"
|
||||
type_prefix {type_prefixes}{whitespace}+
|
||||
type_pointer {whitespace}*"*"
|
||||
type {type_prefix}?[a-zA-Z0-9_]+{type_pointer}?
|
||||
type {type_prefix}?{id}{type_pointer}?
|
||||
|
||||
%option noyywrap
|
||||
%option nounput
|
||||
|
@ -37,6 +39,9 @@ type {type_prefix}?[a-zA-Z0-9_]+{type_pointer}?
|
|||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <tree.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>. { 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>"," { return COMMA; }
|
||||
<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); }
|
||||
|
||||
<STATEMENT>[^%e]+ { return TEXT; }
|
||||
<STATEMENT>[^%e]+ { yylval.text = strdup(yytext); return TEXT; }
|
||||
<STATEMENT>{block_end} { return END; }
|
||||
<STATEMENT>"%" { return TEXT; /* catch % as text */ }
|
||||
<STATEMENT>"e" { return TEXT; /* catch e as text */ }
|
||||
<STATEMENT>"%" { yylval.text = strdup(yytext); return TEXT; /* catch % 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; }
|
||||
|
||||
<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>{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>"}" { 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