Fold graph::Graph into gg::Graph, add TokenKind::End to lexer
This commit is contained in:
parent
6b5f2d7e82
commit
e06b20b604
@ -1,10 +1,39 @@
|
||||
use std::hash::Hash;
|
||||
use im_rc::{HashSet};
|
||||
|
||||
pub mod lexer;
|
||||
|
||||
use super::graph::Graph;
|
||||
#[derive(Clone, Eq, Hash, PartialEq)]
|
||||
pub struct OpenEdge(Value, Value); // edge, src
|
||||
|
||||
#[derive(Clone, Eq, Hash, PartialEq, Debug)]
|
||||
pub enum Value<'a>{
|
||||
Name(&'a str),
|
||||
#[derive(Clone, Eq, Hash, PartialEq)]
|
||||
pub enum Value{
|
||||
Name(String),
|
||||
Number(i64),
|
||||
Graph(&'a Graph<Value<'a>, Value<'a>>),
|
||||
Tuple(Vec<OpenEdge>),
|
||||
Graph(Graph),
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, Hash, PartialEq)]
|
||||
struct Edge<V> {
|
||||
dst_val: V,
|
||||
src_val: V,
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, Hash, PartialEq)]
|
||||
pub struct Graph {
|
||||
edges: HashSet<(Value, OpenEdge)>, // dst, src
|
||||
}
|
||||
|
||||
impl Graph {
|
||||
|
||||
pub fn new() -> Graph {
|
||||
Graph{edges: HashSet::new()}
|
||||
}
|
||||
|
||||
pub fn with(&self, dst_val: Value, src_edge: OpenEdge) -> Self {
|
||||
Graph{
|
||||
edges: self.edges.update((dst_val, src_edge)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,27 @@
|
||||
<name> ::= <letter> | <name-tail>
|
||||
<name-charset> ::= <letter> | <number> | <mark>
|
||||
<name-tail> ::= <name-chareset> <name-tail> | ""
|
||||
|
||||
<number> ::= "-" <ascii-number> <number-tail>
|
||||
| <ascii-number> <number-tail>
|
||||
<number-tail> ::= <ascii-number> <number-tail> | ""
|
||||
|
||||
<value> ::= <name> | <number> | <tuple> | <graph>
|
||||
|
||||
<tuple> ::= "(" <tuple-open-edge>
|
||||
<tuple-open-edge> ::= ")" | <tuple-open-edge-incomplete>
|
||||
<tuple-open-edge-incomplete> ::= <value> ")"
|
||||
| <value> "," <tuple-open-edge>
|
||||
| <value> "<" <tuple-open-edge-incomplete>
|
||||
<tuple> ::= "(" <tuple-edge>
|
||||
<tuple-edge> ::= ")" | <tuple-edge-incomplete>
|
||||
<tuple-edge-incomplete> ::= <value> ")"
|
||||
| <value> "," <tuple-edge>
|
||||
| <value> "<" <tuple-edge-incomplete>
|
||||
|
||||
<graph> ::= "{" <graph-branch>
|
||||
<graph-branch> ::= "}" | <name> "<" <graph-open-edge-incomplete>
|
||||
<graph-open-edge-incomplete> ::= <value> "}"
|
||||
<graph-branch> ::= "}" | <name> "<" <graph-edge-incomplete>
|
||||
<graph-edge-incomplete> ::= <value> "}"
|
||||
| <value> ";" <graph-branch>
|
||||
| <value> "<" <graph-open-edge-incomplete>
|
||||
| <value> "<" <graph-edge-incomplete>
|
||||
|
||||
<outer-graph> ::= <outer-graph-branch>
|
||||
<outer-graph-branch> ::= <eof> | <name> "<" <outer-graph-open-edge-incomplete>
|
||||
<outer-graph-open-edge-incomplete> ::= <value> <eof>
|
||||
<outer-graph-branch> ::= <end> | <name> "<" <outer-graph-edge-incomplete>
|
||||
<outer-graph-edge-incomplete> ::= <value> <end>
|
||||
| <value> ";" <outer-graph-branch>
|
||||
| <value> "<" <outer-graph-open-edge-incomplete>
|
||||
| <value> "<" <outer-graph-edge-incomplete>
|
||||
|
@ -33,6 +33,7 @@ pub enum TokenKind {
|
||||
Name,
|
||||
Number,
|
||||
Punctuation,
|
||||
End,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@ -105,7 +106,7 @@ impl<R: Read> Lexer<R>{
|
||||
&mut self,
|
||||
kind: TokenKind,
|
||||
pred: impl Fn(char) -> bool,
|
||||
) -> Result<Option<(Token, Location)>, Error> {
|
||||
) -> Result<(Token, Location), Error> {
|
||||
|
||||
let loc = self.next_loc;
|
||||
self.buf.truncate(0);
|
||||
@ -115,8 +116,9 @@ impl<R: Read> Lexer<R>{
|
||||
let (c, ok) = self.peek_a_bool()?;
|
||||
|
||||
if !ok || !pred(c) {
|
||||
return Ok(Some(
|
||||
(Token{kind: kind, value: self.buf.clone()}, loc)
|
||||
return Ok((
|
||||
Token{kind: kind, value: self.buf.clone()},
|
||||
loc
|
||||
))
|
||||
}
|
||||
|
||||
@ -129,13 +131,16 @@ impl<R: Read> Lexer<R>{
|
||||
c == '-' || ('0' <= c && c <= '9')
|
||||
}
|
||||
|
||||
pub fn next(&mut self) -> Result<Option<(Token, Location)>, Error> {
|
||||
pub fn next(&mut self) -> Result<(Token, Location), Error> {
|
||||
|
||||
loop {
|
||||
|
||||
let (c, ok) = self.peek_a_bool()?;
|
||||
if !ok {
|
||||
return Ok(None);
|
||||
return Ok((
|
||||
Token{kind: TokenKind::End, value: String::new()},
|
||||
self.next_loc,
|
||||
));
|
||||
|
||||
} else if c == '*' {
|
||||
self.discard_while(|c| c != '\n')?;
|
||||
@ -155,15 +160,16 @@ impl<R: Read> Lexer<R>{
|
||||
let loc = self.next_loc;
|
||||
self.discard();
|
||||
|
||||
return Ok(Some(
|
||||
(Token{kind: TokenKind::Punctuation, value: c.to_string()}, loc)
|
||||
return Ok((
|
||||
Token{kind: TokenKind::Punctuation, value: c.to_string()},
|
||||
loc,
|
||||
))
|
||||
|
||||
} else if c.is_ascii_whitespace() {
|
||||
self.discard_while(|c| c.is_ascii_whitespace())?;
|
||||
|
||||
} else {
|
||||
return Err(Error::Tokenizing("unexpected character", self.next_loc));
|
||||
return Err(Error::Tokenizing("invalid character", self.next_loc));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -192,26 +198,34 @@ mod tests {
|
||||
let tests = vec![
|
||||
Test{
|
||||
input: "",
|
||||
exp: vec![],
|
||||
exp: vec![
|
||||
tok(TokenKind::End, "", 0, 0),
|
||||
],
|
||||
},
|
||||
Test{
|
||||
input: "* foo",
|
||||
exp: vec![],
|
||||
exp: vec![
|
||||
tok(TokenKind::End, "", 0, 5),
|
||||
],
|
||||
},
|
||||
Test{
|
||||
input: "* foo\n",
|
||||
exp: vec![],
|
||||
},
|
||||
Test{
|
||||
input: "* foo\nbar",
|
||||
exp: vec![
|
||||
tok(TokenKind::Name, "bar", 1, 0),
|
||||
tok(TokenKind::End, "", 1, 0),
|
||||
],
|
||||
},
|
||||
Test{
|
||||
input: "* foo\nbar",
|
||||
exp: vec![
|
||||
tok(TokenKind::Name, "bar", 1, 0),
|
||||
tok(TokenKind::End, "", 1, 3),
|
||||
],
|
||||
},
|
||||
Test{
|
||||
input: "* foo\nbar ",
|
||||
exp: vec![
|
||||
tok(TokenKind::Name, "bar", 1, 0),
|
||||
tok(TokenKind::End, "", 1, 4),
|
||||
],
|
||||
},
|
||||
Test{
|
||||
@ -222,6 +236,7 @@ mod tests {
|
||||
tok(TokenKind::Name, "f-o", 1, 0),
|
||||
tok(TokenKind::Name, "f0O", 1, 4),
|
||||
tok(TokenKind::Name, "Foo", 1, 8),
|
||||
tok(TokenKind::End, "", 1, 11),
|
||||
],
|
||||
},
|
||||
Test{
|
||||
@ -230,6 +245,7 @@ mod tests {
|
||||
tok(TokenKind::Number, "1", 0, 0),
|
||||
tok(TokenKind::Number, "100", 0, 2),
|
||||
tok(TokenKind::Number, "-100", 0, 6),
|
||||
tok(TokenKind::End, "", 0, 10),
|
||||
],
|
||||
},
|
||||
Test{
|
||||
@ -242,6 +258,7 @@ mod tests {
|
||||
tok(TokenKind::Number, "-3", 0, 4),
|
||||
tok(TokenKind::Punctuation, "(", 0, 7),
|
||||
tok(TokenKind::Punctuation, ")", 0, 8),
|
||||
tok(TokenKind::End, "", 0, 9),
|
||||
],
|
||||
},
|
||||
];
|
||||
@ -253,9 +270,12 @@ mod tests {
|
||||
let mut res = Vec::new();
|
||||
|
||||
loop {
|
||||
if let Some(token) = l.next().expect("no errors expected") {
|
||||
res.push(token);
|
||||
} else {
|
||||
let (token, loc) = l.next().expect("no errors expected");
|
||||
let is_end = token.kind == TokenKind::End;
|
||||
|
||||
res.push((token, loc));
|
||||
|
||||
if is_end {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1,66 +0,0 @@
|
||||
use std::hash::Hash;
|
||||
use im_rc::{HashMap,HashSet};
|
||||
|
||||
#[derive(Clone, Eq, Hash, PartialEq, Debug)]
|
||||
pub enum OpenEdgeSource<E, V>{
|
||||
Value(V),
|
||||
Tuple(Vec<OpenEdge<E, V>>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, Hash, PartialEq, Debug)]
|
||||
pub struct OpenEdge<E, V>{
|
||||
value: E,
|
||||
source: OpenEdgeSource<E, V>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, Hash, PartialEq, Debug)]
|
||||
pub struct Graph<E, V>
|
||||
where
|
||||
E: Hash + Eq + Clone,
|
||||
V: Hash + Eq + Clone,
|
||||
{
|
||||
roots: HashMap<V, HashSet<OpenEdge<E, V>>>,
|
||||
}
|
||||
|
||||
impl<E, V> Graph<E, V>
|
||||
where
|
||||
E: Hash + Eq + Clone,
|
||||
V: Hash + Eq + Clone,
|
||||
{
|
||||
|
||||
pub fn new() -> Graph<E, V> {
|
||||
Graph{roots: HashMap::new()}
|
||||
}
|
||||
|
||||
pub fn from_value(edge_value: E, source_value: V) -> OpenEdge<E, V> {
|
||||
OpenEdge{
|
||||
value: edge_value,
|
||||
source: OpenEdgeSource::Value(source_value),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_tuple(edge_value: E, source_tuple: Vec<OpenEdge<E, V>>) -> OpenEdge<E, V> {
|
||||
OpenEdge{
|
||||
value: edge_value,
|
||||
source: OpenEdgeSource::Tuple(source_tuple),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with(&self, root_value: V, open_edge: OpenEdge<E, V>) -> Self {
|
||||
|
||||
let new_roots = self.roots.alter(
|
||||
|set_option: Option<HashSet<OpenEdge<E, V>>>| -> Option<HashSet<OpenEdge<E, V>>> {
|
||||
match set_option {
|
||||
None => Some(HashSet::unit(open_edge)),
|
||||
Some(set) => Some(set.update(open_edge)),
|
||||
}
|
||||
},
|
||||
root_value,
|
||||
);
|
||||
|
||||
Graph{
|
||||
roots: new_roots,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1 @@
|
||||
pub mod graph;
|
||||
pub mod gg;
|
||||
|
@ -1,22 +1,2 @@
|
||||
use ginger::graph::Graph;
|
||||
|
||||
fn main() {
|
||||
|
||||
let g = Graph::new().
|
||||
with("foo", Graph::from_value(1, "bar"));
|
||||
|
||||
let g1 = g.
|
||||
with("foo", Graph::from_value(1, "bar")).
|
||||
with("foo", Graph::from_value(2, "baz"));
|
||||
|
||||
let g2 = g.
|
||||
with("bar", Graph::from_tuple(100, vec![
|
||||
Graph::from_value(20, "a"),
|
||||
Graph::from_value(40, "b"),
|
||||
Graph::from_value(60, "c"),
|
||||
]));
|
||||
|
||||
dbg!(g1 == g2);
|
||||
dbg!(&g1);
|
||||
dbg!(&g2);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user