Skip to content

Instantly share code, notes, and snippets.

@bartolsthoorn
Last active August 29, 2015 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bartolsthoorn/02b85847c4c093953a04 to your computer and use it in GitHub Desktop.
Save bartolsthoorn/02b85847c4c093953a04 to your computer and use it in GitHub Desktop.
// A web structure adventure
#![license = "MIT"]
// Disable warning about parser imports
#![allow(dead_code)]
#![allow(unused_imports)]
// Enable peg_syntax_ext phase
#![feature(phase)]
extern crate simhash;
#[phase(plugin)]
extern crate peg_syntax_ext;
use parser::{name, start_tag, end_tag, element, text};
enum Node {
Text(String),
Element(String, Vec<Node>)
}
impl Node {
fn stringify(&self) -> String {
match *self {
Text(ref s) => s.clone(),
Element(ref name, ref nodes) =>
"<".to_string() + name.clone() + ">".to_string() +
nodes.iter().map(|node| node.stringify()).collect::<Vec<String>>().concat() +
"</".to_string() + name.clone() + ">".to_string()
}
}
}
peg! parser(r#"
#[pub]
name -> String
= [a-zA-Z0-9_]+ { match_str.to_string() }
#[pub]
start_tag -> String
= "<" n:name ">" { n }
#[pub]
end_tag -> String
= "</" n:name ">" { n }
#[pub]
element -> super::Node
= s:start_tag c:content e:end_tag { super::Element(s, c) }
#[pub]
content -> Vec<super::Node>
= (element / text)*
#[pub]
text -> super::Node
= (!start_tag !end_tag .)+ { super::Text(match_str.to_string()) }
"#)
#[test]
fn test_parser() {
assert!(name("div").is_ok());
assert!(name("di'v").is_err());
assert_eq!(start_tag("<div>"), Ok("div".to_string()));
assert!(start_tag("</div>").is_err());
assert_eq!(end_tag("</div>"), Ok("div".to_string()));
assert!(end_tag("<div>").is_err());
assert!(text("lorem ipsum").is_ok());
assert!(text("lorem ipsum<div>").is_err());
let result = element("<div><em>x</em></div>");
assert!(result.is_ok());
let node = result.unwrap();
assert_eq!(
match node {
Text(_) => fail!(),
Element(name, _) => name
}, "div".to_string());
assert_eq!(
match node {
Text(_) => fail!(),
Element(_, nodes) => nodes[0].stringify()
}, "<em>x</em>".to_string());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment