extern crate gramatica; use std::cmp::Ordering; use gramatica::{Associativity,EarleyKind,State,Parser,ParsingTablesTrait,AmbiguityInfo}; use std::rc::Rc; #[derive(Clone,Debug,PartialEq)] struct XMLElement{ name:String, attrs:Vec<(String,String)>, contents:Vec, } #[derive(Clone,Debug,PartialEq)] enum XMLContent{ Element(XMLElement), Data(String), } use std::io::{BufRead,Read}; fn main(){ let stdin=std::io::stdin(); let mut buf=String::new(); stdin.lock().read_to_string(&mut buf); match Parser::::parse(&buf,None) { Err(x) => println!("error parsing: {:?}" , x), Ok(x) => println!("parsed correctly: {:?}" , x), } ; } #[derive(Clone,Debug,PartialEq)] enum Token{DummyStart, Space(String),Ident(String),LitStr(String),CloseEmpty,BeginClose,Equal,LT,GT,Other(char),Document(XMLElement),Element(XMLElement),EmptyElemTag(String,Vec<(String,String)>),Attributes(Vec<(String,String)>),Attribute(String,String),STag(String,Vec<(String,String)>),ETag(String),Content(Vec),Contents(Vec),MaybeSpace,CharData(String),} impl Default for Token { fn default()->Self{Token::DummyStart} } struct ParsingTables { } impl ParsingTablesTrait for ParsingTables { fn initial()->usize { 10 } fn match_some(parser: &mut Parser) -> Option<(usize,Token)> { let source=&parser.source[parser.source_index..]; match { match parser.re("(\\s|\n)+",source) { None => None, Some((size,string)) => Some((size,string.parse::().unwrap() )) } } { None => (), Some((size,result)) => return Some((size,Token::Space(result))), }; match { match parser.re("[a-zA-Z\\x80-\\xff_][a-zA-Z0-9\\x80-\\xff_]*",source) { None => None, Some((size,string)) => Some((size,string.parse::().unwrap() )) } } { None => (), Some((size,result)) => return Some((size,Token::Ident(result))), }; { fn _match(parser:&mut Parser,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.push('\\'); r.push(c);}, } ; size += 2;}, Some(c) => {r.push(c); size += 1;}, } ;}} ret} match _match(parser,source) { None=>(), Some((size,result)) => return Some((size,Token::LitStr(result))), } }; match { match parser.re("/>",source) { None => None, Some((size,_string)) => Some((size,())) } } { None => (), Some((size,_result)) => return Some((size,Token::CloseEmpty)), }; match { match parser.re(" None, Some((size,_string)) => Some((size,())) } } { None => (), Some((size,_result)) => return Some((size,Token::BeginClose)), }; match { match parser.re("=",source) { None => None, Some((size,_string)) => Some((size,())) } } { None => (), Some((size,_result)) => return Some((size,Token::Equal)), }; match { match parser.re("<",source) { None => None, Some((size,_string)) => Some((size,())) } } { None => (), Some((size,_result)) => return Some((size,Token::LT)), }; match { match parser.re(">",source) { None => None, Some((size,_string)) => Some((size,())) } } { None => (), Some((size,_result)) => return Some((size,Token::GT)), }; match { match parser.re(".",source) { None => None, Some((size,string)) => Some((size,string.parse::().unwrap() )) } } { None => (), Some((size,result)) => return Some((size,Token::Other(result))), }; None }//match_some fn predict(parser:&mut Parser,index:usize,state_index:usize,token:usize) { match token { 10 => { parser.sets[index].predict(State{rule: 1 ,left: 10 ,right:vec![ 11 ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; 1 ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}); } 11 => { parser.sets[index].predict(State{rule: 2 ,left: 11 ,right:vec![ 12 ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; 1 ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}); parser.sets[index].predict(State{rule: 3 ,left: 11 ,right:vec![ 15,17,16 ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; 3 ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}); } 12 => { parser.sets[index].predict(State{rule: 4 ,left: 12 ,right:vec![ 7,2,13,19,4 ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; 5 ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}); } 13 => { parser.sets[index].predict(State{rule: 5 ,left: 13 ,right:vec![ ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; 0 ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}); parser.sets[index].predict(State{rule: 6 ,left: 13 ,right:vec![ 13,1,14 ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; 3 ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}); } 14 => { parser.sets[index].predict(State{rule: 7 ,left: 14 ,right:vec![ 2,6,3 ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; 3 ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}); } 15 => { parser.sets[index].predict(State{rule: 8 ,left: 15 ,right:vec![ 7,2,13,19,8 ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; 5 ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}); } 16 => { parser.sets[index].predict(State{rule: 9 ,left: 16 ,right:vec![ 5,2,19,8 ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; 4 ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}); } 17 => { parser.sets[index].predict(State{rule: 10 ,left: 17 ,right:vec![ 20 ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; 1 ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}); parser.sets[index].predict(State{rule: 11 ,left: 17 ,right:vec![ 20,18 ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; 2 ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}); } 18 => { parser.sets[index].predict(State{rule: 12 ,left: 18 ,right:vec![ ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; 0 ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}); parser.sets[index].predict(State{rule: 13 ,left: 18 ,right:vec![ 18,11,20 ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; 3 ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}); } 19 => { parser.sets[index].predict(State{rule: 14 ,left: 19 ,right:vec![ ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; 0 ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}); parser.sets[index].predict(State{rule: 15 ,left: 19 ,right:vec![ 1 ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; 1 ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}); } 20 => { parser.sets[index].predict(State{rule: 16 ,left: 20 ,right:vec![ ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; 0 ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}); parser.sets[index].predict(State{rule: 17 ,left: 20 ,right:vec![ 20,1 ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; 2 ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}); parser.sets[index].predict(State{rule: 18 ,left: 20 ,right:vec![ 20,2 ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; 2 ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}); parser.sets[index].predict(State{rule: 19 ,left: 20 ,right:vec![ 20,6 ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; 2 ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}); parser.sets[index].predict(State{rule: 20 ,left: 20 ,right:vec![ 20,9 ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; 2 ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}); } _ => panic!(""), } }//predict fn compute_value(state:&mut State) { state.computed_value = match state.rule { 0 => state.values[0].clone(), 1 => match &state.values[0] { &Token::Element(ref elem) => Token::Document(elem.clone()), _ => panic!(""), }, 2 => match &state.values[0] { &Token::EmptyElemTag(ref name,ref attrs) => Token::Element(XMLElement{name:name.clone(), attrs:attrs.clone(), contents:vec![],}), _ => panic!(""), }, 3 => match (&state.values[0],&state.values[1],&state.values[2]) { (&Token::STag(ref name,ref attrs),&Token::Content(ref content),&Token::ETag(_)) => Token::Element(XMLElement{name:name.clone(), attrs:attrs.clone(), contents:content.clone(),}), _ => panic!(""), }, 4 => match (&state.values[0],&state.values[1],&state.values[2],&state.values[3],&state.values[4]) { (&Token::LT,&Token::Ident(ref name),&Token::Attributes(ref attrs),&Token::MaybeSpace,&Token::CloseEmpty) => { let (x0,x1)=(name.clone(),attrs.clone()); Token::EmptyElemTag(x0,x1) }, _ => panic!(""), }, 5 => Token::Attributes(vec![]), 6 => match (&state.values[0],&state.values[1],&state.values[2]) { (&Token::Attributes(ref attrs),&Token::Space(_),&Token::Attribute(ref a,ref b)) => Token::Attributes({let mut new=(attrs.clone()); new.push((a.clone(),b.clone())); new}), _ => panic!(""), }, 7 => match (&state.values[0],&state.values[1],&state.values[2]) { (&Token::Ident(ref a),&Token::Equal,&Token::LitStr(ref b)) => { let (x0,x1)=(a.clone(),b.clone()); Token::Attribute(x0,x1) }, _ => panic!(""), }, 8 => match (&state.values[0],&state.values[1],&state.values[2],&state.values[3],&state.values[4]) { (&Token::LT,&Token::Ident(ref name),&Token::Attributes(ref attrs),&Token::MaybeSpace,&Token::GT) => { let (x0,x1)=(name.clone(),attrs.clone()); Token::STag(x0,x1) }, _ => panic!(""), }, 9 => match (&state.values[0],&state.values[1],&state.values[2],&state.values[3]) { (&Token::BeginClose,&Token::Ident(ref s),&Token::MaybeSpace,&Token::GT) => Token::ETag(s.clone()), _ => panic!(""), }, 10 => match &state.values[0] { &Token::CharData(ref s) => Token::Content(vec![XMLContent :: Data (s . clone ())]), _ => panic!(""), }, 11 => match (&state.values[0],&state.values[1]) { (&Token::CharData(ref s),&Token::Contents(ref list)) => Token::Content({let mut new=vec![XMLContent :: Data (s . clone ())]; new.extend(list.iter().map(|x|x.clone())); new}), _ => panic!(""), }, 12 => Token::Contents(vec![]), 13 => match (&state.values[0],&state.values[1],&state.values[2]) { (&Token::Contents(ref list),&Token::Element(ref elem),&Token::CharData(ref s)) => Token::Contents({let mut new=(list.clone()); new.push(XMLContent::Element(elem.clone())); if s != "" {new.push(XMLContent::Data(s.clone()));} new}), _ => panic!(""), }, 14 => { (); Token::MaybeSpace }, 15 => match &state.values[0] { &Token::Space(_) => { (); Token::MaybeSpace }, _ => panic!(""), }, 16 => Token::CharData(String::new()), 17 => match (&state.values[0],&state.values[1]) { (&Token::CharData(ref s),&Token::Space(ref o)) => Token::CharData(format!("{}{}" , s , o)), _ => panic!(""), }, 18 => match (&state.values[0],&state.values[1]) { (&Token::CharData(ref s),&Token::Ident(ref o)) => Token::CharData(format!("{}{}" , s , o)), _ => panic!(""), }, 19 => match (&state.values[0],&state.values[1]) { (&Token::CharData(ref s),&Token::Equal) => Token::CharData(format!("{}=" , s)), _ => panic!(""), }, 20 => match (&state.values[0],&state.values[1]) { (&Token::CharData(ref s),&Token::Other(o)) => Token::CharData(format!("{}{}" , s , o)), _ => panic!(""), }, _ => panic!(""), } }//compute_value fn table_terminal(token_index:usize)->bool { match token_index { 1|2|3|4|5|6|7|8|9 => true, 0|10|11|12|13|14|15|16|17|18|19|20 => false, _ => panic!("table_terminal"), } }//table_terminal fn table_priority(a:usize, b:usize) -> Option { match (a,b) { _ => None, } }//table_priority fn table_associativity(rule:usize) -> Option { match rule { _ => None, } }//table_associativity fn to_usize(token:&Token) -> usize { match token { &Token::DummyStart => 0, &Token::Space(_) => 1, &Token::Ident(_) => 2, &Token::LitStr(_) => 3, &Token::CloseEmpty => 4, &Token::BeginClose => 5, &Token::Equal => 6, &Token::LT => 7, &Token::GT => 8, &Token::Other(_) => 9, &Token::Document(_) => 10, &Token::Element(_) => 11, &Token::EmptyElemTag(_,_) => 12, &Token::Attributes(_) => 13, &Token::Attribute(_,_) => 14, &Token::STag(_,_) => 15, &Token::ETag(_) => 16, &Token::Content(_) => 17, &Token::Contents(_) => 18, &Token::MaybeSpace => 19, &Token::CharData(_) => 20, } }//to_usize }//impl