我工作的一個模板引擎,其中的一些語法可能是這樣的:匹配模板過濾器表達式與NOM
{{ somevar|filter }}
在地方的somevar
可以是任意「表達」,這是說,要麼是變量名稱,如somevar
,要麼是嵌套的過濾器表達式(如{{ somevar|filter|anotherfilter }}
)。我試圖用Rust的nom分析器組合庫來解析這個問題,但是到目前爲止還沒有得到它的工作。
這裏的解析器,我拿出這麼遠:
#[macro_use]
extern crate nom;
use std::str;
#[derive(Debug)]
pub enum Expr<'a> {
Var(&'a [u8]),
Filter(&'a str, Box<Expr<'a>>),
}
#[derive(Debug)]
pub enum Node<'a> {
Lit(&'a [u8]),
Expr(Expr<'a>),
}
named!(expr_var<Expr>, dbg_dmp!(map!(nom::alphanumeric, Expr::Var)));
named!(expr_filter<Expr>,
dbg_dmp!(do_parse!(
val: any_expr >>
tag_s!("|") >>
name: map_res!(nom::alphanumeric, str::from_utf8) >>
(Expr::Filter(name, Box::new(val)))
))
);
named!(any_expr<Expr>, dbg_dmp!(ws!(
alt_complete!(
expr_filter |
expr_var
))));
named!(expr_node<Node>, dbg_dmp!(map!(
delimited!(tag_s!("{{"), any_expr, tag_s!("}}")),
Node::Expr)));
named!(parse_template< Vec<Node> >, many1!(expr_node));
隨着playground。當前版本通過堆棧溢出發生混亂。我可以通過逆轉any_expr
中的expr_var | expr_filter
訂單來解決此問題,但後來我恢復了與之前基本相同的錯誤。
我強烈建議在嘗試編寫代碼之前寫出實際的語法。解析工具的一個重點是它們幫助將語法映射到代碼。 – Shepmaster
我也會推薦1)做一個正確的http://stackoverflow.com/help/mcve(也許用http://play.rust-lang.org/)。另見http://www.sscce.org/。 2)提供一種單元測試,作爲解析語法的例子。 – ArtemGr