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