rqml/src/parser.rs

93 lines
3.5 KiB
Rust

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<String>,
pub properties: HashMap<String, Value>,
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<Rule>) -> 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
}