*.o
*~
-lib.c
-test
+ct
+parse.[ch]
+scan.c
--- /dev/null
+#include <stdio.h>
+#include <glib.h>
+
+#include "parse.h"
+
+gpointer parse(FILE *input, GList **data, GList **code);
+
+int main(int argc, char **argv)
+{
+ /* Parse arguments */
+ int option_log_level = 7;
+ GOptionEntry entries[] = {
+ {"debug", 'd', 0, G_OPTION_ARG_INT, &option_log_level,
+ "Change default log level", "[1-7]"},
+ {NULL}
+ };
+ GOptionContext *context = g_option_context_new("infile");
+ g_option_context_add_main_entries(context, entries, NULL);
+ g_option_context_parse(context, &argc, &argv, NULL);
+
+ FILE *input = stdin;
+ for (int i = 1; i < argc; i++)
+ if (g_str_has_suffix(argv[i], ".ct"))
+ input = fopen(argv[i], "r");
+
+ /* Start compiling */
+ GList *data = NULL;
+ GList *code = NULL;
+ parse(input, &data, &code);
+ data = g_list_reverse(data);
+ code = g_list_reverse(code);
+
+ g_print("#include <stdio.h>\n");
+ g_print("\n");
+ for (GList *cur = data; cur; cur = cur->next)
+ g_print("%s", cur->data);
+ g_print("\n");
+ for (GList *cur = code; cur; cur = cur->next)
+ g_print("%s", cur->data);
+}
-[void header() {]
+<% void header() { %>
Content-Type: application/xhtml+xml; charset=UTF-8
-[}]
+<% } %>
-[void body() {]
- [for (int i = 0; i < 3; i++)]
+<% void body() { %>
+ <% for (int i = 0; i < 3; i++) %>
<p>hello, world</p>
-[}]
+<% } %>
-[void html() {]
+<% void html() { %>
<html>
<body>
- [body();]
+ <% body(); %>
</body>
</html>
-[}]
+<% } %>
-[#include <glib.h>]
+<% #include <glib.h> %>
-[void header() {]
+
+<% void header() { %>
Content-Type: text/html; charset=UTF-8
-[}]
+<% } %>
-[void frame_index(){]
+<% void frame_index(){ %>
<html>
<frameset rows="20, *">
<frame name="head" src="?head">
</frameset>
</frameset>
</html>
-[}]
+<% } %>
-[void frame_head(){]
+<% void frame_head(){ %>
<html>
<head>
<style>
</center>
</body>
</html>
-[}]
+<% } %>
-[void frame_nav(int square, GList *images) {]
+<% void frame_nav(int square, GList *images) { %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
text-align:center;
text-decoration:none;
width:214px;
- [if (square)]
+ <% if (square) %>
height:214px;
}
.box {
</style>
</head>
<body>
- [for (GList *cur = images; cur; cur = cur->next) {]
+ <% for (GList *cur = images; cur; cur = cur->next) { %>
+ <% gchar *img = (gchar *)cur->data; %>
<div class="align">
- <a class="box" target="content"
- [g_print("href=\"images/%s\"", (gchar*)cur->data);]
- ><img
- [g_print("src=\"thumbs/%s\"", (gchar*)cur->data);]
- ></a>
+ <a class="box" target="content" href="images/<%= "%s", img %>">
+ <img src="thumbs/<%= "%s", img %>"></a>
</div>
- [}]
+ <% } %>
</body>
</html>
-[}]
+<% } %>
-[void frame_content(){]
+<% void frame_content(){ %>
<html>
</html>
-[}]
+<% } %>
%.c: %.ct
- ../tmpl.awk <$prereq >$target
+ (cd .. && mk)
+ ../ct <$prereq >$target
ex +'norm gg=G' +'wq' $target
<$HOME/lib/mkcommon
--- /dev/null
+PROGS=ct
+PKGS=glib-2.0
+ct-test:V: ct
+ ./ct < example/html.ct
+ct: ct.o scan.o parse.o parse.h
+%.c: %.l
+ flex -o $target $prereq
+%.h %.c: %.y
+ bison -d -o $stem.c $stem.y
+CLEAN=parse.h parse.c scan.c
+<$HOME/lib/mkcommon
--- /dev/null
+%{
+#define YYSTYPE char *
+#include <stdio.h>
+#include <glib.h>
+extern FILE *yyin;
+int yylex(void);
+void yyerror(gpointer node, char const *s);
+static GList *code = NULL;
+static GList *data = NULL;
+%}
+%error-verbose
+%parse-param {gpointer root};
+%token START END DATA OUT
+%%
+
+input : all | all input ;
+
+all : data | code | print ;
+
+data : DATA {
+ static int i = 0;
+ data = g_list_prepend(data, g_strdup_printf(
+ "static char data%d[] = \"%s\\n\";\n",
+ i, g_strescape($1, "")));
+ code = g_list_prepend(code, g_strdup_printf(
+ "fwrite(data%d, sizeof(data%d)-1, 1, stdout);\n",
+ i, i));
+ i++;
+};
+
+code : START DATA END {
+ code = g_list_prepend(code, g_strdup_printf("%s\n", $2));
+};
+
+print : START OUT DATA END {
+ code = g_list_prepend(code, g_strdup_printf("printf(%s);\n", $3));
+};
+
+%%
+gpointer parse(FILE *input, GList **_data, GList **_code) {
+ yyin = input;
+ yyparse(NULL);
+ *_data = data;
+ *_code = code;
+ return NULL;
+}
+void yyerror(gpointer root, char const *s) {
+ g_error("[%s]\n", s);
+}
--- /dev/null
+%{
+#define YYSTYPE char *
+#include <glib.h>
+#include "parse.h"
+#define debug(arg) // g_message("scan: " arg, yytext);
+%}
+%option noyywrap
+%option nounput
+%option noinput
+/* %option nodebug */
+START [ \t]*<%
+END [ \t]*%>[ \t]*
+DATA ([^<\n]|<[^%])*
+CODE [ \t\n]([^%\n]|%[^>])*
+%s IN FMT
+%%
+<INITIAL>{START} { debug("START [%s]"); yylval = g_strdup(yytext); BEGIN(IN); return START; }
+<INITIAL>{DATA} { debug("DATA [%s]"); yylval = g_strdup(yytext); return DATA; }
+<IN>{END} { debug("END [%s]"); yylval = g_strdup(yytext); BEGIN(INITIAL); return END; }
+<IN>= { debug("OUT [%s]"); yylval = g_strdup(yytext); return OUT; }
+<IN>{CODE} { debug("CODE [%s]"); yylval = g_strdup(yytext); return DATA; }
+[\n] { debug("NL [%s]"); }
+%%