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),
};
}