2

我想使用 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.
"""

可以看到${}字符串里面有个a,它的内容很复杂。

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

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

但我不知道如何定义expr规则。它可能包含{or },所以我不能简单地使用anyIn('{}').neg().

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

4

3 回答 3

1

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

于 2013-06-22T17:57:40.640 回答
0

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

于 2013-06-22T16:04:35.247 回答
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()
  }"""

那是${}在一个字符串里面,里面是一个${}. 除了这个还有其他情况吗?

于 2013-06-22T16:28:44.283 回答