gramatica 0.2.1

A compiler compiler for Rust implementing Earley's parser.
Documentation

extern crate gramatica;

use std::cmp::Ordering;
use gramatica::{Associativity,EarleyKind,State,Parser,ParsingTablesTrait,AmbiguityInfo};

//See https://www.json.org/

use std::rc::Rc;

//We define an auxiliar type to store JSON values
#[derive(Clone,Debug,PartialEq)]
enum JsonValue
{
	Literal(String),
	Number(f64),
	Object(Vec<(String,JsonValue)>),
	Array(Vec<JsonValue>),
	True,
	False,
	Null,
}


// ---- Start of the grammar ----
keyword_terminal!(True,"true");
keyword_terminal!(False,"false");
keyword_terminal!(Null,"null");

re_terminal!(Number(f64),"[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?");

terminal LitStr(String)
{
	//This function has limited escaping capabilities
	fn _match(parser: &mut Parser<Token,ParsingTables>, source:&str) -> Option<(usize,String)>
	{
		let mut ret=None;
		let mut characters=source.chars();
		if (characters.next())!=(Some('"'))
		{
		}
		else
		{
			let mut size=1;
			let mut r=String::from("\"");
			while true
			{
				match characters.next()
				{
					None => break,
					Some('"') =>
					{
						ret=(Some((size+1,r+&"\"")));
						break;
					},
					Some('\\') =>
					{
						match characters.next()
						{
							None => break,
							//Some(c) => r+='\\'+c,
							Some(c) =>
							{
								r.push('\\');
								r.push(c);
							}
						};
						size+=2;
					},
					Some(c) =>
					{
						//r+=&String::from(c);
						r.push(c);
						size+=1;
					},
				};
			}
		}
		ret
	}
}

re_terminal!(LBrace,"\\{");
re_terminal!(RBrace,"\\}");
re_terminal!(LBracket,"\\[");
re_terminal!(RBracket,"\\]");
re_terminal!(Comma,",");
re_terminal!(Colon,":");
re_terminal!(_,"\\s+|\n");//Otherwise skip spaces

nonterminal Object(JsonValue)
{
	(LBrace,RBrace) => JsonValue::Object(vec![]),
	(LBrace,Members(ref list),RBrace) => JsonValue::Object(list.clone()),
}

nonterminal Members(Vec<(String,JsonValue)>)
{
	(Pair(ref s,ref value)) => vec![(s.clone(),value.clone())],
	//(Pair,Comma,Members) => (),
	(Members(ref list),Comma,Pair(ref s,ref value)) =>
	{
		let mut new=(list.clone());
		new.push((s.clone(),value.clone()));
		new
	},
}

nonterminal Pair(String,JsonValue)
{
	(LitStr(ref s),Colon,Value(ref value)) => (s.clone(),value.clone()),
}

nonterminal Array(Vec<JsonValue>)
{
	(LBracket,RBracket) => vec![],
	(LBracket,Elements(ref list),RBracket) => list.clone(),
}

nonterminal Elements(Vec<JsonValue>)
{
	(Value(ref value)) => vec![value.clone()],
	//(Value,Comma,Elements) => (),
	(Elements(ref list),Comma,Value(ref value)) =>
	{
		let mut new=(list.clone());
		new.push(value.clone());
		new
	},
}

nonterminal Value(JsonValue)
{
	(LitStr(ref s)) => JsonValue::Literal(s.clone()),
	(Number(v)) => JsonValue::Number(v),
	(Object(ref value)) => value.clone(),
	(Array(ref list)) => JsonValue::Array(list.clone()),
	(True) => JsonValue::True,
	(False) => JsonValue::False,
	(Null) => JsonValue::Null,
}

// ---- End of the grammar ----

use std::io::{BufRead,Read};

//As example, we parse stdin for a JSON object
fn main()
{
	let stdin=std::io::stdin();
	let mut buf=String::new();
	stdin.lock().read_to_string(&mut buf);
	match Parser::<Token,ParsingTables>::parse(&buf,None)
	{
		Err(x) => println!("error parsing: {:?}",x),
		Ok(x) => println!("parsed correctly: {:?}",x),
	};
}