我想使用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()
。
我现在该怎么办?我觉得这将是一个非常复杂的规则。
答案 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()
}"""
在${}
内的字符串中${}
。除此之外还有其他案例吗?