Initial commit
This commit is contained in:
commit
6ff32bd4a4
7 changed files with 190 additions and 0 deletions
14
.gitignore
vendored
Normal file
14
.gitignore
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# Rust
|
||||||
|
/target
|
||||||
|
Cargo.lock
|
||||||
|
|
||||||
|
# Version control and locks.
|
||||||
|
*.orig
|
||||||
|
*.swp
|
||||||
|
*~
|
||||||
|
.#*
|
||||||
|
\#*\#
|
||||||
|
ChangeLog
|
||||||
|
[0-9]*.patch
|
||||||
|
[0-9]*.txt
|
||||||
|
/vc-dwim-log-*
|
19
Cargo.toml
Normal file
19
Cargo.toml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
[package]
|
||||||
|
name = "sing"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
build = "build.rs"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
lalrpop = "0.19"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
syn = "1"
|
||||||
|
regex = "1"
|
||||||
|
lalrpop-util = "0.19"
|
||||||
|
lalrpop = "0.19"
|
34
TODO
Normal file
34
TODO
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# Sing
|
||||||
|
|
||||||
|
Std
|
||||||
|
I/o
|
||||||
|
Negotiator
|
||||||
|
Generator
|
||||||
|
|
||||||
|
## What is sing meant to be?
|
||||||
|
|
||||||
|
- Provide stdio interface to traits
|
||||||
|
- not like serde because it's for traits instead of objects
|
||||||
|
- not like clap since it works at run time, not before
|
||||||
|
- similar ease of use as both of the above though
|
||||||
|
|
||||||
|
## How to get there
|
||||||
|
|
||||||
|
- Using lalrpop (in a feature flag)
|
||||||
|
- Maybe utilize serde
|
||||||
|
- Look at how clap handles states between macro calls
|
||||||
|
- They operate on a singleton lol
|
||||||
|
- This would need to store All traits and their functions
|
||||||
|
- It should also own (locked) Stdin, Stdout and Stderr (or any one Read and two Write objects)
|
||||||
|
- This bad boi would also implement the main loop for the cli application.
|
||||||
|
|
||||||
|
## Links oder so lül
|
||||||
|
|
||||||
|
https://serde.rs/impl-serializer.html
|
||||||
|
https://docs.serde.rs/serde/trait.Serializer.html
|
||||||
|
https://docs.rs/proc-macro2/1.0.36/proc_macro2/
|
||||||
|
https://docs.rs/syn/1.0.86/syn/
|
||||||
|
https://github.com/clap-rs/clap/blob/master/src/derive.rs
|
||||||
|
https://github.com/clap-rs/clap
|
||||||
|
https://github.com/clap-rs/clap/blob/v3.0.14/examples/tutorial_builder/README.md
|
||||||
|
https://www.morling.dev/blog/whats-in-a-good-error-message/
|
5
build.rs
Normal file
5
build.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
extern crate lalrpop;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
lalrpop::process_root().unwrap();
|
||||||
|
}
|
47
src/callobj.rs
Normal file
47
src/callobj.rs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
pub struct CallObj {
|
||||||
|
trait_string: Option<String>,
|
||||||
|
fun_string: String,
|
||||||
|
index: usize,
|
||||||
|
data: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CallObj {
|
||||||
|
pub fn new((trait_string, fun_string, index): (Option<String>, String, usize), data: Vec<String>) -> Self {
|
||||||
|
Self{
|
||||||
|
trait_string,
|
||||||
|
fun_string,
|
||||||
|
index,
|
||||||
|
data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for CallObj {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let mut repr = String::new();
|
||||||
|
|
||||||
|
match &self.trait_string {
|
||||||
|
Some(tstr) => {
|
||||||
|
repr.push_str(tstr);
|
||||||
|
repr.push('>');
|
||||||
|
},
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
repr.push_str(&self.fun_string);
|
||||||
|
|
||||||
|
if self.index != usize::MAX {
|
||||||
|
repr.push('>');
|
||||||
|
repr.push_str(&self.index.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
for element in &self.data {
|
||||||
|
repr.push(' ');
|
||||||
|
repr.push_str(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(f, "{}", repr)
|
||||||
|
}
|
||||||
|
}
|
22
src/fun_parser.lalrpop
Normal file
22
src/fun_parser.lalrpop
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use crate::callobj::CallObj;
|
||||||
|
|
||||||
|
grammar;
|
||||||
|
|
||||||
|
pub Call: CallObj = {
|
||||||
|
<Descriptor> <Data> => CallObj::new(<>),
|
||||||
|
};
|
||||||
|
|
||||||
|
Descriptor: (Option<String>, String, usize) = {
|
||||||
|
<t: (<Identifier> ">")?> <f: Identifier> ">" <i: Index> => (t, f, i),
|
||||||
|
<t: (<Identifier> ">")?> <f:Identifier> => (t, f, usize::MAX),
|
||||||
|
}
|
||||||
|
|
||||||
|
Identifier: String = r"[A-Z][a-zA-Z]*" => <>.to_string();
|
||||||
|
|
||||||
|
Index: usize = r"[1-9][0-9]*" => usize::from_str(<>).unwrap();
|
||||||
|
|
||||||
|
Data: Vec<String> = Value+;
|
||||||
|
|
||||||
|
Value: String = r" [0-9a-zA-Z]*" => (<>[1..<>.chars().count()]).to_string();
|
49
src/lib.rs
Normal file
49
src/lib.rs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
#[macro_use] extern crate lalrpop_util;
|
||||||
|
extern crate lalrpop;
|
||||||
|
|
||||||
|
mod callobj;
|
||||||
|
|
||||||
|
lalrpop_mod!(fun_parser);
|
||||||
|
|
||||||
|
#[proc_macro_derive(HelloMacro)]
|
||||||
|
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
|
||||||
|
let _friend = lalrpop::process_root();
|
||||||
|
println!("Hello world!");
|
||||||
|
fun_parser::CallParser::new();
|
||||||
|
input
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::fun_parser;
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_works() {
|
||||||
|
let result = 2 + 2;
|
||||||
|
assert_eq!(result, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parser_parses() {
|
||||||
|
let test_str = "Trait>Fun>1 arg1 arg2 arg3";
|
||||||
|
assert!(fun_parser::CallParser::new()
|
||||||
|
.parse(test_str)
|
||||||
|
.is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parser_parses_correctly() {
|
||||||
|
let test_str: &str = "Trait>Fun>1 arg1 arg2 arg3";
|
||||||
|
println!("[{}]",
|
||||||
|
fun_parser::CallParser::new()
|
||||||
|
.parse(test_str).unwrap()
|
||||||
|
);
|
||||||
|
assert!(format!( "{}",
|
||||||
|
fun_parser::CallParser::new()
|
||||||
|
.parse(test_str).unwrap()
|
||||||
|
) == test_str);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue