const JSON = require("tree-sitter-json/grammar")
module.exports = grammar(JSON, {
name: 'apachesynapse',
extras: $ => [
$.comment,
/\s+/,
],
rules: {
document: $ => seq(
optional($.xml_declaration),
repeat($._definition),
),
_definition: $ => choice(
$.sequence_definition,
$.api_definition,
),
api_definition: $ => seq(
'',
repeat1(field('resource_definition', $.resource_definition)),
'',
),
xmlns: $ => attr('xmlns', 'http://ws.apache.org/ns/synapse'),
resource_definition: $ => seq(
'',
optional(repeat($._mediation_sequences)),
'',
),
url_mapping: $ => attr('url-mapping', $.path),
_mediation_sequences: $ => choice(
field('in', $.in_sequence),
field('out', $.out_sequence),
field('fault', $.fault_sequence),
),
in_sequence: $ => seq(
'',
optional(repeat($.mediator)),
'',
),
out_sequence: $ => seq(
'',
optional(repeat($.mediator)),
'',
),
fault_sequence: $ => seq(
'',
optional(repeat($.mediator)),
'',
),
methods: $ => repeat1(attr('methods', $.method)),
uri_template: $ => attr('uri-template', $.path),
api_attributes: $ => seq(
field('xmlns', $.xmlns),
field('name', $.name),
field('context', $.context),
optional(
repeat(
choice(
attr('hostname', $.hostname),
attr('port', $.port),
attr('version', $.version),
attr('swagger', $.swagger),
),
),
),
),
context: $ => attr('context', $.path),
path: $ => seq(
/[a-zA-Z0-9_/]+/,
),
hostname: $ => attr('hostname', $.identifier),
port: $ => attr('port', $.number),
version: $ => attr('version', $.identifier),
swagger: $ => attr('swagger', $.identifier),
sequence_definition: $ => seq(
'',
optional(repeat($.mediator)),
'',
),
_sequence_properties: $ => repeat1(
choice(
field('name', $.name),
field('xmlns', $.xmlns),
),
),
mediator: $ => choice(
$.log,
$.respond,
$.property,
$.call,
$.foreach,
$.filter,
$.aggregate,
$.send,
$.iterate,
$.sequence,
$.payload_factory,
$.header
// TODO: add more mediators
),
respond: $ => seq(
''
),
send: $ => choice(
'',
seq(
'',
field('endpoint', $.endpoint),
''
),
),
log: $ => choice(
seq(
'',
optional(repeat($.mediator)),
''
),
seq(
''
)
),
property: $ => seq(
''
),
_property_attribute: $ => choice(
attr('scope', choice(
'default',
'axis2',
'axis2-client',
'operation',
'transport',
'registry',
'synapse',
'system',
'env',
'file'
)),
attr('action', choice(
'set',
'remove',
)),
choice(
field('value', $.value),
field('expression', $.expression),
),
attr('type', choice(
'STRING',
'INTEGER',
'BOOLEAN',
'DOUBLE',
'FLOAT',
'LONG',
'SHORT',
'OM',
)),
attr('pattern', $.regex),
attr('group', $.number),
),
call: $ => seq(
'',
choice(
field('endpoint', $.endpoint),
//endpoint reference
field('endpoint_reference', $.endpoint_reference),
),
''
),
foreach: $ => seq(
'',
field('sequence', $.sequence),
''
),
filter: $ => seq(
'',
field('then', $.then),
optional(field('else', $.else)),
''
),
aggregate: $ => seq(
choice(
'',
seq(
'',
),
),
optional(field('correlateOn', $.correlateOn)),
optional(field('complete_condition', $.complete_condition)),
optional(field('on_complete', $.on_complete)),
''
),
iterate: $ => seq(
'',
field('target', $.target),
''
),
payload_factory: $ => seq(
'',
field('format', $.format),
field('args', $.args),
''
),
//
header: $ => seq(
''
),
header_scope: $ => attr('scope', choice(
'default',
'transport',
)),
header_action: $ => attr('action', choice(
'set',
'remove',
)),
media_type: $ => attr('media-type', choice(
'xml',
'json',
)),
format: $ => seq(
'',
field('value', $._value),
''
),
_value: (_, previous) => choice(
previous,
),
args: $ => choice(
'',
seq(
'',
optional(repeat(
seq(
''
),
)),
'',
),
),
arg: $ => seq(
optional(field('evaluator', $.evaluator)),
choice(
field('expression', $.expression),
field('value', $.value),
),
),
evaluator: $ => attr('evaluator', choice(
'xml',
'json',
)),
sequential: $ => attr('sequential', $.boolean),
continueParent: $ => attr('continueParent', $.boolean),
preservePayload: $ => attr('preservePayload', $.boolean),
attachPath: $ => attr('attachPath', choice(
$.xpath,
$.json_eval,
)),
sequence: $ => choice(
seq(
'',
optional(repeat($.mediator)),
''
),
seq(
'',
),
),
target: $ => seq(
'',
field('sequence', $.sequence),
''
),
correlateOn: $ => seq(
''
),
complete_condition: $ => seq(
'',
optional(field('message_count', $.message_count)),
''
),
on_complete: $ => seq(
'',
optional(repeat($.mediator)),
''
),
message_count: $ => seq(
''
),
min: $ => attr('min', $.number),
max: $ => attr('max', $.number),
key: $ => attr('key', $.identifier),
then: $ => seq(
'',
optional(repeat($.mediator)),
''
),
else: $ => seq(
'',
optional(repeat($.mediator)),
''
),
source: $ => seq(
attr('source', choice(
$.json_eval,
$.xpath,
)),
field('regex', $.regex),
),
regex: $ => attr('regex', $.expression_string),
endpoint: $ => seq(
'',
field('endpoint_type', $._endpoint_type),
''
),
_endpoint_type: $ => choice(
$.http_endpoint,
//TODO: add more endpoint types
),
http_endpoint: $ => seq(
'',
repeat($.endpoint_error_property),
''
),
_endpoint_attribute: $ => choice(
attr('uri-template', $.identifier),
attr('method', $.method),
),
method: $ =>
choice(
'GET',
'POST',
'PUT',
'DELETE',
'HEAD',
'OPTIONS',
'PATCH',
'get',
'post',
'put',
'delete',
'head',
'options',
'patch',
),
_endpoint_property: $ => choice(
//TODO: add more endpoint properties
),
endpoint_error_property: $ => choice(
$.timeout,
$.suspend_on_failure,
$.mark_for_suspending,
),
timeout: $ => seq(
'',
repeat($._timeout_property),
''
),
mark_for_suspending: $ => seq(
'',
repeat($._mark_for_suspending_property),
''
),
_mark_for_suspending_property: $ => choice(
$.error_codes,
$.retries_before_suspending,
$.retry_delay,
),
retries_before_suspending: $ => seq(
'',
field('number', $.number),
''
),
retry_delay: $ => seq(
'',
field('number', $.number),
''
),
suspend_on_failure: $ => seq(
'',
repeat($._suspend_on_failure_property),
''
),
_suspend_on_failure_property: $ => choice(
$.initial_duration,
$.progression_factor,
$.maximum_duration,
$.error_codes,
),
initial_duration: $ => seq(
'',
field('number', $.number),
''
),
progression_factor: $ => seq(
'',
field('number', $.number),
''
),
maximum_duration: $ => seq(
'',
field('number', $.number),
''
),
error_codes: $ => seq(
'',
sepBy1(',', $.number),
''
),
_timeout_property: $ => choice(
$.duration,
$.response_action,
),
duration: $ => seq(
'',
field('number', $.number),
''
),
response_action: $ => seq(
'',
choice(
'never',
'discard',
'fault',
),
''
),
endpoint_reference: $ => seq(
''
),
blocking: $ =>
attr(
'blocking',
choice(
'true',
'false',
),
),
value: $ => attr('value', /[^"]*/),
expression: $ => seq(
attr('expression', choice(
$.xpath,
$.json_eval,
$.json_path,
))
),
json_eval: $ => seq(
'json-eval(',
$.json_path,
')'
),
name: $ => seq(
attr('name', $.identifier)
),
id: $ => seq(
attr('id', $.identifier)
),
level: $ => seq(
'level',
'=',
'"',
choice(
'full',
'simple',
'custom',
'headers',
),
'"'
),
identifier: $ => /[a-zA-Z_][a-zA-Z0-9_.]*/,
number: $ => choice(
$._float,
$._unsigned_int,
$._int,
),
_float: $ => /[0-9]+\.[0-9]+/,
_unsigned_int: $ => /[0-9]+/,
_int: $ => /-[0-9]+/,
boolean: $ => choice(
'true',
'false',
),
expression_string: $ => /[^"]*/,
// xml declaration
xml_declaration: $ => seq(
''
),
version_info: $ => seq(
'version',
'=',
$.version_number
),
version_number: $ => /"1\.[0-9]+"/,
encoding_declaration: $ => seq(
'encoding',
'=',
$.encoding
),
encoding: $ => /"UTF-8"/,
comment: $ => token(seq('')),
// xpath scrappy implementation
xpath: $ => seq(
repeat1(
choice(
$._xpath_node,
$._xpath_selectors,
$._xPath_extension_functions,
choice(
$._xpath_function,
seq(
'fn:',
$._xpath_function,
),
),
$._xpath_string,
$.string_literal,
),
)
),
_xpath_node: $ => /[a-zA-Z_][a-zA-Z0-9_]*/,
_xpath_selectors: $ => choice(
'/',
'//',
'..',
'.',
'@',
),
_xPath_extension_functions: $ => choice(
$.base64_encode,
$.base64_decode,
$.get_property,
$.synapse_xpath_property,
),
_xpath_function: $ => choice(
$.boolean_function,
$.ceiling_function,
$.choose_function,
$.concat_function,
$.contains_function,
$.count_function,
$.current_function,
$.document_function,
$.element_available_function,
$.false_function,
$.floor_function,
$.format_number_function,
$.function_available_function,
$.generate_id_function,
$.id_function,
$.key_function,
$.lang_function,
$.last_function,
$.local_name_function,
$.name_function,
$.namespace_uri_function,
$.normalize_space_function,
$.not_function,
$.number_function,
$.position_function,
$.round_function,
$.starts_with_function,
$.string_function,
$.string_length_function,
$.substring_function,
$.substring_after_function,
$.substring_before_function,
$.sum_function,
$.system_property_function,
$.translate_function,
$.true_function,
$.unparsed_entity_url_function,
),
boolean_function: $ => xPathFunction('boolean', $.xpath),
ceiling_function: $ => xPathFunction('ceiling', $.xpath),
choose_function: $ => xPathFunction('choose', $.xpath),
concat_function: $ => xPathFunction('concat', sepBy1(',', $.xpath)),
contains_function: $ => xPathFunction('contains', $.xpath),
count_function: $ => xPathFunction('count', $.xpath),
current_function: $ => xPathFunction('current', $.xpath),
document_function: $ => xPathFunction('document', $.xpath),
element_available_function: $ => xPathFunction('element-available', $.xpath),
false_function: $ => xPathFunction('false', $.xpath),
floor_function: $ => xPathFunction('floor', $.xpath),
format_number_function: $ => xPathFunction('format-number', $.xpath),
function_available_function: $ => xPathFunction('function-available', $.xpath),
generate_id_function: $ => xPathFunction('generate-id', $.xpath),
id_function: $ => xPathFunction('id', $.xpath),
key_function: $ => xPathFunction('key', $.xpath),
lang_function: $ => xPathFunction('lang', $.xpath),
last_function: $ => xPathFunction('last', $.xpath),
local_name_function: $ => xPathFunction('local-name', $.xpath),
name_function: $ => xPathFunction('name', $.xpath),
namespace_uri_function: $ => xPathFunction('namespace-uri', $.xpath),
normalize_space_function: $ => xPathFunction('normalize-space', $.xpath),
not_function: $ => xPathFunction('not', $.xpath),
number_function: $ => xPathFunction('number', $.xpath),
position_function: $ => xPathFunction('position', $.xpath),
round_function: $ => xPathFunction('round', $.xpath),
starts_with_function: $ => xPathFunction('starts-with', $.xpath),
string_function: $ => xPathFunction('string', $.xpath),
string_length_function: $ => xPathFunction('string-length', $.xpath),
substring_function: $ => xPathFunction('substring', $.xpath),
substring_after_function: $ => xPathFunction('substring-after', $.xpath),
substring_before_function: $ => xPathFunction('substring-before', $.xpath),
sum_function: $ => xPathFunction('sum', $.xpath),
system_property_function: $ => xPathFunction('system-property', $.xpath),
translate_function: $ => xPathFunction('translate', $.xpath),
true_function: $ => xPathFunction('true', $.xpath),
unparsed_entity_url_function: $ => xPathFunction('unparsed-entity-url', $.xpath),
base64_encode: $ => xPathFunction('base64Encode', $.xpath),
base64_decode: $ => xPathFunction('base64Decode', $.xpath),
get_property: $ => seq(
'get-property(',
'\'',
$.identifier,
'\'',
')'
),
string_literal: $ => seq(
'\'',
/[a-zA-Z_\/][a-zA-Z0-9_.\s\/]*/,
'\''
),
_xpath_string: $ => /[a-zA-Z_][a-zA-Z0-9_.\s]*/,
synapse_xpath_property: $ => seq(
choice(
'$body',
'$header',
'$axis2',
'$ctx',
'$trp',
'$url',
'$func',
'$env',
),
optional(seq(
':',
$.identifier,
)),
),
//incorrect implementation of json path
json_path: $ => seq(
'$.',
$.identifier,
repeat(
choice(
$.json_path_array,
$.json_path_object,
)
)
),
json_path_array: $ => seq(
'[',
$.number,
']'
),
json_path_object: $ => seq(
'.',
$.identifier
),
}
});
function sepBy1(sep, rule) {
return seq(rule, repeat(seq(sep, rule)))
}
function sepBy(sep, rule) {
return optional(sepBy1(sep, rule))
}
function attr(name, rule) {
return seq(name, '=', '"', rule, '"')
}
function xPathFunction(name, rule) {
return seq(name, '(', rule, ')')
}