Created
August 1, 2020 12:30
-
-
Save matthewmueller/98ec8465bde19c463cdbe17ca5f84851 to your computer and use it in GitHub Desktop.
Route parser, similar to https://github.com/pillarjs/path-to-regexp in Express.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package route | |
//go:generate peg -switch -inline grammar.peg | |
import ( | |
"regexp" | |
"github.com/kr/pretty" | |
) | |
// Parse fn | |
func Parse(input string) (*regexp.Regexp, error) { | |
parser := &parser{Buffer: input} | |
parser.Init() | |
err := parser.Parse() | |
if err != nil { | |
return nil, err | |
} | |
parser.Execute() | |
pretty.Println(parser.route) | |
return nil, nil | |
} | |
// Route struct | |
type Route struct { | |
Segments []Segment | |
} | |
// Segment interface | |
type Segment interface { | |
segment() | |
} | |
// Slash struct | |
type Slash struct { | |
} | |
// OptionalKey struct | |
type OptionalKey struct { | |
Prefix *Text | |
Key Key | |
} | |
func (*Slash) segment() {} | |
func (*OptionalKey) segment() {} | |
func (*RegexpKey) segment() {} | |
func (*BasicKey) segment() {} | |
func (*Text) segment() {} | |
// Key interface | |
type Key interface { | |
Segment | |
key() | |
} | |
// RegexpKey struct | |
type RegexpKey struct { | |
Name *Identifier | |
Regexp *Regexp | |
} | |
// BasicKey struct | |
type BasicKey struct { | |
Name *Identifier | |
} | |
func (*RegexpKey) key() {} | |
func (*BasicKey) key() {} | |
// Identifier struct | |
type Identifier struct { | |
Value string | |
} | |
// Regexp struct | |
type Regexp struct { | |
Value string | |
} | |
// Text struct | |
type Text struct { | |
Value string | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package route | |
type parser Peg { | |
route *Route | |
segments []Segment | |
key Key | |
rkey *RegexpKey | |
bkey *BasicKey | |
optional *OptionalKey | |
slash *Slash | |
regexp *Regexp | |
identifier *Identifier | |
text *Text | |
} | |
Route <- Segment+ End { | |
p.route = &Route{ | |
Segments: p.segments, | |
} | |
} | |
Segment <- Slash { p.segments = append(p.segments, p.slash) } | |
/ OptionalKey { p.segments = append(p.segments, p.optional) } | |
/ Key { p.segments = append(p.segments, p.key) } | |
/ Text { p.segments = append(p.segments, p.text) } | |
OptionalKey <- Text? Key '?' { | |
p.optional = &OptionalKey{ | |
Prefix: p.text, | |
Key: p.key, | |
} | |
} | |
Key <- RegexpKey { p.key = p.rkey } | |
/ BasicKey { p.key = p.bkey } | |
RegexpKey <- ':' Identifier Regexp { | |
p.rkey = &RegexpKey{ | |
Name: p.identifier, | |
Regexp: p.regexp, | |
} | |
fmt.Println("regexp", text) | |
} | |
BasicKey <- ':' Identifier { | |
p.bkey = &BasicKey{Name: p.identifier} | |
} | |
Regexp <- '(' < [^)]+ > ')' { | |
p.regexp = &Regexp{Value: text} | |
} | |
Identifier <- < [A-Za-z] [A-Za-z0-9]* > { | |
p.identifier = &Identifier{Value: text} | |
} | |
Text <- < [^:/]+ > { | |
p.text = &Text{Value: text} | |
} | |
Slash <- '/' { | |
p.slash = &Slash{} | |
} | |
End | |
<- !. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// First prototype in peg.js | |
Route = Segment+ | |
Segment = Slash / OptionalKey / Key / Text | |
Key = RegexpKey / BasicKey | |
OptionalKey = prefix:Text? key:Key '?' { | |
return { | |
type: "optional", | |
prefix: prefix, | |
key: key | |
} | |
} | |
RegexpKey = ':' id:Identifier regex:Regexp { | |
return { | |
type: "rekey", | |
name: id, | |
pattern: regex, | |
} | |
} | |
BasicKey = ':' id:Identifier { | |
return { | |
type: "key", | |
name: id, | |
} | |
} | |
Slash = '/' { | |
return { | |
type:"slash", | |
value: text() | |
} | |
} | |
Text = [^:/]+ { | |
return { | |
type:"text", | |
value: text() | |
} | |
} | |
Regexp = '(' regex:[^\)]+ ')' { | |
return { | |
type: "regexp", | |
value: regex.join('') | |
} | |
} | |
Identifier = head:[A-Za-z] tail:[A-Za-z0-9]* { | |
return { | |
type: "identifier", | |
value: [head].concat(tail).join("") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment