first commit
This commit is contained in:
commit
fb89e929fe
7 changed files with 204 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
**/*.rs.bk
|
6
Cargo.lock
generated
Normal file
6
Cargo.lock
generated
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "petri"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "petri"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["eater <=@eater.me>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
32
README.md
Normal file
32
README.md
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# Petri
|
||||||
|
|
||||||
|
A directional shell
|
||||||
|
|
||||||
|
# Syntax
|
||||||
|
|
||||||
|
The syntax of petri is a bit different than normal shells because it uses ASCII art to define running graphs
|
||||||
|
|
||||||
|
```
|
||||||
|
#!/usr/bin/env petri
|
||||||
|
\(diff @ @)
|
||||||
|
^ ^
|
||||||
|
| |
|
||||||
|
\(ls /dev) -> replace_x --+-> replace_y --x-+
|
||||||
|
| |
|
||||||
|
+-> replace_z --+
|
||||||
|
---
|
||||||
|
replace_x: sed 's:x:y:g'
|
||||||
|
replace_y: sed 's:y:z:g'
|
||||||
|
replace_z: sed 's:z:x:g'
|
||||||
|
```
|
||||||
|
|
||||||
|
This would be the equivalent of the bash file:
|
||||||
|
|
||||||
|
```
|
||||||
|
ls /dev | sed 's:x:y:g' > /tmp/temp_file
|
||||||
|
diff <(sed 's:z:x:g' < /tmp/temp_file) <(sed 's:y:z:g' < /tmp/temp_file)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Why 'petri'
|
||||||
|
|
||||||
|
Originally I wanted to call it `dish` but I found that to generic, and since dish is from time to time preceded with petri, I choose that.
|
28
src/graph.rs
Normal file
28
src/graph.rs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug)]
|
||||||
|
pub struct Graph {
|
||||||
|
pub nodes: HashMap<u32, Node>,
|
||||||
|
pub node_names: HashMap<String, u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug)]
|
||||||
|
pub struct Node {
|
||||||
|
pub name: Option<String>,
|
||||||
|
// Set string to command
|
||||||
|
pub command: Option<String>,
|
||||||
|
pub edges: Vec<Edge>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
|
||||||
|
pub enum Transport {
|
||||||
|
Err,
|
||||||
|
Out,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug)]
|
||||||
|
pub struct Edge {
|
||||||
|
pub from: u32,
|
||||||
|
pub to: u32,
|
||||||
|
pub transports: HashSet<Transport>,
|
||||||
|
}
|
14
src/main.rs
Normal file
14
src/main.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
use crate::parser::parse;
|
||||||
|
|
||||||
|
mod graph;
|
||||||
|
mod parser;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let graph = parse(r"
|
||||||
|
# hello
|
||||||
|
hello -> bye
|
||||||
|
|
||||||
|
".to_string());
|
||||||
|
|
||||||
|
println!("result: {:?}", graph);
|
||||||
|
}
|
113
src/parser.rs
Normal file
113
src/parser.rs
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
use crate::graph::{Graph, Node};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fmt::Error;
|
||||||
|
|
||||||
|
enum State {
|
||||||
|
Default,
|
||||||
|
Edge,
|
||||||
|
Node(String),
|
||||||
|
AnonymousNode,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Consumer {
|
||||||
|
lines: Vec<String>,
|
||||||
|
state: ConsumerState,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ConsumerState {
|
||||||
|
line: usize,
|
||||||
|
position: usize,
|
||||||
|
absolute_position: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Consumer {
|
||||||
|
fn consume_from_line(&mut self) -> Option<char> {
|
||||||
|
if let Some(chxr) = self.peek_on_line() {
|
||||||
|
self.push_char();
|
||||||
|
Some(chxr)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn peek_on_line(&mut self) -> Option<char> {
|
||||||
|
let line = &self.lines[self.state.line];
|
||||||
|
if self.state.position + 1 >= line.len() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Ok(line[self.state.position + 1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_char(&mut self) {
|
||||||
|
self.state.position += 1;
|
||||||
|
self.state.absolute_position += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(content: String) -> Consumer {
|
||||||
|
Consumer {
|
||||||
|
lines: content
|
||||||
|
.lines()
|
||||||
|
.map(|x| String::from(x))
|
||||||
|
.collect(),
|
||||||
|
state: ConsumerState {
|
||||||
|
position: 0,
|
||||||
|
line: 0,
|
||||||
|
absolute_position: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ParserError {
|
||||||
|
message: String,
|
||||||
|
absolute_position: u64,
|
||||||
|
position: usize,
|
||||||
|
line: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ParserError {
|
||||||
|
fn from_consumer(consumer: &Consumer, error: &str) -> ParserError {
|
||||||
|
ParserError {
|
||||||
|
message: error.to_string(),
|
||||||
|
absolute_position: consumer.state.absolute_position,
|
||||||
|
position: consumer.state.position,
|
||||||
|
line: consumer.state.line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse(contents: String) -> Result<Graph, ParserError> {
|
||||||
|
let mut nodes: Vec<Node>;
|
||||||
|
let mut node_names: HashMap<String, u32>;
|
||||||
|
let mut state = State::Default;
|
||||||
|
let mut consumer = Consumer::new(contents);
|
||||||
|
|
||||||
|
while consumer.consume_line() {
|
||||||
|
while let Some(chxr) = consumer.consume_from_line() {
|
||||||
|
match state {
|
||||||
|
State::Default => {
|
||||||
|
match chxr {
|
||||||
|
'\\' => {
|
||||||
|
if consumer.peek_on_line() == Some('(') {
|
||||||
|
consumer.consume_from_line();
|
||||||
|
state = State::AnonymousNode;
|
||||||
|
} else {
|
||||||
|
return Err(ParserError::from_consumer(&consumer, "Found \\ without valid next character"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
'a'..'z' | 'A'..'Z' => {
|
||||||
|
state = State::Node(chxr.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("{:?}", lines);
|
||||||
|
|
||||||
|
Ok(Graph::default())
|
||||||
|
}
|
Loading…
Reference in a new issue