Under construction..
use crate::parser::{
char, choice, extract_map, flatten_map, kind, lazy, many, map, regexp, seq, token, trim,
type_map, wrap_map, Node, ParserCombinator, Type,
};
fn main() {
let space = token(" ");
let num = kind(
&type_map::<_, _, i32>(&trim(®exp(r"([1-9][0-9]*|[0-9])"), &space)),
"Num",
);
let operator = kind(&char("+-*/"), "Op");
let parenthesis = lazy();
let atom = choice(&num).or(&parenthesis);
let expression = kind(
&flatten_map(&seq(&wrap_map(&atom)).and(&flatten_map(&many(&seq(&operator).and(&atom))))),
"Expr",
);
let paren_open = trim(&token("("), &space);
let paren_close = trim(&token(")"), &space);
parenthesis.set_parser(&extract_map(
&seq(&paren_open).and(&expression).and(&paren_close),
1, // extract expression
));
let parser: ParserCombinator = ParserCombinator::new(&expression);
let target = "1 + 2 - (3 * 4) / (5)";
println!("[In]:\n{}\n", target);
println!("[Out]:\n{}\n", parser.parse(target).unwrap()); // simple print
}
[In]:
1 + 2 - (3 * 4) / (5)
[Out]:
Expr [Num I32(1), Op Str("+"), Num I32(2), Op Str("-"), Expr [Num I32(3), Op Str("*"), Num I32(4)], Op Str("/"), Expr [Num I32(5)]]
use crate::parser::{
map, regexp, seq, token, type_map, Node, ParserCombinator, Type,
};
#[derive(Clone, Debug)]
enum ExtendedType {
Complex32(i32, i32),
}
fn main() {
let num = type_map::<_, _, i32>(®exp(r"([1-9][0-9]*|[0-9])"));
let plus = token("+");
let imaginary = token("i");
let expr = seq(&num).and(&plus).and(&num).and(&imaginary);
let complex = map(
&expr,
Box::new(|node| match node.value {
Type::Arr(children) => {
let re = match children[0].value {
Type::I32(re) => re,
_ => panic!("err"),
};
let im = match children[2].value {
Type::I32(re) => re,
_ => panic!("err"),
};
Node {
value: Type::Val(ExtendedType::Complex32(re, im)),
kind: None,
}
}
_ => panic!("Error"),
}),
);
let parser: ParserCombinator<ExtendedType> = ParserCombinator::new(&complex);
let target = "100+100i";
println!("[In]:\n{}\n", target);
println!("[Out]:\n{:#?}\n", parser.parse(target).unwrap()); // detail print
}
[In]:
100+100i
[Out]:
Node {
value: Val(
Complex32(
100,
100
)
),
kind: None
}
use crate::parser::{parse, DefaultType};
let parser = // ...
let target = "target &str";
parse::<DefaultType, _>(&parser, target); // -> Result<Node, String>
or
use crate::parser::ParserCombinator;
let parser = // ...
let parser = ParserCombinator::new(&parser);
let target = "target &str";
parser.parse(target); // -> Result<Node, String>
Customize parsed data type.
use crate::parser::ParserCombinator;
#[derive(Clone, Debug)]
enum ExtendedType {
ComplexI32(i32, i32),
}
let parser = // ...
let parser: ParserCombinator<ExtendedType> = ParserCombinator::new(&parser);
#[derive(Debug, Clone)]
pub struct State<T: Clone> {
pub success: bool,
pub node: Option<Node<T>>,
pub position: usize,
}
#[derive(Debug, Clone)]
pub struct Node<T: Clone> {
pub value: Type<T>,
pub kind: Option<String>,
}
#[derive(Clone, Debug)]
pub enum Type<T: Clone> {
Str(String),
Char(char),
Isize(isize),
Usize(usize),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
U128(u128),
I16(i16),
I32(i32),
I64(i64),
I128(i128),
F32(f32),
F64(f64),
Bool(bool),
Val(T),
Arr(Vec<Node<T>>),
}
pub trait Parser<T: Clone> {
fn parse(&self, target: &str, position: usize) -> State<T>;
fn box_clone(&self) -> Box<Parser<T>>;
}
Grant label
let num = kind(&RegExp(r"([1-9][0-9]*|[0-9])"), "Num");
println!("{}", parse(&num, "100").unwrap());
// Num 100
let token = token("token");
println!("{}", parse(&token, "token").unwrap());
// token
let operator = char("+-");
println!("{}", parse(&operator, "+").unwrap());
// +
println!("{}", parse(&operator, "-").unwrap());
// -
let num = regexp(r"([1-9][0-9]*|[0-9])");
println!("{}", parse(&number, "12345").unwrap());
// 12345
let seq = seq(&token("a")).and(&token("b"));
println!("{}", parse(&seq, "ab").unwrap());
// [a, b]
let many = many(&token("a"));
println!("{}", parse(&many, "aaaaa").unwrap());
// [a, a, a, a, a]
/(option)?/;
let option = opt(&token("aaa"));
println!("{}", parse(&option, "aaa").unwrap());
// aaa
println!("{}", parse(&option, "").unwrap());
//
let choice = choice(&token("a")).or(&token("b"));
println!("{}", parse(&choice, "a").unwrap());
// a
println!("{}", parse(&choice, "b").unwrap());
// b
Lazy initialized parser. It is useful for making recursive parser.
let lazy = lazy();
// define parsers
lazy.set_parser(&parser);
let f = |node| => true
let filtered = filter(&parser, f);
map node to new node.
// map a to b
let map = map(
&token("a"),
|node| {
Node {
value: Type::Str("b".to_string()),
kind: None,
}
}
);
println!("{}", parse(&map, "a").unwrap());
// b
map str to specific type.
TypeMap(Type::Str) => Type::I32
let toI32 = type_map::<_, _, i32>(&parser);
let toI64 = type_map::<_, _, i64>(&parser);
Extract an element from elements.
ExtractMap([ a, b, c ], 1) = b
let extraction = extract(&parser, extraction_index);
Flatten elements in elements.
Flatten(
[
[a1, b1, c1, ...],
[a2, b2, c2, ...]
]
) = [a1, b1, c1, ..., a2, b2, c2, ...]
let flatten = flatten(&parser);
Wrap elements.
WrapMap([a, b, c, ...]) = [[a, b, c, ...]]
let wrap = wrap(&parser);
Unwrap element.
WrapMap([a]) = a
let unwrap = unwrap(&parser);
Triming "a" by "-" yields: "--a--" -> "a"
let trim = trim(&parser, &by);
// eg
let trim = trim(&token("a"), &token("-"));