This commit is contained in:
anon 2024-09-06 16:22:52 +02:00
parent c76113e400
commit cd86cd6bdf
5 changed files with 165 additions and 0 deletions

View File

@ -0,0 +1,3 @@
main:
bison --header=main.tab.h main.y
gcc main.tab.c tslex.c $$(pkg-config --cflags --libs tree-sitter tree-sitter-c) -ggdb

View File

@ -0,0 +1,37 @@
a few days ago i saw this pet project on https://git.peppe.rs/languages/tbsp/tree/examples/code-overview/overview.tbsp
being a DSL fan, i really like the idea.
except seemingly the guy is making a full general purpose interpreter too,
which sentences the project to death.
i have email him about this (response pending)
as i was thinking however i started wondering if bison could do it
given an adaquate lex()
well, the answer is kinda.
if you look at the code, well it works.
problems:
+ bison doesnt know includes so it would have to be preprocessed
(to provide tokens as -perversily- the scanner defines them)
+ the tree sitter query language is much more...
well lets say verboser than i imagined, so our code has to be much
more complexed than i hoped so;
either the bison programmer has to type a lot or lex()
define a bunch of wrappers which would be language specific
+ we are not really using the stack are we?
(unless we do stuff like `BEGIN FUNCTION`/`END FUNCTION`
to mimic the "original" grammar (which is not bad))
so its a hack to begin with,
and because of the above reasons and ugly one of that
so, instead, i do think a DSL is the answer.
only issue is that if the guy disagrees on making it "supplementary"
then i will have to make my own.
one more thing, a ts node query language would also be nice.
something along the lines of
```
$$->declarator
```
expanding to a node object
(or erroring out safely if the "declarator" named field does not exist)

46
C_C++/bison/tslex/main.y Normal file
View File

@ -0,0 +1,46 @@
%{
#include <stdio.h>
#include <string.h>
#include <tree_sitter/api.h>
#include "tslex.h"
%}
%token UNDEF
%token<nodeval> FUNCTION
%union {
TSNode nodeval;
}
%%
document
: any
;
any
: %empty
| UNDEF any
| FUNCTION any {
printf("-- %s\n",
ts_node_string($1)
);
char * s = "declarator";
TSNode identifier = ts_node_child_by_field_name($1, s, strlen(s));
if (ts_node_is_null(identifier)) {
break;
}
printf("-- %.*s\n",
ts_node_text_len(identifier),
ts_node_text(identifier)
);
}
;
%%
signed main() {
yyinit();
yyparse();
yydeinit();
return 0;
}

63
C_C++/bison/tslex/tslex.c Normal file
View File

@ -0,0 +1,63 @@
#include <stdio.h>
#include <string.h>
#include <tree_sitter/api.h>
#include "main.tab.h"
extern const TSLanguage * tree_sitter_c(void);
TSParser * parser;
TSTree * tree;
TSTreeCursor cursor;
TSNode current_node;
const char * source_code = "int main() { return 0; }";
int yyinit() {
parser = ts_parser_new();
ts_parser_set_language(parser, tree_sitter_c());
tree = ts_parser_parse_string(parser, NULL, source_code, strlen(source_code));
cursor = ts_tree_cursor_new(ts_tree_root_node(tree));
current_node = ts_tree_root_node(tree);
}
int yydeinit() {
ts_tree_delete(tree);
ts_parser_delete(parser);
ts_tree_cursor_delete(&cursor);
}
#define RETURN(x) do {\
r = x; \
goto END; \
} while(0);
int yylex() {
int r = UNDEF;
static int end = 0; // XXX
if (end) {
return 0;
}
if (!strcmp("function_definition", ts_node_type(current_node))) {
yylval.nodeval = current_node;
RETURN(FUNCTION);
}
END:
if (ts_tree_cursor_goto_first_child(&cursor)
&& ts_tree_cursor_goto_next_sibling(&cursor)
&& ts_tree_cursor_goto_parent(&cursor)) {
end = 1;
}
current_node = ts_tree_cursor_current_node(&cursor);
return r;
}
void yyerror() {
puts("error -- this should never happen");
}

16
C_C++/bison/tslex/tslex.h Normal file
View File

@ -0,0 +1,16 @@
#include <tree_sitter/api.h>
extern void yyerror();
extern int yyinit();
extern int yydeinit();
extern int yylex();
extern const char * source_code;
const char * ts_node_text(const TSNode node) {
return source_code + ts_node_start_byte(node);
}
int ts_node_text_len(const TSNode node) {
return ts_node_end_byte(node) - ts_node_start_byte(node);
}