first commit

This commit is contained in:
eater 2019-12-21 01:19:11 +01:00
commit fb89e929fe
Signed by: eater
GPG key ID: AD2560A0F84F0759
7 changed files with 204 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/target
**/*.rs.bk

6
Cargo.lock generated Normal file
View 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
View 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
View 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
View 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
View 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
View 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())
}