+tslex
This commit is contained in:
parent
c76113e400
commit
cd86cd6bdf
3
C_C++/bison/tslex/Makefile
Normal file
3
C_C++/bison/tslex/Makefile
Normal 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
|
37
C_C++/bison/tslex/README.md
Normal file
37
C_C++/bison/tslex/README.md
Normal 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
46
C_C++/bison/tslex/main.y
Normal 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
63
C_C++/bison/tslex/tslex.c
Normal 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
16
C_C++/bison/tslex/tslex.h
Normal 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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user