nreplops-tool 0.3.0

Non-interactive nREPL client for shell scripting and command-line
Documentation
// conn_expr/grammar.pest
// Copyright 2022 Matti Hänninen
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

connection_expr = {
    SOI ~ (
        tunneled_connection_expr
      | remote_connection_expr
      | local_connection_expr
      | host_key_expr
    ) ~ end
}

// XXX(soija) The first octet of the server's IPv4 address could be get confused
//            with the tunnel host's optional port, if it's left out.  Therefore
//            we need this slightly messy rule.
tunneled_connection_expr = {
   ( user ~ "@" )? ~ (
       addr          ~ ":" ~ remote_connection_expr
     | addr_and_port ~ ":" ~ remote_connection_expr
   )
}
remote_connection_expr = { addr ~ ":" ~ local_connection_expr }
local_connection_expr = { port_set }

host_key_expr = { host_key_leading_char ~ host_key_char* }
host_key_leading_char = _{ ASCII_ALPHA }
host_key_char = _{ ASCII_ALPHANUMERIC | "-" | "_" }

user = { user_char+ }
user_char = _{
    ASCII_ALPHANUMERIC
  | "!" | "$" | "&" | "'" | "(" | ")" | "*" | "+" | "," | "-" | "." | ";" | "="
  | "_" | "~"
}

port_set_expr = { SOI ~ port_set ~ end }
port_set = { ( port_range | port ) ~ ( "," ~ ( port_range | port ) )* }
port_range = { port ~ "-" ~ port }
port = { ASCII_NONZERO_DIGIT ~ ASCII_DIGIT* }

addr_and_port = { addr ~ ":" ~ port_set }

addr_expr = { SOI ~ addr ~ end }
addr = { "[" ~ ipv6_addr ~ "]" | ipv4_addr | domain_addr }

domain_addr = { domain_label ~ ( "." ~ domain_label )* ~ "."? }
domain_label = { ASCII_ALPHA ~ ( "-"* ~ ASCII_ALPHANUMERIC+ )* }

ipv6_addr = @{
                                          ( h16 ~ ":" ){6} ~ ls32
  |                                "::" ~ ( h16 ~ ":" ){5} ~ ls32
  |   h16?                       ~ "::" ~ ( h16 ~ ":" ){4} ~ ls32
  | ( h16 ~ ( ":" ~ h16 ){,1} )? ~ "::" ~ ( h16 ~ ":" ){3} ~ ls32
  | ( h16 ~ ( ":" ~ h16 ){,2} )? ~ "::" ~ ( h16 ~ ":" ){2} ~ ls32
  | ( h16 ~ ( ":" ~ h16 ){,3} )? ~ "::" ~   h16 ~ ":"      ~ ls32
  | ( h16 ~ ( ":" ~ h16 ){,4} )? ~ "::"                    ~ ls32
  | ( h16 ~ ( ":" ~ h16 ){,5} )? ~ "::"                    ~ h16
  | ( h16 ~ ( ":" ~ h16 ){,6} )? ~ "::"
}
ls32 = { h16 ~ ":" ~ h16 | ipv4_addr }
h16 = { ASCII_HEX_DIGIT{1,4} }

// XXX(soija) Strictly speaking the trailing zero octets of an IPv4 address are
//            optional.  However Rust's net::IpAddr has issues with this.
ipv4_addr = @{ dec_octet ~ ( "." ~ dec_octet ){3} }
dec_octet = {
    "25" ~ '0'..'5'
  | "2" ~ '0'..'4' ~ ASCII_DIGIT
  | "1" ~ ASCII_DIGIT ~ ASCII_DIGIT
  | '1'..'9' ~ ASCII_DIGIT
  | ASCII_DIGIT
}

end = _{ EOI }