fixed tests and memory management; added multi selector rule support
This commit is contained in:
parent
8d9b6c5256
commit
e716ece6a9
3
Makefile
3
Makefile
@ -29,7 +29,7 @@ else
|
||||
endif
|
||||
|
||||
CFLAGS += -std=c2x -Wall -Wpedantic
|
||||
CPPFLAGS += -Iobject -Ilibrary
|
||||
CPPFLAGS += -Isource -Iobject -Ilibrary
|
||||
|
||||
# --- Rule Section ---
|
||||
${OUT}: ${GENSOURCE} ${GENOBJECT} ${OBJECT} ${LIBS}
|
||||
@ -60,3 +60,4 @@ clean:
|
||||
-rm ${GENSOURCE}
|
||||
-rm ${OBJECT}
|
||||
-rm ${OUT}
|
||||
-rm test/*.tb.*
|
||||
|
@ -23,10 +23,6 @@ extern int tbsp_yy_deinit(void);
|
||||
extern int tbsp_c_yy_init(void);
|
||||
extern int tbsp_c_yy_deinit(void);
|
||||
|
||||
char * language = NULL;
|
||||
char * verbatim = NULL;
|
||||
char * top = NULL;
|
||||
|
||||
void yyerror(const char * const fmt, ...) {
|
||||
extern int yylineno;
|
||||
va_list args;
|
||||
@ -52,7 +48,7 @@ void dump_rule_table(const char * const name, rule_type_t type_mask) {
|
||||
sprint_r = asprintf(&sprint_buffer,
|
||||
TBSP_case,
|
||||
kv_A(rules, i).string,
|
||||
kv_A(rules, i).target
|
||||
kv_A(codes, kv_A(rules, i).code_index).number
|
||||
);
|
||||
fputs(sprint_buffer, yyout);
|
||||
free(sprint_buffer);
|
||||
@ -82,7 +78,7 @@ void dump_output(void) {
|
||||
dump_rule_table("leave_cases", LEAVE_RULE);
|
||||
|
||||
fputs(TBSP_traverse_top, yyout);
|
||||
for (int i = 0; i < kv_size(rules); i++) {
|
||||
for (int i = 0; i < kv_size(codes); i++) {
|
||||
const char * const case_string = "\
|
||||
case %d: {\n\
|
||||
%s\n\
|
||||
@ -90,8 +86,8 @@ void dump_output(void) {
|
||||
";
|
||||
sprint_r = asprintf(&sprint_buffer,
|
||||
case_string,
|
||||
kv_A(rules, i).target,
|
||||
kv_A(rules, i).code
|
||||
kv_A(codes, i).number,
|
||||
kv_A(codes, i).code
|
||||
);
|
||||
fputs(sprint_buffer, yyout);
|
||||
free(sprint_buffer);
|
||||
@ -111,17 +107,13 @@ void init(void) {
|
||||
|
||||
static inline
|
||||
void deinit(void) {
|
||||
for (int i = 0; i < kv_size(rules); i++) {
|
||||
free(kv_A(rules, i).string);
|
||||
free(kv_A(rules, i).code);
|
||||
}
|
||||
fclose(yyin);
|
||||
fclose(yyout);
|
||||
tbsp_tab_deinit();
|
||||
tbsp_yy_deinit();
|
||||
tbsp_c_yy_deinit();
|
||||
free(output_file_name);
|
||||
free(input_file_name);
|
||||
free(verbatim);
|
||||
free(language);
|
||||
free(top);
|
||||
}
|
||||
|
||||
signed main(const int argc, const char * const * const argv) {
|
||||
|
28
source/rule.h
Normal file
28
source/rule.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef RULE_H
|
||||
#define RULE_H
|
||||
|
||||
#include <kvec.h>
|
||||
|
||||
typedef enum {
|
||||
ENTER_RULE = 0b0001,
|
||||
LEAVE_RULE = 0b0010,
|
||||
} rule_type_t;
|
||||
|
||||
typedef struct {
|
||||
int number;
|
||||
char * code;
|
||||
} code_t;
|
||||
|
||||
typedef struct {
|
||||
rule_type_t type;
|
||||
char * string;
|
||||
int code_index;
|
||||
} rule_t;
|
||||
|
||||
typedef kvec_t(rule_t) rule_vector_t;
|
||||
extern rule_vector_t rules;
|
||||
|
||||
typedef kvec_t(code_t) code_vector_t;
|
||||
extern code_vector_t codes;
|
||||
|
||||
#endif
|
@ -40,7 +40,7 @@ identifier [a-zA-z][-a-zA-z0-9_]*
|
||||
return SEPARATOR;
|
||||
}
|
||||
. {
|
||||
yyerror("unknown shit");
|
||||
yyerror("unknown expression in rule section");
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,7 +86,6 @@ leave[[:space:]] { return LEAVE; }
|
||||
}
|
||||
|
||||
--code_nesting;
|
||||
;
|
||||
}
|
||||
.|\n { buffer = sdscat(buffer, yytext); }
|
||||
}
|
||||
|
@ -1,36 +1,30 @@
|
||||
%{
|
||||
#include "tbsp.yy.h"
|
||||
|
||||
extern char * language;
|
||||
extern char * top;
|
||||
extern char * verbatim;
|
||||
#include <kvec.h>
|
||||
|
||||
int target_counter = 1;
|
||||
|
||||
kvec_t(char *) rule_selectors;
|
||||
|
||||
char * language = NULL;
|
||||
char * verbatim = NULL;
|
||||
char * top = NULL;
|
||||
|
||||
#define COMA ,
|
||||
%}
|
||||
%code requires {
|
||||
typedef enum {
|
||||
ENTER_RULE = 0b0001,
|
||||
LEAVE_RULE = 0b0010,
|
||||
} rule_type_t;
|
||||
|
||||
typedef struct {
|
||||
rule_type_t type;
|
||||
int target;
|
||||
char * string;
|
||||
char * code;
|
||||
} rule_t;
|
||||
|
||||
#include <kvec.h>
|
||||
typedef kvec_t(rule_t) rule_vector_t;
|
||||
extern rule_vector_t rules;
|
||||
|
||||
#include "rule.h"
|
||||
extern void yyerror(const char * const s, ...);
|
||||
}
|
||||
%code provides {
|
||||
void tbsp_tab_init(void);
|
||||
void tbsp_tab_deinit(void);
|
||||
|
||||
extern rule_vector_t rules;
|
||||
|
||||
extern char * language;
|
||||
extern char * top;
|
||||
extern char * verbatim;
|
||||
}
|
||||
%union{
|
||||
char * strval;
|
||||
@ -41,7 +35,6 @@
|
||||
%token ENTER LEAVE
|
||||
%token<strval> IDENTIFIER CODE_BLOB
|
||||
%type<ruleval> rule_type
|
||||
%type<strval> rule_selector
|
||||
%%
|
||||
document
|
||||
: %empty
|
||||
@ -91,16 +84,22 @@ rule
|
||||
|
||||
char * code_blob_expanded = strdup(tbsp_c_expland_code($3));
|
||||
|
||||
kv_push(rule_t, rules, (rule_t) {
|
||||
.type = $1 COMA
|
||||
.target = target_counter COMA
|
||||
.string = $2 COMA
|
||||
.code = code_blob_expanded COMA
|
||||
kv_push(code_t, codes, (code_t) {
|
||||
.number = target_counter++ COMA
|
||||
.code = code_blob_expanded COMA
|
||||
});
|
||||
|
||||
++target_counter;
|
||||
for (int i = 0; i < kv_size(rule_selectors); i++) {
|
||||
kv_push(rule_t, rules, (rule_t) {
|
||||
.type = $1 COMA
|
||||
.string = kv_A(rule_selectors, i) COMA
|
||||
.code_index = codes.n-1 COMA
|
||||
});
|
||||
}
|
||||
|
||||
rule_selectors.n = 0;
|
||||
tbsp_c_yy_reset();
|
||||
free($3);
|
||||
}
|
||||
;
|
||||
|
||||
@ -111,7 +110,12 @@ rule_type
|
||||
;
|
||||
|
||||
rule_selector
|
||||
: IDENTIFIER { $$ = $1; }
|
||||
: IDENTIFIER {
|
||||
kv_push(char *, rule_selectors, $1);
|
||||
}
|
||||
| IDENTIFIER rule_selector {
|
||||
kv_push(char *, rule_selectors, $1);
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
@ -123,16 +127,32 @@ code_section
|
||||
%%
|
||||
|
||||
rule_vector_t rules;
|
||||
code_vector_t codes;
|
||||
|
||||
void tbsp_tab_init(void) {
|
||||
kv_init(rules);
|
||||
kv_init(codes);
|
||||
kv_init(rule_selectors);
|
||||
}
|
||||
|
||||
void tbsp_tab_deinit(void) {
|
||||
for (int i = 0; i < kv_size(rule_selectors); i++) {
|
||||
free(kv_A(rule_selectors, i));
|
||||
}
|
||||
|
||||
for (int i = 0; i < kv_size(codes); i++) {
|
||||
free(kv_A(codes, i).code);
|
||||
}
|
||||
|
||||
for (int i = 0; i < kv_size(rules); i++) {
|
||||
free(kv_A(rules, i).string);
|
||||
free(kv_A(rules, i).code);
|
||||
}
|
||||
|
||||
kv_destroy(rules);
|
||||
kv_destroy(codes);
|
||||
kv_destroy(rule_selectors);
|
||||
|
||||
free(verbatim);
|
||||
free(language);
|
||||
free(top);
|
||||
}
|
||||
|
@ -1,25 +1,53 @@
|
||||
class CMDTEST_master_batch < Cmdtest::Testcase
|
||||
def setup
|
||||
import_file "test/file2str.h", "./"
|
||||
end
|
||||
|
||||
def test_converter
|
||||
import_file "test/convert.tbsp", "./"
|
||||
source = "convert"
|
||||
|
||||
import_file "test/#{source}.tbsp", "./"
|
||||
import_file "test/input.md", "./"
|
||||
|
||||
cmd "tbsp -o convert.tb.c convert.tbsp" do
|
||||
created_files ["convert.tb.c"]
|
||||
cmd "tbsp -o #{source}.tb.c #{source}.tbsp" do
|
||||
created_files ["#{source}.tb.c"]
|
||||
end
|
||||
shell "bake convert.tb.c"
|
||||
cmd "./convert.tb.out input.md" do
|
||||
cmd "gcc -w -o #{source}.out #{source}.tb.c $(pkg-config --cflags --libs tree-sitter) -ltree-sitter-markdown" do
|
||||
created_files ["#{source}.out"]
|
||||
end
|
||||
cmd "./#{source}.out input.md" do
|
||||
stdout_equal /.+/
|
||||
end
|
||||
end
|
||||
|
||||
def test_function_collector
|
||||
import_file "test/function_collector.tbsp", "./"
|
||||
source = "function_collector"
|
||||
|
||||
cmd "tbsp -o function_collector.tb.cpp function_collector.tbsp" do
|
||||
created_files ["function_collector.tb.cpp"]
|
||||
import_file "test/#{source}.tbsp", "./"
|
||||
|
||||
cmd "tbsp -o #{source}.tb.cpp #{source}.tbsp" do
|
||||
created_files ["#{source}.tb.cpp"]
|
||||
end
|
||||
shell "bake function_collector.tb.cpp"
|
||||
cmd "./function_collector.tb.out function_collector.tb.cpp" do
|
||||
cmd "g++ -w -o #{source}.out #{source}.tb.cpp $(pkg-config --cflags --libs tree-sitter tree-sitter-cpp)" do
|
||||
created_files ["#{source}.out"]
|
||||
end
|
||||
cmd "./#{source}.out #{source}.tb.cpp" do
|
||||
stdout_equal /.+/
|
||||
end
|
||||
end
|
||||
|
||||
def test_double_selector
|
||||
source = "double_selector"
|
||||
|
||||
import_file "test/#{source}.tbsp", "./"
|
||||
|
||||
cmd "tbsp #{source}.tbsp" do
|
||||
created_files ["#{source}.tb.c"]
|
||||
end
|
||||
cmd "g++ -w -o #{source}.out #{source}.tb.c $(pkg-config --cflags --libs tree-sitter tree-sitter-c)" do
|
||||
created_files ["#{source}.out"]
|
||||
end
|
||||
cmd "./#{source}.out #{source}.tb.c" do
|
||||
stdout_equal /.+/
|
||||
end
|
||||
end
|
||||
|
@ -14,6 +14,7 @@ leave section {
|
||||
}
|
||||
|
||||
enter atx_heading {
|
||||
puts("AAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
printf("<h%d>\n", depth);
|
||||
}
|
||||
leave atx_heading {
|
||||
@ -21,66 +22,57 @@ leave atx_heading {
|
||||
}
|
||||
|
||||
enter paragraph {
|
||||
printf("<p>");
|
||||
puts("<p>");
|
||||
}
|
||||
leave paragraph {
|
||||
printf("</p>\n");
|
||||
puts("</p>");
|
||||
}
|
||||
|
||||
enter list {
|
||||
printf("<ol>");
|
||||
puts("<ol>");
|
||||
}
|
||||
leave list {
|
||||
printf("</ol>\n");
|
||||
puts("</ol>");
|
||||
}
|
||||
|
||||
enter list_item {
|
||||
printf("<li>");
|
||||
puts("<li>");
|
||||
}
|
||||
leave list_item {
|
||||
printf("</li>\n");
|
||||
puts("</li>");
|
||||
}
|
||||
|
||||
enter fenced_code_block {
|
||||
printf("<pre>");
|
||||
puts("<pre>");
|
||||
}
|
||||
leave fenced_code_block {
|
||||
printf("</pre>\n");
|
||||
puts("</pre>");
|
||||
}
|
||||
|
||||
enter inline {
|
||||
char * text = tbget_text;
|
||||
printf(text);
|
||||
puts(text);
|
||||
free(text);
|
||||
}
|
||||
enter code_fence_content {
|
||||
char * text = tbget_text;
|
||||
printf(text);
|
||||
puts(text);
|
||||
free(text);
|
||||
}
|
||||
|
||||
%%
|
||||
// @BAKE g++ -o $*.out $@ $(pkg-config --cflags --libs tree-sitter) -ltree-sitter-markdown -ggdb
|
||||
/* @BAKE
|
||||
tbsp $@
|
||||
gcc -o $*.out $*.tb.c $(pkg-config --cflags --libs tree-sitter) -ltree-sitter-markdown -ggdb
|
||||
./$*.out input.md
|
||||
@STOP
|
||||
*/
|
||||
|
||||
#include "file2str.h"
|
||||
|
||||
signed main(int argc, char * * argv) {
|
||||
if (argc < 2) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
FILE* f = fopen(argv[1], "r");
|
||||
|
||||
if (!f) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
int flen = ftell(f);
|
||||
rewind(f);
|
||||
char fstr[flen+1];
|
||||
fstr[flen] = '\00';
|
||||
fread(fstr, flen, sizeof(char), f);
|
||||
|
||||
fclose(f);
|
||||
if (argc < 2) { return 1; }
|
||||
FILE2STR(fstr, argv[1]);
|
||||
|
||||
printf("-- meta: %d chars\n", flen);
|
||||
|
||||
|
36
test/double_selector.tbsp
Normal file
36
test/double_selector.tbsp
Normal file
@ -0,0 +1,36 @@
|
||||
%language c
|
||||
%%
|
||||
|
||||
enter function_definition declaration {
|
||||
TSNode declarator = $$->"declarator";
|
||||
TSNode next_declarator = declarator;
|
||||
while (next_declarator = tbnode_child_by_field_name(next_declarator, "declarator"),
|
||||
!ts_node_is_null(next_declarator)) {
|
||||
declarator = next_declarator;
|
||||
}
|
||||
|
||||
char * s = tbget_node_text(declarator);
|
||||
puts(s);
|
||||
free(s);
|
||||
}
|
||||
|
||||
%%
|
||||
/* @BAKE
|
||||
tbsp $@
|
||||
gcc -o $*.out $*.tb.c $(pkg-config --cflags --libs tree-sitter tree-sitter-c) -ggdb
|
||||
./$*.out $.tb.c
|
||||
@STOP
|
||||
*/
|
||||
|
||||
#include "file2str.h"
|
||||
|
||||
signed main(int argc, char * * argv) {
|
||||
if (argc < 2) { return 1; }
|
||||
FILE2STR(fstr, argv[1]);
|
||||
|
||||
puts(fstr);
|
||||
|
||||
tbtraverse(fstr);
|
||||
|
||||
return 0;
|
||||
}
|
15
test/file2str.h
Normal file
15
test/file2str.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef FILE2STR_H
|
||||
#define FILE2STR_H
|
||||
|
||||
#define FILE2STR(dest, filename) \
|
||||
FILE* f = fopen(filename, "r"); \
|
||||
if (!f) { return 1; } \
|
||||
fseek(f, 0, SEEK_END); \
|
||||
int flen = ftell(f); \
|
||||
rewind(f); \
|
||||
char fstr[flen+1]; \
|
||||
dest[flen] = '\00'; \
|
||||
fread(dest, flen, sizeof(char), f); \
|
||||
fclose(f);
|
||||
|
||||
#endif
|
@ -19,22 +19,19 @@ enter function_definition {
|
||||
}
|
||||
|
||||
%%
|
||||
/* @BAKE
|
||||
tbsp -o $*.tb.cpp $@
|
||||
g++ -o $*.out $*.tb.cpp $(pkg-config --cflags --libs tree-sitter tree-sitter-cpp) -ggdb
|
||||
./$*.out $@
|
||||
@STOP
|
||||
*/
|
||||
|
||||
// @BAKE g++ $@ -o $*.out $(pkg-config --cflags --libs tree-sitter tree-sitter-cpp)
|
||||
#include "file2str.h"
|
||||
|
||||
signed main(int argc, char * * argv) {
|
||||
if (argc < 2) {
|
||||
return 1;
|
||||
}
|
||||
if (argc < 2) { return 1; }
|
||||
|
||||
FILE* f = fopen(argv[1], "r");
|
||||
fseek(f, 0, SEEK_END);
|
||||
int flen = ftell(f);
|
||||
rewind(f);
|
||||
char fstr[flen+1];
|
||||
fstr[flen] = '\00';
|
||||
fread(fstr, flen, sizeof(char), f);
|
||||
fclose(f);
|
||||
FILE2STR(fstr, argv[1]);
|
||||
|
||||
tbtraverse(fstr);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user