// This is a TextMate grammar distributed by `starry-night`. // This grammar is developed at // // and licensed `mpl-2.0`. // See for more info. /** * @import {Grammar} from '@wooorm/starry-night' */ /** @type {Grammar} */ const grammar = { extensions: [], names: ['bird2', 'bird', 'bird3'], patterns: [ {include: '#comments'}, {include: '#strings'}, {include: '#ip-addresses'}, {include: '#prefixes'}, {include: '#vpn-rd'}, {include: '#bytestrings'}, {include: '#bgp-paths'}, {include: '#print-statements'}, {include: '#template-definitions'}, {include: '#filter-definitions'}, {include: '#function-definitions'}, {include: '#protocol-definitions'}, {include: '#next-hop-statements'}, {include: '#neighbor-statements'}, {include: '#import-export-statements'}, {include: '#variable-declarations'}, {include: '#method-calls'}, {include: '#function-calls'}, {include: '#method-properties'}, {include: '#route-attributes'}, {include: '#data-types'}, {include: '#constants'}, {include: '#protocol-phrases'}, {include: '#structural-keywords'}, {include: '#functional-keywords'}, {include: '#semantic-modifiers'}, {include: '#builtin-functions'}, {include: '#filter-names'}, {include: '#user-variables'}, {include: '#operators'}, {include: '#numbers'}, {include: '#symbols'}, {include: '#blocks'} ], repository: { 'bgp-paths': { patterns: [ { begin: '\\[=', beginCaptures: { 0: {name: 'punctuation.definition.bgp-path.begin.bird'} }, end: '=\\]', endCaptures: {0: {name: 'punctuation.definition.bgp-path.end.bird'}}, name: 'meta.bgp-path.bird', patterns: [ {match: '[*?+]', name: 'keyword.operator.wildcard.bird'}, {match: '\\b[0-9]+\\b', name: 'constant.numeric.asn.bird'}, {include: '#operators'}, {include: '#symbols'} ] } ] }, blocks: { patterns: [ { begin: '\\{', beginCaptures: {0: {name: 'punctuation.definition.block.begin.bird'}}, end: '\\}', endCaptures: {0: {name: 'punctuation.definition.block.end.bird'}}, name: 'meta.block.bird', patterns: [{include: '$self'}] }, { begin: '\\[', beginCaptures: {0: {name: 'punctuation.definition.set.begin.bird'}}, end: '\\]', endCaptures: {0: {name: 'punctuation.definition.set.end.bird'}}, name: 'meta.set.bird', patterns: [{include: '$self'}] }, { begin: '\\(', beginCaptures: {0: {name: 'punctuation.definition.tuple.begin.bird'}}, end: '\\)', endCaptures: {0: {name: 'punctuation.definition.tuple.end.bird'}}, name: 'meta.tuple.bird', patterns: [{include: '$self'}] }, {match: ';', name: 'punctuation.terminator.statement.bird'}, {match: ',', name: 'punctuation.separator.bird'} ] }, 'builtin-functions': { patterns: [ { match: '\\b(?:defined|unset|roa_check|aspa_check|aspa_check_downstream|aspa_check_upstream|from_hex|format|append|prepend|add|delete|empty|reset|bt_assert|bt_check_assign|bt_test_suite|bt_test_same)\\b', name: 'support.function.builtin.bird' } ] }, bytestrings: { patterns: [ { match: '\\bhex:[0-9a-fA-F]{2}(?:[:\\-\\s\\.]*[0-9a-fA-F]{2})*\\b', name: 'constant.numeric.bytestring.bird' }, { match: '\\b(?:[0-9a-fA-F]{2}[:\\-\\s\\.]*){15,}[0-9a-fA-F]{2}\\b', name: 'constant.numeric.bytestring.bird' }, { match: '\\b[0-9a-fA-F]{32,}\\b', name: 'constant.numeric.bytestring.bird' } ] }, comments: { patterns: [ { begin: '#', beginCaptures: {0: {name: 'punctuation.definition.comment.bird'}}, end: '$', name: 'comment.line.number-sign.bird' }, { begin: '/\\*', beginCaptures: { 0: {name: 'punctuation.definition.comment.begin.bird'} }, end: '\\*/', endCaptures: {0: {name: 'punctuation.definition.comment.end.bird'}}, name: 'comment.block.bird' } ] }, constants: { patterns: [ { match: '\\b(?:on|off|yes|no|true|false)\\b', name: 'constant.language.boolean.bird' }, { match: '\\b(?:empty|unknown|generic|rt|ro|one|ten)\\b', name: 'constant.language.special.bird' }, { match: '\\b(?:SCOPE_HOST|SCOPE_LINK|SCOPE_SITE|SCOPE_ORGANIZATION|SCOPE_UNIVERSE|SCOPE_UNDEFINED)\\b', name: 'constant.language.scope.bird' }, { match: '\\b(?:RTS_STATIC|RTS_INHERIT|RTS_DEVICE|RTS_STATIC_DEVICE|RTS_REDIRECT|RTS_RIP|RTS_OSPF|RTS_OSPF_IA|RTS_OSPF_EXT1|RTS_OSPF_EXT2|RTS_BGP|RTS_PIPE|RTS_BABEL|RTS_RPKI|RTS_L3VPN|RTS_AGGREGATED|RTS_BRIDGE|RTS_EVPN)\\b', name: 'constant.language.source.bird' }, { match: '\\b(?:RTD_UNICAST|RTD_ROUTER|RTD_DEVICE|RTD_MULTIPATH|RTD_BLACKHOLE|RTD_UNREACHABLE|RTD_PROHIBIT)\\b', name: 'constant.language.dest.bird' }, { match: '\\b(?:ROA_UNKNOWN|ROA_INVALID|ROA_VALID)\\b', name: 'constant.language.roa.bird' }, { match: '\\b(?:ASPA_UNKNOWN|ASPA_INVALID|ASPA_VALID)\\b', name: 'constant.language.aspa.bird' }, { match: '\\b(?:ORIGIN_IGP|ORIGIN_EGP|ORIGIN_INCOMPLETE)\\b', name: 'constant.language.bgp-origin.bird' }, { match: '\\b(?:RA_PREF_LOW|RA_PREF_MEDIUM|RA_PREF_HIGH)\\b', name: 'constant.language.ra-preference.bird' }, { match: '\\b(?:AF_IPV4|AF_IPV6)\\b', name: 'constant.language.address-family.bird' }, { match: '\\b(?:KBR_SRC_BIRD|KBR_SRC_LOCAL|KBR_SRC_STATIC|KBR_SRC_DYNAMIC)\\b', name: 'constant.language.bridge-source.bird' }, { match: '\\b(?:NET_IP4|NET_IP6|NET_IP6_SADR|NET_VPN4|NET_VPN6|NET_ROA4|NET_ROA6|NET_FLOW4|NET_FLOW6|NET_MPLS|NET_ETH|NET_ASPA|NET_EVPN|NET_EVPN_EAD|NET_EVPN_MAC|NET_EVPN_IMET|NET_EVPN_ES|NET_NEIGHBOR)\\b', name: 'constant.language.net-type.bird' }, { match: '\\b(?:MPLS_POLICY_NONE|MPLS_POLICY_STATIC|MPLS_POLICY_PREFIX|MPLS_POLICY_AGGREGATE|MPLS_POLICY_VRF)\\b', name: 'constant.language.mpls.bird' } ] }, 'data-types': { patterns: [ { match: '\\b(?:(?:int|pair|quad|ip|prefix|mac|ec|lc|rd|enum)\\s+set|int|bool|ip|prefix|mac|rd|pair|quad|ec|lc|string|bytestring|bgpmask|bgppath|clist|eclist|lclist|set|enum|route)\\b', name: 'storage.type.bird' } ] }, 'filter-definitions': { patterns: [ { begin: "\\b(filter)\\s+((?:[a-zA-Z_][a-zA-Z0-9_]*|'[0-9A-Za-z_.:-]+'))\\s*\\{", beginCaptures: { 1: {name: 'keyword.control.filter.bird'}, 2: {name: 'entity.name.function.filter.bird'} }, end: '\\}', endCaptures: {0: {name: 'punctuation.definition.block.end.bird'}}, name: 'meta.filter-definition.bird', patterns: [{include: '$self'}] } ] }, 'filter-names': { patterns: [ { match: '\\b[a-zA-Z_][a-zA-Z0-9_]*_filter\\b', name: 'entity.name.function.filter.bird' } ] }, 'function-calls': { patterns: [ { begin: '\\b([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\(', beginCaptures: {1: {name: 'entity.name.function.call.bird'}}, end: '\\)', name: 'meta.function-call.bird', patterns: [{include: '$self'}] } ] }, 'function-definitions': { patterns: [ { begin: "\\b(function)\\s+((?:[a-zA-Z_][a-zA-Z0-9_]*|'[0-9A-Za-z_.:-]+'))(?=\\s*\\()", beginCaptures: { 1: {name: 'keyword.control.function.bird'}, 2: {name: 'entity.name.function.user-defined.bird'} }, end: '\\}', endCaptures: {0: {name: 'punctuation.definition.block.end.bird'}}, name: 'meta.function-definition.bird', patterns: [ { begin: '\\(', beginCaptures: { 0: {name: 'punctuation.definition.parameters.begin.bird'} }, end: '\\)', endCaptures: { 0: {name: 'punctuation.definition.parameters.end.bird'} }, name: 'meta.function-parameters.bird', patterns: [{include: '#data-types'}, {include: '#symbols'}] }, { begin: '->', beginCaptures: {0: {name: 'keyword.operator.return-type.bird'}}, end: '(?=\\{)', name: 'meta.function-return-type.bird', patterns: [{include: '#data-types'}] }, {include: '$self'} ] } ] }, 'functional-keywords': { patterns: [ { match: '\\b(?:static|rip|ospf|bgp|babel|rpki|bfd|bmp|device|direct|kernel|pipe|perf|mrt|aggregator|l3vpn|radv|bridge|evpn)\\b', name: 'keyword.control.protocol-type.bird' }, { match: '\\b(?:graceful|restart|preference|disabled|hold|keepalive|connect|retry|start|delay|error|wait|forget|scan|randomize|router|id)\\b', name: 'keyword.control.routing.bird' }, { match: '\\b(?:interface|type|wired|wireless|tunnel|rxcost|limit|hello|update|interval|port|tx|class|dscp|priority|rx|buffer|length|check|link|rtt|cost|min|max|decay|send|timestamps)\\b', name: 'keyword.other.interface.bird' }, {match: '\\b(?:preferred)\\b', name: 'keyword.other.device.bird'}, { match: '\\b(?:refresh\\s+keep|retry\\s+keep|expire\\s+keep|transport\\s+tcp|transport\\s+ssh|authentication\\s+none|authentication\\s+md5|local\\s+address|ignore\\s+max\\s+length|min\\s+version|max\\s+version|bird\\s+private\\s+key|remote\\s+public\\s+key)\\b|\\b(?:refresh|retry|expire|transport|ssh|tcp|user|address|version|ignore|private|public|key)\\b', name: 'keyword.other.rpki.bird' }, { match: '\\b(?:cmac\\s+aes128|authentication|none|mac|permissive|ao|password|key|keys|secret|deprecated|preferred|generate|accept|from|to|algorithm|hmac|cmac|aes128|sha1|sha224|sha256|sha384|sha512|blake2s128|blake2s256|blake2b256|blake2b512)\\b', name: 'keyword.other.auth.bird' }, {match: '\\b(?:time)\\b', name: 'keyword.other.time.bird'}, { match: '\\b(?:hostname|description|debug|log|syslog|stderr|udp|cli|bird|protocols|tables|channels|timeouts|passwords|bfd|confederation|cluster|stub|dead|neighbors|area|md5|multihop|passive|rfc1583compat|tick|ls|retransmit|transmit|ack|state|database|summary|external|nssa|translator|always|candidate|never|role|stability|election|action|warn|warning|auth|bug|fatal|info|trace|block|disable|keep|filtered|receive|modify|add|delete|withdraw|unreachable|blackhole|prohibit|unreach|igp_metric|localpref|med|origin|community|large_community|ext_community|as_path|prepend|weight|gateway|scope|onlink|recursive|multipath|igp|channel|sadr|src|learn|persist|via|ng|threads|thread|group|cork|threshold|settle|digest|fixed|ping|wakeup|scheduling|sockets|allocator|timers|mrtdump|timeformat|preexport|noexport|exported|stats|count|rpki|reload)\\b', name: 'keyword.other.config.bird' }, { match: '\\b(?:flow4|flow6|dst|src|proto|header|dport|sport|icmp|code|tcp|flags|dscp|dont_fragment|is_fragment|first_fragment|last_fragment|fragment|label|offset)\\b', name: 'keyword.other.flowspec.bird' }, { match: '\\b(?:ipv4-mpls|ipv6-mpls|ipv6-sadr|vpn4-mc|vpn4-mpls|vpn6-mc|vpn6-mpls|ipv4_mc|ipv6_mc|vpn4|vpn6|mpls|aspa|roa4|roa6|eth|evpn|neighbor|pri|sec)\\b', name: 'keyword.other.address.bird' }, { match: '\\b(?:all|none)\\b', name: 'keyword.other.quick-declaration.bird' } ] }, 'import-export-statements': { patterns: [ { captures: { 1: {name: 'keyword.control.import-export.bird'}, 2: {name: 'keyword.control.filter.bird'}, 3: {name: 'entity.name.function.filter.bird'} }, match: "\\b(import)\\s+(filter)\\s+((?:[a-zA-Z_][a-zA-Z0-9_]*|'[0-9A-Za-z_.:-]+'))\\b", name: 'meta.import-statement.bird' }, { begin: '\\b(import)\\s+(filter)\\s*\\{', beginCaptures: { 1: {name: 'keyword.control.import-export.bird'}, 2: {name: 'keyword.control.filter.bird'} }, end: '\\}', endCaptures: {0: {name: 'punctuation.definition.block.end.bird'}}, name: 'meta.import-filter-inline.bird', patterns: [{include: '$self'}] }, { begin: '\\b(export)\\s+(where)\\b', beginCaptures: { 1: {name: 'keyword.control.import-export.bird'}, 2: {name: 'keyword.control.where.bird'} }, end: ';', endCaptures: {0: {name: 'punctuation.terminator.statement.bird'}}, name: 'meta.export-where-clause.bird', patterns: [{include: '$self'}] }, { begin: '\\b(export\\s+in)\\b', beginCaptures: {1: {name: 'keyword.control.import-export.bird'}}, end: ';', endCaptures: {0: {name: 'punctuation.terminator.statement.bird'}}, name: 'meta.export-prefilter-clause.bird', patterns: [{include: '$self'}] }, { captures: { 1: {name: 'keyword.control.import-export.bird'}, 2: {name: 'keyword.control.filter.bird'}, 3: {name: 'entity.name.function.filter.bird'} }, match: "\\b(export)\\s+(filter)\\s+((?:[a-zA-Z_][a-zA-Z0-9_]*|'[0-9A-Za-z_.:-]+'))\\b", name: 'meta.export-statement.bird' } ] }, 'ip-addresses': { patterns: [ { match: '\\b(?:[0-9]{1,3}\\.){3}[0-9]{1,3}(?:/[0-9]{1,2})?\\b', name: 'constant.numeric.ip.ipv4.bird' }, { match: '\\b(?:[0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}(?:/[0-9]{1,3})?\\b', name: 'constant.numeric.ip.ipv6.bird' }, { match: '::(?:[0-9a-fA-F]{0,4}:){0,6}[0-9a-fA-F]{0,4}(?:/[0-9]{1,3})?\\b', name: 'constant.numeric.ip.ipv6.bird' }, { match: '\\b(?:[0-9a-fA-F]{0,4}:){1,6}::(?:[0-9a-fA-F]{0,4}:){0,5}[0-9a-fA-F]{0,4}(?:/[0-9]{1,3})?\\b', name: 'constant.numeric.ip.ipv6.bird' } ] }, 'method-calls': { patterns: [ { begin: '\\.\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\(', beginCaptures: {1: {name: 'entity.name.function.method.bird'}}, end: '\\)', name: 'meta.method-call.bird', patterns: [{include: '$self'}] }, { captures: {1: {name: 'variable.other.property.bird'}}, match: '\\.\\s*([a-zA-Z_][a-zA-Z0-9_]*)', name: 'meta.method-access.bird' } ] }, 'method-properties': { patterns: [ { match: '(?<=\\.)\\s*(?:first|last|last_nonaggregated|len|asn|data|data1|data2|is_v4|ip|src|dst|rd|maxlen|type|mask|min|max|mac|vlan_id|evpn_type|evpn_tag|evpn_esi|router_ip)\\b(?!\\s*\\()', name: 'support.variable.property.bird' } ] }, 'neighbor-statements': { patterns: [ { captures: { 1: {name: 'keyword.control.local.bird'}, 2: {name: 'entity.name.symbol.local-address.bird'}, 3: {name: 'keyword.control.port.bird'}, 4: {name: 'constant.numeric.port.bird'}, 5: {name: 'keyword.control.as.bird'}, 6: {name: 'constant.numeric.asn.bird'} }, match: "\\b(local)\\s+((?:[0-9a-fA-F:.]+|[A-Za-z_][A-Za-z0-9_]*|'[0-9A-Za-z_.:-]+'))(?:\\s+(port)\\s+((?:[0-9]+|[A-Za-z_][A-Za-z0-9_]*)))?\\s+(as)\\s+((?:[0-9]+|[A-Za-z_][A-Za-z0-9_]*))\\b", name: 'meta.local-as-statement.bird' }, { captures: { 1: {name: 'keyword.control.local.bird'}, 2: {name: 'keyword.control.as.bird'}, 3: {name: 'constant.numeric.asn.bird'} }, match: '\\b(local)\\s+(as)\\s+((?:[0-9]+|[A-Za-z_][A-Za-z0-9_]*))\\b', name: 'meta.local-as-template-statement.bird' }, { captures: { 1: {name: 'keyword.control.neighbor.bird'}, 2: {name: 'constant.numeric.ip-address.bird'}, 3: {name: 'meta.interface-reference.bird'}, 4: {name: 'string.quoted.single.interface.bird'}, 5: {name: 'variable.other.interface.bird'}, 6: {name: 'keyword.control.as.bird'}, 7: {name: 'constant.numeric.asn.bird'}, 8: {name: 'keyword.control.port.bird'}, 9: {name: 'constant.numeric.port.bird'} }, match: "\\b(neighbor)\\s+([0-9a-fA-F:.]+)\\s*(%\\s*(?:'([0-9A-Za-z_.:-]+)'|([A-Za-z0-9_.:-]+)))?(?:\\s+(as)\\s+((?:[0-9]+|[A-Za-z_][A-Za-z0-9_]*)))?\\s+(port)\\s+((?:[0-9]+|[A-Za-z_][A-Za-z0-9_]*))\\b", name: 'meta.neighbor-port-statement.bird' }, { captures: { 1: {name: 'keyword.control.neighbor.bird'}, 2: {name: 'entity.name.symbol.neighbor-address.bird'}, 3: {name: 'meta.interface-reference.bird'}, 4: {name: 'string.quoted.single.interface.bird'}, 5: {name: 'variable.other.interface.bird'}, 6: {name: 'keyword.control.as.bird'}, 7: {name: 'constant.numeric.asn.bird'}, 8: {name: 'keyword.control.port.bird'}, 9: {name: 'constant.numeric.port.bird'} }, match: "\\b(neighbor)\\s+((?:'[0-9A-Za-z_.:-]+'|(?!as\\b|range\\b)[A-Za-z_][A-Za-z0-9_]*))\\s*(%\\s*(?:'([0-9A-Za-z_.:-]+)'|([A-Za-z0-9_.:-]+)))?(?:\\s+(as)\\s+((?:[0-9]+|[A-Za-z_][A-Za-z0-9_]*)))?\\s+(port)\\s+((?:[0-9]+|[A-Za-z_][A-Za-z0-9_]*))\\b", name: 'meta.neighbor-port-symbolic-statement.bird' }, { captures: { 1: {name: 'keyword.control.neighbor.bird'}, 2: {name: 'constant.numeric.ip-address.bird'}, 3: {name: 'meta.interface-reference.bird'}, 4: {name: 'string.quoted.single.interface.bird'}, 5: {name: 'variable.other.interface.bird'}, 6: {name: 'keyword.control.as.bird'}, 7: {name: 'constant.numeric.asn.bird'} }, match: "\\b(neighbor)\\s+([0-9a-fA-F:.]+)\\s*(%\\s*(?:'([0-9A-Za-z_.:-]+)'|([A-Za-z0-9_.:-]+)))?\\s+(as)\\s+((?:[0-9]+|[A-Za-z_][A-Za-z0-9_]*))\\b", name: 'meta.neighbor-statement.bird' }, { captures: { 1: {name: 'keyword.control.neighbor.bird'}, 2: {name: 'entity.name.symbol.neighbor-address.bird'}, 3: {name: 'meta.interface-reference.bird'}, 4: {name: 'string.quoted.single.interface.bird'}, 5: {name: 'variable.other.interface.bird'}, 6: {name: 'keyword.control.as.bird'}, 7: {name: 'constant.numeric.asn.bird'} }, match: "\\b(neighbor)\\s+((?:'[0-9A-Za-z_.:-]+'|(?!as\\b|range\\b)[A-Za-z_][A-Za-z0-9_]*))\\s*(%\\s*(?:'([0-9A-Za-z_.:-]+)'|([A-Za-z0-9_.:-]+)))?\\s+(as)\\s+((?:[0-9]+|[A-Za-z_][A-Za-z0-9_]*))\\b", name: 'meta.neighbor-symbolic-statement.bird' }, { captures: { 1: {name: 'keyword.control.neighbor.bird'}, 2: {name: 'keyword.control.as.bird'}, 3: {name: 'constant.numeric.asn.bird'} }, match: '\\b(neighbor)\\s+(as)\\s+((?:[0-9]+|[A-Za-z_][A-Za-z0-9_]*))\\b', name: 'meta.neighbor-template-statement.bird' }, { captures: { 1: {name: 'keyword.control.neighbor.bird'}, 2: {name: 'entity.name.symbol.neighbor-address.bird'}, 3: {name: 'keyword.other.semantic-modifier.bird'} }, match: "\\b(neighbor)\\s+([0-9a-fA-F:.]+|(?:'[0-9A-Za-z_.:-]+'|(?!as\\b|range\\b)[A-Za-z_][A-Za-z0-9_]*))\\s+(internal|external)\\b", name: 'meta.neighbor-role-statement.bird' }, { captures: { 1: {name: 'keyword.control.neighbor.bird'}, 2: {name: 'entity.name.symbol.neighbor-address.bird'}, 3: {name: 'keyword.other.semantic-modifier.bird'} }, match: "\\b(neighbor)\\s+([0-9a-fA-F:.]+|(?:'[0-9A-Za-z_.:-]+'|(?!as\\b|range\\b)[A-Za-z_][A-Za-z0-9_]*))\\s+(onlink)\\b", name: 'meta.neighbor-onlink-statement.bird' }, { captures: { 1: {name: 'keyword.control.source.bird'}, 2: {name: 'constant.numeric.ip-address.bird'} }, match: '\\b(source address)\\s+([0-9a-fA-F:.]+)\\b', name: 'meta.source-address-statement.bird' } ] }, 'next-hop-statements': { patterns: [ { captures: { 1: {name: 'keyword.control.routing.bird'}, 2: {name: 'keyword.other.ip-version.bird'}, 3: {name: 'constant.numeric.ip-address.bird'} }, match: '\\b(next hop)\\s+(ipv4)\\s+([0-9\\.]+)\\b', name: 'meta.next-hop-ipv4.bird' }, { captures: { 1: {name: 'keyword.control.routing.bird'}, 2: {name: 'keyword.other.ip-version.bird'}, 3: {name: 'constant.numeric.ip-address.bird'} }, match: '\\b(next hop)\\s+(ipv6)\\s+([0-9a-fA-F:]+)\\b', name: 'meta.next-hop-ipv6.bird' }, { captures: { 1: {name: 'keyword.control.routing.bird'}, 2: {name: 'keyword.other.semantic-modifier.bird'} }, match: '\\b(next hop)\\s+(self)\\b', name: 'meta.next-hop-simple.bird' }, { captures: { 1: {name: 'keyword.control.routing.bird'}, 2: {name: 'keyword.other.semantic-modifier.bird'} }, match: '\\b(next hop prefer)\\s+(global|local|native|ipv6)\\b', name: 'meta.next-hop-prefer-statement.bird' }, { captures: { 1: {name: 'keyword.control.routing.bird'}, 2: {name: 'keyword.other.semantic-modifier.bird'} }, match: '\\b(next hop keep)(?:\\s+(ibgp|ebgp))?\\b', name: 'meta.next-hop-keep-statement.bird' }, { captures: { 1: {name: 'keyword.control.routing.bird'}, 2: {name: 'keyword.other.semantic-modifier.bird'} }, match: '\\b(extended next hop)\\s+(on|off)\\b', name: 'meta.extended-next-hop-statement.bird' }, { captures: { 1: {name: 'keyword.control.routing.bird'}, 2: {name: 'keyword.other.semantic-modifier.bird'} }, match: '\\b(require extended next hop)\\s+(yes|no|on|off|true|false)\\b', name: 'meta.require-extended-next-hop-statement.bird' } ] }, numbers: { patterns: [ {match: '\\b0x[0-9a-fA-F]+\\b', name: 'constant.numeric.hex.bird'}, {match: '\\b[0-9]+\\b', name: 'constant.numeric.decimal.bird'}, { captures: {1: {name: 'keyword.other.unit.bird'}}, match: '\\b[0-9]+\\s*(s|ms|us)\\b', name: 'constant.numeric.time.bird' } ] }, operators: { patterns: [ { match: '(?:==|!=|<=|>=|!~|=|~|<|>)', name: 'keyword.operator.comparison.bird' }, {match: '(?:&&|\\|\\||!|->)', name: 'keyword.operator.logical.bird'}, { match: '(?