extern crate pest; use crate::Value::{QmlIdent, QmlNumber, QmlString}; use pest::iterators::Pairs; use pest::Parser; use std::collections::HashMap; use std::fs::read_to_string; #[derive(Parser)] #[grammar = "../pest/qml.pest"] struct QmlParser; #[derive(Debug, Clone)] pub enum Value { QmlString(String), QmlNumber(f64), QmlIdent(String), } #[derive(Debug, Clone)] pub struct QML { pub imports: Vec, pub properties: HashMap, pub children: Vec<(String, QML)>, } pub fn parse_qml(path: &str) -> QML { let qml_file = read_to_string(path).unwrap(); let qml_tokens = QmlParser::parse(Rule::qml, qml_file.as_str()).unwrap_or_else(|e| panic!("{}", e)); parse(qml_tokens) } fn parse(qml: Pairs) -> QML { let mut qmldoc = QML { imports: vec![], properties: Default::default(), children: vec![], }; for pair in qml { // println!("Rule {:?} Str {}", pair.as_rule(), pair.as_str()); match pair.as_rule() { Rule::import => { let mut tokens = pair.into_inner(); let import = tokens.next().unwrap().as_str(); println!("Found new Import {} ", import); qmldoc.imports.push(String::from(import)); } Rule::body => { let mut tokens = pair.into_inner(); let ident = tokens.next().unwrap().as_str(); println!("Found new Body: {} ", ident); qmldoc.children.push((String::from(ident), parse(tokens.into_iter()))); } Rule::property => { let mut tokens = pair.into_inner(); let ident = tokens.next().unwrap().as_str(); let value = tokens.next().unwrap(); // let value = tokens.next().unwrap().as_str(); match value.as_rule() { Rule::number => { let num: f64 = value.as_str().parse().unwrap(); println!("Found new Property: {} {:?}", ident, num); qmldoc.properties.insert(String::from(ident), QmlNumber(num)); } Rule::string => { println!("Found new Property: {} {}", ident, value.as_str()); qmldoc.properties.insert(String::from(ident), QmlString(String::from(value.into_inner().next().unwrap().as_str()))); } Rule::ident => { println!("Found new Property: {} {}", ident, value.as_str()); qmldoc.properties.insert(String::from(ident), QmlIdent(String::from(value.as_str()))); } _ => { println!("Found new Property: {} {:?}", ident, value.as_rule()); let value = String::from(value.as_str()) + tokens.concat().as_ref(); println!("Found new Property: {} {}", ident, value.as_str()); qmldoc.properties.insert(String::from(ident), QmlString(String::from(value.clone().trim()))); } } } Rule::function => { let mut tokens = pair.into_inner(); let ident = tokens.next().unwrap().as_str(); let value = tokens.concat(); qmldoc.properties.insert(String::from(ident), QmlString(String::from(value.clone().trim()))); } _ => return parse(pair.into_inner()), } } qmldoc }