Compare commits

..

2 commits

4 changed files with 44 additions and 2 deletions

View file

@ -1,6 +1,6 @@
[package] [package]
name = "purrchance" name = "purrchance"
version = "0.1.0" version = "0.2.0"
authors = ["xenofem <xenofem@xeno.science>"] authors = ["xenofem <xenofem@xeno.science>"]
description = "An unofficial Rust implementation of the Perchance grammar engine" description = "An unofficial Rust implementation of the Perchance grammar engine"
repository = "https://git.xeno.science/xenofem/purrchance" repository = "https://git.xeno.science/xenofem/purrchance"

25
src/bin/purrchance.rs Normal file
View file

@ -0,0 +1,25 @@
use purrchance::*;
use purrchance::parser::*;
use std::env;
use std::fs::read_to_string;
use std::process::exit;
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
eprintln!("too few arguments!");
exit(1);
}
let raw_grammar = read_to_string(&args[1]).unwrap();
let grammar = load_grammar(&raw_grammar);
if args.len() < 3 {
eprintln!("{:?}", grammar);
exit(0);
}
let sym = Symbol::NonTerminal(args[2].clone());
println!("{}", sym.eval(&grammar).unwrap());
}

View file

@ -10,6 +10,7 @@ pub trait Purrchance {
fn eval(&self, g: &Grammar) -> Option<String>; fn eval(&self, g: &Grammar) -> Option<String>;
} }
#[derive(Debug)]
pub enum Symbol { pub enum Symbol {
Terminal(String), Terminal(String),
NonTerminal(String), NonTerminal(String),
@ -24,6 +25,7 @@ impl Purrchance for Symbol {
} }
} }
#[derive(Debug)]
pub struct Expr(Vec<Symbol>); pub struct Expr(Vec<Symbol>);
impl Purrchance for Expr { impl Purrchance for Expr {
@ -32,6 +34,7 @@ impl Purrchance for Expr {
} }
} }
#[derive(Debug)]
pub struct List(Vec<(Expr, f64)>); pub struct List(Vec<(Expr, f64)>);
impl Purrchance for List { impl Purrchance for List {
@ -40,6 +43,7 @@ impl Purrchance for List {
} }
} }
#[derive(Debug)]
pub struct Grammar(HashMap<String,List>); pub struct Grammar(HashMap<String,List>);
#[cfg(test)] #[cfg(test)]
@ -142,6 +146,19 @@ test
test test
foo ^1000000 foo ^1000000
bar ^1/1000000 bar ^1/1000000
");
let nt = Symbol::NonTerminal(String::from("test"));
assert_eq!(nt.eval(&g), Some(String::from("foo")));
}
#[test]
fn eval_loaded_grammar_multiple_lists() {
let g = load_grammar("
test
[test1]
test1
foo
"); ");
let nt = Symbol::NonTerminal(String::from("test")); let nt = Symbol::NonTerminal(String::from("test"));
assert_eq!(nt.eval(&g), Some(String::from("foo"))); assert_eq!(nt.eval(&g), Some(String::from("foo")));

View file

@ -25,7 +25,7 @@ fn whitespace(input: &str) -> IResult<&str, ()> {
} }
fn empty_line(input: &str) -> IResult<&str, ()> { fn empty_line(input: &str) -> IResult<&str, ()> {
map(tuple((opt(comment), tag("\n"))), |_| ())(input) map(tuple((whitespace, opt(comment), tag("\n"))), |_| ())(input)
} }
pub fn take_until_any<T, Input, Error: ParseError<Input>>(tags: Vec<T>) -> impl Fn(Input) -> IResult<Input, Input, Error> pub fn take_until_any<T, Input, Error: ParseError<Input>>(tags: Vec<T>) -> impl Fn(Input) -> IResult<Input, Input, Error>