Skip to content

Commit

Permalink
feat: align grammar with OpenAPI specification
Browse files Browse the repository at this point in the history
  • Loading branch information
char0n committed Dec 28, 2024
1 parent 670dfbe commit c5e2b8f
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 154 deletions.
25 changes: 11 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,27 +256,24 @@ The Server URL Templating is defined by the following [ABNF](https://tools.ietf.

```abnf
; OpenAPI Server URL templating ABNF syntax
; Aligned with RFC 6570 (https://www.rfc-editor.org/rfc/rfc6570)
server-url-template = 1*( literals / server-variable )
server-url-template = 1*( literals / server-variable ) ; variant of https://www.rfc-editor.org/rfc/rfc6570#section-2
server-variable = "{" server-variable-name "}"
server-variable-name = 1*( unreserved / pct-encoded / sub-delims / ":" / "@" )
literals = 1*( %x21 / %x23-24 / %x26 / %x28-3B / %x3D / %x3F-5B
server-variable-name = 1*( %x00-7A / %x7C / %x7E-10FFFF ) ; every UTF8 character except { and } (from OpenAPI)
; https://www.rfc-editor.org/rfc/rfc6570#section-2.1
; https://www.rfc-editor.org/errata/eid6937
literals = 1*( %x21 / %x23-24 / %x26-3B / %x3D / %x3F-5B
/ %x5D / %x5F / %x61-7A / %x7E / ucschar / iprivate
/ pct-encoded)
; any Unicode character except: CTL, SP,
; DQUOTE, "'", "%" (aside from pct-encoded),
; "<", ">", "\", "^", "`", "{", "|", "}"
; any Unicode character except: CTL, SP,
; DQUOTE, "%" (aside from pct-encoded),
; "<", ">", "\", "^", "`", "{", "|", "}"
; Characters definitions (from RFC 6570)
ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
; https://www.rfc-editor.org/rfc/rfc6570#section-1.5
DIGIT = %x30-39 ; 0-9
HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
; case-insensitive
HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F" ; case-insensitive
pct-encoded = "%" HEXDIG HEXDIG
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="
ucschar = %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF
/ %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD
Expand Down
25 changes: 11 additions & 14 deletions src/server-url-templating.bnf
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
; OpenAPI Server URL templating ABNF syntax
; Aligned with RFC 6570 (https://www.rfc-editor.org/rfc/rfc6570)
server-url-template = 1*( literals / server-variable )
server-url-template = 1*( literals / server-variable ) ; variant of https://www.rfc-editor.org/rfc/rfc6570#section-2
server-variable = "{" server-variable-name "}"
server-variable-name = 1*( unreserved / pct-encoded / sub-delims / ":" / "@" )
literals = 1*( %x21 / %x23-24 / %x26 / %x28-3B / %x3D / %x3F-5B
server-variable-name = 1*( %x00-7A / %x7C / %x7E-10FFFF ) ; every UTF8 character except { and } (from OpenAPI)

; https://www.rfc-editor.org/rfc/rfc6570#section-2.1
; https://www.rfc-editor.org/errata/eid6937
literals = 1*( %x21 / %x23-24 / %x26-3B / %x3D / %x3F-5B
/ %x5D / %x5F / %x61-7A / %x7E / ucschar / iprivate
/ pct-encoded)
; any Unicode character except: CTL, SP,
; DQUOTE, "'", "%" (aside from pct-encoded),
; "<", ">", "\", "^", "`", "{", "|", "}"
; any Unicode character except: CTL, SP,
; DQUOTE, "%" (aside from pct-encoded),
; "<", ">", "\", "^", "`", "{", "|", "}"

; Characters definitions (from RFC 6570)
ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
; https://www.rfc-editor.org/rfc/rfc6570#section-1.5
DIGIT = %x30-39 ; 0-9
HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
; case-insensitive
HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F" ; case-insensitive

pct-encoded = "%" HEXDIG HEXDIG
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="

ucschar = %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF
/ %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD
Expand Down
194 changes: 77 additions & 117 deletions src/server-url-templating.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@
export default function grammar(){
// ```
// SUMMARY
// rules = 12
// rules = 9
// udts = 0
// opcodes = 87
// opcodes = 62
// --- ABNF original opcodes
// ALT = 9
// ALT = 6
// CAT = 2
// REP = 3
// RNM = 14
// TLS = 26
// RNM = 9
// TLS = 9
// TBS = 6
// TRG = 27
// --- SABNF superset opcodes
// UDT = 0
// AND = 0
// NOT = 0
// characters = [33 - 1114109]
// characters = [0 - 1114111]
// ```
/* OBJECT IDENTIFIER (for internal parser use) */
this.grammarObject = 'grammarObject';
Expand All @@ -31,14 +31,11 @@ export default function grammar(){
this.rules[1] = { name: 'server-variable', lower: 'server-variable', index: 1, isBkr: false };
this.rules[2] = { name: 'server-variable-name', lower: 'server-variable-name', index: 2, isBkr: false };
this.rules[3] = { name: 'literals', lower: 'literals', index: 3, isBkr: false };
this.rules[4] = { name: 'ALPHA', lower: 'alpha', index: 4, isBkr: false };
this.rules[5] = { name: 'DIGIT', lower: 'digit', index: 5, isBkr: false };
this.rules[6] = { name: 'HEXDIG', lower: 'hexdig', index: 6, isBkr: false };
this.rules[7] = { name: 'pct-encoded', lower: 'pct-encoded', index: 7, isBkr: false };
this.rules[8] = { name: 'unreserved', lower: 'unreserved', index: 8, isBkr: false };
this.rules[9] = { name: 'sub-delims', lower: 'sub-delims', index: 9, isBkr: false };
this.rules[10] = { name: 'ucschar', lower: 'ucschar', index: 10, isBkr: false };
this.rules[11] = { name: 'iprivate', lower: 'iprivate', index: 11, isBkr: false };
this.rules[4] = { name: 'DIGIT', lower: 'digit', index: 4, isBkr: false };
this.rules[5] = { name: 'HEXDIG', lower: 'hexdig', index: 5, isBkr: false };
this.rules[6] = { name: 'pct-encoded', lower: 'pct-encoded', index: 6, isBkr: false };
this.rules[7] = { name: 'ucschar', lower: 'ucschar', index: 7, isBkr: false };
this.rules[8] = { name: 'iprivate', lower: 'iprivate', index: 8, isBkr: false };

/* UDTS */
this.udts = [];
Expand All @@ -61,137 +58,100 @@ export default function grammar(){
/* server-variable-name */
this.rules[2].opcodes = [];
this.rules[2].opcodes[0] = { type: 3, min: 1, max: Infinity };// REP
this.rules[2].opcodes[1] = { type: 1, children: [2,3,4,5,6] };// ALT
this.rules[2].opcodes[2] = { type: 4, index: 8 };// RNM(unreserved)
this.rules[2].opcodes[3] = { type: 4, index: 7 };// RNM(pct-encoded)
this.rules[2].opcodes[4] = { type: 4, index: 9 };// RNM(sub-delims)
this.rules[2].opcodes[5] = { type: 7, string: [58] };// TLS
this.rules[2].opcodes[6] = { type: 7, string: [64] };// TLS
this.rules[2].opcodes[1] = { type: 1, children: [2,3,4] };// ALT
this.rules[2].opcodes[2] = { type: 5, min: 0, max: 122 };// TRG
this.rules[2].opcodes[3] = { type: 6, string: [124] };// TBS
this.rules[2].opcodes[4] = { type: 5, min: 126, max: 1114111 };// TRG

/* literals */
this.rules[3].opcodes = [];
this.rules[3].opcodes[0] = { type: 3, min: 1, max: Infinity };// REP
this.rules[3].opcodes[1] = { type: 1, children: [2,3,4,5,6,7,8,9,10,11,12,13,14] };// ALT
this.rules[3].opcodes[1] = { type: 1, children: [2,3,4,5,6,7,8,9,10,11,12,13] };// ALT
this.rules[3].opcodes[2] = { type: 6, string: [33] };// TBS
this.rules[3].opcodes[3] = { type: 5, min: 35, max: 36 };// TRG
this.rules[3].opcodes[4] = { type: 6, string: [38] };// TBS
this.rules[3].opcodes[5] = { type: 5, min: 40, max: 59 };// TRG
this.rules[3].opcodes[6] = { type: 6, string: [61] };// TBS
this.rules[3].opcodes[7] = { type: 5, min: 63, max: 91 };// TRG
this.rules[3].opcodes[8] = { type: 6, string: [93] };// TBS
this.rules[3].opcodes[9] = { type: 6, string: [95] };// TBS
this.rules[3].opcodes[10] = { type: 5, min: 97, max: 122 };// TRG
this.rules[3].opcodes[11] = { type: 6, string: [126] };// TBS
this.rules[3].opcodes[12] = { type: 4, index: 10 };// RNM(ucschar)
this.rules[3].opcodes[13] = { type: 4, index: 11 };// RNM(iprivate)
this.rules[3].opcodes[14] = { type: 4, index: 7 };// RNM(pct-encoded)

/* ALPHA */
this.rules[4].opcodes = [];
this.rules[4].opcodes[0] = { type: 1, children: [1,2] };// ALT
this.rules[4].opcodes[1] = { type: 5, min: 65, max: 90 };// TRG
this.rules[4].opcodes[2] = { type: 5, min: 97, max: 122 };// TRG
this.rules[3].opcodes[4] = { type: 5, min: 38, max: 59 };// TRG
this.rules[3].opcodes[5] = { type: 6, string: [61] };// TBS
this.rules[3].opcodes[6] = { type: 5, min: 63, max: 91 };// TRG
this.rules[3].opcodes[7] = { type: 6, string: [93] };// TBS
this.rules[3].opcodes[8] = { type: 6, string: [95] };// TBS
this.rules[3].opcodes[9] = { type: 5, min: 97, max: 122 };// TRG
this.rules[3].opcodes[10] = { type: 6, string: [126] };// TBS
this.rules[3].opcodes[11] = { type: 4, index: 7 };// RNM(ucschar)
this.rules[3].opcodes[12] = { type: 4, index: 8 };// RNM(iprivate)
this.rules[3].opcodes[13] = { type: 4, index: 6 };// RNM(pct-encoded)

/* DIGIT */
this.rules[5].opcodes = [];
this.rules[5].opcodes[0] = { type: 5, min: 48, max: 57 };// TRG
this.rules[4].opcodes = [];
this.rules[4].opcodes[0] = { type: 5, min: 48, max: 57 };// TRG

/* HEXDIG */
this.rules[6].opcodes = [];
this.rules[6].opcodes[0] = { type: 1, children: [1,2,3,4,5,6,7] };// ALT
this.rules[6].opcodes[1] = { type: 4, index: 5 };// RNM(DIGIT)
this.rules[6].opcodes[2] = { type: 7, string: [97] };// TLS
this.rules[6].opcodes[3] = { type: 7, string: [98] };// TLS
this.rules[6].opcodes[4] = { type: 7, string: [99] };// TLS
this.rules[6].opcodes[5] = { type: 7, string: [100] };// TLS
this.rules[6].opcodes[6] = { type: 7, string: [101] };// TLS
this.rules[6].opcodes[7] = { type: 7, string: [102] };// TLS
this.rules[5].opcodes = [];
this.rules[5].opcodes[0] = { type: 1, children: [1,2,3,4,5,6,7] };// ALT
this.rules[5].opcodes[1] = { type: 4, index: 4 };// RNM(DIGIT)
this.rules[5].opcodes[2] = { type: 7, string: [97] };// TLS
this.rules[5].opcodes[3] = { type: 7, string: [98] };// TLS
this.rules[5].opcodes[4] = { type: 7, string: [99] };// TLS
this.rules[5].opcodes[5] = { type: 7, string: [100] };// TLS
this.rules[5].opcodes[6] = { type: 7, string: [101] };// TLS
this.rules[5].opcodes[7] = { type: 7, string: [102] };// TLS

/* pct-encoded */
this.rules[7].opcodes = [];
this.rules[7].opcodes[0] = { type: 2, children: [1,2,3] };// CAT
this.rules[7].opcodes[1] = { type: 7, string: [37] };// TLS
this.rules[7].opcodes[2] = { type: 4, index: 6 };// RNM(HEXDIG)
this.rules[7].opcodes[3] = { type: 4, index: 6 };// RNM(HEXDIG)

/* unreserved */
this.rules[8].opcodes = [];
this.rules[8].opcodes[0] = { type: 1, children: [1,2,3,4,5,6] };// ALT
this.rules[8].opcodes[1] = { type: 4, index: 4 };// RNM(ALPHA)
this.rules[8].opcodes[2] = { type: 4, index: 5 };// RNM(DIGIT)
this.rules[8].opcodes[3] = { type: 7, string: [45] };// TLS
this.rules[8].opcodes[4] = { type: 7, string: [46] };// TLS
this.rules[8].opcodes[5] = { type: 7, string: [95] };// TLS
this.rules[8].opcodes[6] = { type: 7, string: [126] };// TLS

/* sub-delims */
this.rules[9].opcodes = [];
this.rules[9].opcodes[0] = { type: 1, children: [1,2,3,4,5,6,7,8,9,10,11] };// ALT
this.rules[9].opcodes[1] = { type: 7, string: [33] };// TLS
this.rules[9].opcodes[2] = { type: 7, string: [36] };// TLS
this.rules[9].opcodes[3] = { type: 7, string: [38] };// TLS
this.rules[9].opcodes[4] = { type: 7, string: [39] };// TLS
this.rules[9].opcodes[5] = { type: 7, string: [40] };// TLS
this.rules[9].opcodes[6] = { type: 7, string: [41] };// TLS
this.rules[9].opcodes[7] = { type: 7, string: [42] };// TLS
this.rules[9].opcodes[8] = { type: 7, string: [43] };// TLS
this.rules[9].opcodes[9] = { type: 7, string: [44] };// TLS
this.rules[9].opcodes[10] = { type: 7, string: [59] };// TLS
this.rules[9].opcodes[11] = { type: 7, string: [61] };// TLS
this.rules[6].opcodes = [];
this.rules[6].opcodes[0] = { type: 2, children: [1,2,3] };// CAT
this.rules[6].opcodes[1] = { type: 7, string: [37] };// TLS
this.rules[6].opcodes[2] = { type: 4, index: 5 };// RNM(HEXDIG)
this.rules[6].opcodes[3] = { type: 4, index: 5 };// RNM(HEXDIG)

/* ucschar */
this.rules[10].opcodes = [];
this.rules[10].opcodes[0] = { type: 1, children: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17] };// ALT
this.rules[10].opcodes[1] = { type: 5, min: 160, max: 55295 };// TRG
this.rules[10].opcodes[2] = { type: 5, min: 63744, max: 64975 };// TRG
this.rules[10].opcodes[3] = { type: 5, min: 65008, max: 65519 };// TRG
this.rules[10].opcodes[4] = { type: 5, min: 65536, max: 131069 };// TRG
this.rules[10].opcodes[5] = { type: 5, min: 131072, max: 196605 };// TRG
this.rules[10].opcodes[6] = { type: 5, min: 196608, max: 262141 };// TRG
this.rules[10].opcodes[7] = { type: 5, min: 262144, max: 327677 };// TRG
this.rules[10].opcodes[8] = { type: 5, min: 327680, max: 393213 };// TRG
this.rules[10].opcodes[9] = { type: 5, min: 393216, max: 458749 };// TRG
this.rules[10].opcodes[10] = { type: 5, min: 458752, max: 524285 };// TRG
this.rules[10].opcodes[11] = { type: 5, min: 524288, max: 589821 };// TRG
this.rules[10].opcodes[12] = { type: 5, min: 589824, max: 655357 };// TRG
this.rules[10].opcodes[13] = { type: 5, min: 655360, max: 720893 };// TRG
this.rules[10].opcodes[14] = { type: 5, min: 720896, max: 786429 };// TRG
this.rules[10].opcodes[15] = { type: 5, min: 786432, max: 851965 };// TRG
this.rules[10].opcodes[16] = { type: 5, min: 851968, max: 917501 };// TRG
this.rules[10].opcodes[17] = { type: 5, min: 921600, max: 983037 };// TRG
this.rules[7].opcodes = [];
this.rules[7].opcodes[0] = { type: 1, children: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17] };// ALT
this.rules[7].opcodes[1] = { type: 5, min: 160, max: 55295 };// TRG
this.rules[7].opcodes[2] = { type: 5, min: 63744, max: 64975 };// TRG
this.rules[7].opcodes[3] = { type: 5, min: 65008, max: 65519 };// TRG
this.rules[7].opcodes[4] = { type: 5, min: 65536, max: 131069 };// TRG
this.rules[7].opcodes[5] = { type: 5, min: 131072, max: 196605 };// TRG
this.rules[7].opcodes[6] = { type: 5, min: 196608, max: 262141 };// TRG
this.rules[7].opcodes[7] = { type: 5, min: 262144, max: 327677 };// TRG
this.rules[7].opcodes[8] = { type: 5, min: 327680, max: 393213 };// TRG
this.rules[7].opcodes[9] = { type: 5, min: 393216, max: 458749 };// TRG
this.rules[7].opcodes[10] = { type: 5, min: 458752, max: 524285 };// TRG
this.rules[7].opcodes[11] = { type: 5, min: 524288, max: 589821 };// TRG
this.rules[7].opcodes[12] = { type: 5, min: 589824, max: 655357 };// TRG
this.rules[7].opcodes[13] = { type: 5, min: 655360, max: 720893 };// TRG
this.rules[7].opcodes[14] = { type: 5, min: 720896, max: 786429 };// TRG
this.rules[7].opcodes[15] = { type: 5, min: 786432, max: 851965 };// TRG
this.rules[7].opcodes[16] = { type: 5, min: 851968, max: 917501 };// TRG
this.rules[7].opcodes[17] = { type: 5, min: 921600, max: 983037 };// TRG

/* iprivate */
this.rules[11].opcodes = [];
this.rules[11].opcodes[0] = { type: 1, children: [1,2,3] };// ALT
this.rules[11].opcodes[1] = { type: 5, min: 57344, max: 63743 };// TRG
this.rules[11].opcodes[2] = { type: 5, min: 983040, max: 1048573 };// TRG
this.rules[11].opcodes[3] = { type: 5, min: 1048576, max: 1114109 };// TRG
this.rules[8].opcodes = [];
this.rules[8].opcodes[0] = { type: 1, children: [1,2,3] };// ALT
this.rules[8].opcodes[1] = { type: 5, min: 57344, max: 63743 };// TRG
this.rules[8].opcodes[2] = { type: 5, min: 983040, max: 1048573 };// TRG
this.rules[8].opcodes[3] = { type: 5, min: 1048576, max: 1114109 };// TRG

// The `toString()` function will display the original grammar file(s) that produced these opcodes.
this.toString = function toString(){
let str = "";
str += "; OpenAPI Server URL templating ABNF syntax\n";
str += "; Aligned with RFC 6570 (https://www.rfc-editor.org/rfc/rfc6570)\n";
str += "server-url-template = 1*( literals / server-variable )\n";
str += "server-url-template = 1*( literals / server-variable ) ; variant of https://www.rfc-editor.org/rfc/rfc6570#section-2\n";
str += "server-variable = \"{\" server-variable-name \"}\"\n";
str += "server-variable-name = 1*( unreserved / pct-encoded / sub-delims / \":\" / \"@\" )\n";
str += "literals = 1*( %x21 / %x23-24 / %x26 / %x28-3B / %x3D / %x3F-5B\n";
str += "server-variable-name = 1*( %x00-7A / %x7C / %x7E-10FFFF ) ; every UTF8 character except { and } (from OpenAPI)\n";
str += "\n";
str += "; https://www.rfc-editor.org/rfc/rfc6570#section-2.1\n";
str += "; https://www.rfc-editor.org/errata/eid6937\n";
str += "literals = 1*( %x21 / %x23-24 / %x26-3B / %x3D / %x3F-5B\n";
str += " / %x5D / %x5F / %x61-7A / %x7E / ucschar / iprivate\n";
str += " / pct-encoded)\n";
str += " ; any Unicode character except: CTL, SP,\n";
str += " ; DQUOTE, \"'\", \"%\" (aside from pct-encoded),\n";
str += " ; \"<\", \">\", \"\\\", \"^\", \"`\", \"{\", \"|\", \"}\"\n";
str += " ; any Unicode character except: CTL, SP,\n";
str += " ; DQUOTE, \"%\" (aside from pct-encoded),\n";
str += " ; \"<\", \">\", \"\\\", \"^\", \"`\", \"{\", \"|\", \"}\"\n";
str += "\n";
str += "; Characters definitions (from RFC 6570)\n";
str += "ALPHA = %x41-5A / %x61-7A ; A-Z / a-z\n";
str += "; https://www.rfc-editor.org/rfc/rfc6570#section-1.5\n";
str += "DIGIT = %x30-39 ; 0-9\n";
str += "HEXDIG = DIGIT / \"A\" / \"B\" / \"C\" / \"D\" / \"E\" / \"F\"\n";
str += " ; case-insensitive\n";
str += "HEXDIG = DIGIT / \"A\" / \"B\" / \"C\" / \"D\" / \"E\" / \"F\" ; case-insensitive\n";
str += "\n";
str += "pct-encoded = \"%\" HEXDIG HEXDIG\n";
str += "unreserved = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n";
str += "sub-delims = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n";
str += " / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n";
str += "\n";
str += "ucschar = %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF\n";
str += " / %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD\n";
Expand Down
Loading

0 comments on commit c5e2b8f

Please sign in to comment.