如何使用PetitParser匹配dart字符串中的表达式?

时间:2013-06-22 14:22:15

标签: parsing dart petitparser

我想使用PetitParserDart来解析dart字符串中的嵌入表达式。

准备一些物品:

class User {
    String name;
}
var user1 = new User()..name="Mike";
var user2 = new User()..name="Jeff";
var user3 = new User()..name="John}}}";
var users = [user1, user2, user3];

长串:

var s = """
Hello, this is an embed dart expression below:
  ${
     users.where((u)=>u.name!='Jeff}}}}}}}}')
          .where((u) { return u.name!='{{{John'})
          .map((u)=>u.name).toList()
   }
It's very complex.
"""

您可以看到字符串中有${},其内容非常复杂。

我尝试使用这样的petitparser代码:

def("expr_in_string", string('${').ref('expr').char('}'));
def("expr", ????);

但我不知道如何定义expr规则。它可能包含{},因此我无法使用anyIn('{}').neg()

我现在该怎么办?我觉得这将是一个非常复杂的规则。

3 个答案:

答案 0 :(得分:1)

我认为如果没有或多或少完整的Dart表达式语法,你可以正确地解析所有可能的字符串。您可以编写近似值(就像在答案中所做的那样),也可以尝试使用示例附带的Dart语法的表达式。在任何一种情况下,结果语法都很复杂,因为你试图匹配的东西很复杂。

答案 1 :(得分:0)

在src / dart / grammar.dart中有一个Dart的语法,看起来它可以解析它。

答案 2 :(得分:0)

我找到了一个解决方案:确定${}内的字符串,先匹配它们。然后匹配所有{}

代码:

// whole `${...}`
def("expr", string(r"$") & ref("block_brace"));
// strings
def("dart_str_single", char("'") & (string(r"\'") | char("'").neg()).star() & char("'"));
def("dart_str_double", char('"') & (string(r'\"') | char('"').neg()).star() & char('"'));
def("dart_str_triple_single", string("'''") & string("'''").neg().star() & string("'''"));
def("dart_str_triple_double", string('"""') & string('"""').neg().star() & string('"""'));
// (...)
def("block_parenthesis", char('(') & (
    ref("dart_str_triple_single")
    | ref("dart_str_triple_double")
    | ref("dart_str_single")
    | ref("dart_str_double")
    | ref("block_parenthesis")
    | ref("block_brace")
    | char(')').neg()
).star() & char(')'));
// {...}
def("block_brace", char('{') & (
    ref("dart_str_triple_single")
    | ref("dart_str_triple_double")
    | ref("dart_str_single")
    | ref("dart_str_double")
    | ref("block_parenthesis")
    | ref("block_brace")
    | char('}').neg()
).star() & char('}'));

测试代码:

  var x4 = grammar["expr"];
  var yyy4 = x4.parse(r"""${
  users.where((u) => u.name != 'Jeff}}}}}}}}')
  .where((u) {
    return u.name != '{{{John';
  })
  .map((u) => u.name).toList()
  }""");
  print(yyy4.value);

打印:

[$, [{, [
,  ,  ,  ,  ,  ,  , u, s, e, r, s, ., w, h, e, r, e, 
[(, [[(, [u], )],  , =, >,  , u, ., n, a, m, e,  , !, =,  , 
[', [J, e, f, f, }, }, }, }, }, }, }, }], ']], )], 
,  ,  ,  ,  ,  ,  , ., w, h, e, r, e, [(, [[(, [u], )],  , [{, 
[,  ,  ,  ,  ,  ,  ,  ,  , r, e, t, u, r, n,  , u, ., n, a, m, e,  , !, =,  , 
[', [{, {, {, J, o, h, n], '], ;, ,  ,  ,  ,  ,  ,  ], }]], )], 
,  ,  ,  ,  ,  ,  , ., m, a, p, [(, [[(, [u], )],  , =, >,  , u, ., n, a, m, e], )],
 ., t, o, L, i, s, t, [(, [], )], 
,  ,  ,  ,  ,  ,  ], }]]

我认为这是正确的,但我仍然在寻找一种更简单的解决方案。


更新

它无法处理如此复杂的代码:

"""${
  users.where((u) => u.name != 'Jeff}}}}}}}}')
  .where((u) {
    return u.name != '{{{John${
  users.where((u) => u.name != 'Jeff}}}}}}}}')
  .where((u) {
    return u.name != '{{{John';
  })
  .map((u) => u.name).toList()
  }';
  })
  .map((u) => u.name).toList()
  }"""

${}内的字符串中${}。除此之外还有其他案例吗?