New week, new Rust! What are you folks up to?
I've added the ability to generate a bottom-up parser to my LL parser generator, lexigram (initially inspired by ANTLR, though not quite the same). It has the same features on the LR side: custom trait-based listener interface, transparent support for + and * repetitions and list of token-separated items, syntax-based token interception, ability to parse virtually endless "live" streams, and so on.
Last missing feature: now it's time to add error recovery, which allows the LR parser to continue after a lexical or syntax error is met. After that, I'll have to update the documentation. If it gets enough attention, that is, which wasn't the case for LL.
It's very interesting to have both types and see them from the point of view of the generator. LR is an entirely different animal from LL, more powerful yet less flexible, but I'm trying to make both types of parsers as close as possible from the perspective of the interface.
A remarkable property of LR is that their parsing algorithm itself remains exactly the same, no matter the type: LR(1), LALR(1), SLR, IELR, ... And so does the generated interface around it, which is by far the worst part to write in a generator like this! It'll allow me to add more of those types later without touching that part of the code, and, more importantly, it'll allow the user to switch without having to change anything—except perhaps the grammar, depending on the relative freedom given by those different parsers. Currently, it's just LALR.
Continuing to develop my custom system programming language that uses Rust
I just finished adding more, like pointer support, pointer must use lifetime, non null pointer like STD NonNull, module system. This can be a place of my demonstration of my ideas that may can be added to Rust
Like :
.main {
mut val: i32 = 10 until lifetime_name
// nullable pointer with syntax sugar ?
const pointer: mut ptr? i32 = &val until lifetime_name
// close the original memory and all pointer that point to it
close lifetime_name
// else must present otherwise compile error (non else variant can only be used in non null ptr aka ptr without ?
// the else supports blockless and block
// else panic or return error etc
// this will return compile error that the pointer is already closed, so can not be used aka dangling pointer is detected
deref pointer = 20 else panic("oh no null ptr")
}
So the lifetime already prevent forgot to free, double free, and use after free while remaining flexible and zero cost. The optional ptr type prevent null ptr
The module is also flexible
// src/a.fl :
register my_module
pub .hello {
println("hello")
}
// src/folder/b.fl :
register my_module2
pub struct data {
i32 val
}
pub .hello {
println("hello")
}
// Main file or any other file :
// bring all module and public
bring all
// to call must use the module name
my_module:hello()
// Or bring specific module :
bring my_module
my_module:helllo()
// Or specific module + specific code, like only struct data and function hello :
bring my_module: data .hello
// does not need module name to call
hello()
No folder structure needed, free to organize the folder all user want
Register + pub modifier from anywhere inside src folder. Then caller can bring which one they want without caring folder structure
Now designing buffer overflow prevention :<
Preparing v0.3.0 of Vicarian, a TLS-first (well only) reverse proxy. The big feature this release is static-file support, although I also added Prometheus metrics recently.
After that I have to make a decision about the config language; it's currently Corn, but I'm considering a move to HCL or KDL before declaring it beta-ready.