rust - 将模板过滤器表达式与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。当前版本因堆栈溢出而死机。我可以通过颠倒expr_var | expr_filter中的any_expr顺序来解决这个问题,但之后我又回到了与以前基本相同的错误。

最佳答案

我不能说我理解你的问题:没有应该解析的文本示例,也没有描述在构建解析器时遇到的问题。
不过,也许下面的例子会有帮助。一个有效的递归分析器:

#[macro_use]
extern crate nom;

use nom::alphanumeric;

type Variable = String;
type Filter = String;

named! (plain_expression (&str) -> (Variable, Filter), do_parse! (
    tag_s! ("{{") >>
    variable: alphanumeric >>
    tag_s! ("|") >>
    filter: alphanumeric >>
    tag_s! ("}}") >>
    ((variable.into(), filter.into()))));

#[derive(Debug)]
enum Expression {
    Plain(Variable, Filter),
    Recursive(Box<Expression>, Filter),
}

named! (recursive_expression (&str) -> Expression,
  alt_complete! (
    map! (plain_expression, |(v, f)| Expression::Plain (v, f)) |
    do_parse! (
      tag_s! ("{{") >>
      sub: recursive_expression >>
      tag_s! ("|") >>
      filter: alphanumeric >>
      tag_s! ("}}") >>
      (Expression::Recursive (Box::new (sub), filter.into())))));

fn main() {
    let plain = "{{var|fil}}";
    let recursive = "{{{{{{var1|fil1}}|fil2}}|fil3}}";
    // Prints: Done("", ("var", "fil")).
    println!("{:?}", plain_expression(plain));
    // Prints: Done("", Recursive(Recursive(Plain("var1", "fil1"), "fil2"), "fil3")).
    println!("{:?}", recursive_expression(recursive));
}

playground)。

本文翻译自 https://stackoverflow.com/questions/41449860/

网站遵循 CC BY-SA 4.0 协议,转载或引用请注明出处。

标签 rust parser-combinators nom


相关文章:

rust - 在实现Deref特征时无法推断生命周期参数的适当生命周期

parsing - Nom 5:多次使用另一个解析器创建一个组合器

c - 在C中使用解析器组合器的更好方法?

rust - 如何在nom中创建流解析器?

rust - 一个数组如何包含对同一对象的多个可变引用? [重复]

websocket - Rouille中websocket的CPU使用率高

rust - 如何将Rust字符转换为整数,以使“ 1”变为1?

java - Scala解析器组合器与ANTLR / Java生成的解析器?

parsing - 用nom解析驼峰字符串