Хотя токены создаются для всего входного примера, не все обрабатываются парсером. Если вы запустите это:
String mappingExpression = "results.(\n" +
" $y := \"test\"; \n" +
" $bta := function($x) {\n" +
" (\n" +
" $count($x.billToAccounts) > 1 \n" +
" ? ($contains($join($x.billToAccounts, ','), \"super\") ? \"Super\" : \"Standard\")\n" +
" : ($contains($x.billToAccounts[0], \"super\") ? \"Super\" : \"Standard\") \n" +
" )\n" +
" };\n" +
" { \n" +
" \"users\": $filter($, function($v, $i, $a) { \n" +
" $v.status = \"PROVISIONED\" \n" +
" })\n" +
" { \n" +
" \"firstName\": $.profile.firstName, \n" +
" \"lastName\": $.profile.lastName, \n" +
" \"email\": $.profile.login, \n" +
" \"lastLogin\": $.lastLogin, \n" +
" \"id\" : $.id, \n" +
" \"userType\": $bta($.profile) \n" +
" }\n" +
" } \n" +
")";
InputStream targetStream = new ByteArrayInputStream(mappingExpression.getBytes());
MappingExpressionLexer lexer = new MappingExpressionLexer(CharStreams.fromStream(targetStream, StandardCharsets.UTF_8));
MappingExpressionParser parser = new MappingExpressionParser(new CommonTokenStream(lexer));
ParseTree tree = parser.expr();
System.out.println(tree.toStringTree(parser));
будет напечатано следующее:
(expr results)
Это означает, что expr
успешно анализирует первый вариант, ID
, а затем останавливается.
Чтобы заставить анализатор использовать все токены, введите следующее правило:
expr_to_eof
: expr EOF
;
и измените:
ParseTree tree = parser.expr();
на:
ParseTree tree = parser.expr_to_eof();
Когда вы снова запустите фрагмент кода, который я опубликовал (с прослушивателями ошибок по умолчанию!), Вы увидите некоторые сообщения об ошибках на своей консоли (т. Е. Синтаксический анализатор не успешно обработал ввод).
Если я попробуйте проанализировать ввод:
results.(
$y := "test";
$bta := function($x) {
(
$count($x.billToAccounts) > 1
? ($contains($join($x.billToAccounts, ','), "super") ? "Super" : "Standard")
: ($contains($x.billToAccounts[0], "super") ? "Super" : "Standard")
)
};
{
"users": $filter($, function($v, $i, $a) {
$v.status = "PROVISIONED"
})
}
)
, тогда у парсера с этим проблем нет. Проверка дерева:
{
"users": $filter($, function($v, $i, $a) {
$v.status = "PROVISIONED"
})
}
Я вижу, что оно распознается как OBJ_OPEN fieldList? OBJ_CLOSE
, где fieldList
определяется следующим образом:
fieldList : STRING ':' expr (',' STRING ':' expr)*;
т.е. список значений ключей, разделенных запятые. Поэтому, если вы передадите парсеру следующее:
{
"users": $filter($, function($v, $i, $a) {
$v.status = "PROVISIONED"
})
{
"firstName": $.profile.firstName,
"lastName": $.profile.lastName,
"email": $.profile.login,
"lastLogin": $.lastLogin,
"id" : $.id,
"userType": $bta($.profile)
}
}
он не сможет его правильно проанализировать, поскольку:
{
"firstName": $.profile.firstName,
"lastName": $.profile.lastName,
"email": $.profile.login,
"lastLogin": $.lastLogin,
"id" : $.id,
"userType": $bta($.profile)
}
не является ключом-значением, и между ними нет запятой.
Это правильно проанализирует это:
{
"users": $filter($, function($v, $i, $a) {
$v.status = "PROVISIONED"
}),
"some-key": {
"firstName": $.profile.firstName,
"lastName": $.profile.lastName,
"email": $.profile.login,
"lastLogin": $.lastLogin,
"id" : $.id,
"userType": $bta($.profile)
}
}
Или $filter($, function($v, $i, $a) { $v.status = "PROVISIONED" })
может иметь { "firstName": ... }
непосредственно после него, но я не могу видеть, что это верно из вашей грамматики.