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, ')') }