Paste: Mailbox parse - RFC 5322
Author: | Roberto López |
Mode: | factor |
Date: | Fri, 12 Dec 2014 08:19:37 |
Plain Text |
USING: kernel accessors formatting peg peg.ebnf strings
sequences present sequences.deep continuations ;
IN: email
<PRIVATE
TUPLE: ast-atom value ;
TUPLE: ast-string value ;
EBNF: email-tokenizer
Space = " " | "\t" | "\r" | "\n"
Spaces = Space* => [[ ignore ]]
Letter = [a-zA-Z]
Digit = [0-9]
Atom = (Letter|Digit|[)(!#$%&'*+/=?^_`{|}~-])+ => [[ >string ast-atom boa ]]
Escape-char = "\\" => [[ 92 ]]
| "\\n" => [[ 10 ]]
| "\\r" => [[ 13 ]]
| "\\t" => [[ 9 ]]
String-char = (Escape-char | !('"') .)* => [[ >string ]]
String = '"' String-char '"' => [[ concat ast-string boa ]]
Special = "(" | ")" | "<" | ">" | "@" | ","
| ":" | "\" | '"' | "." | "[" | "]"
Tok = Spaces ( Atom | String | Special )
Toks = Tok* Spaces
;EBNF
PRIVATE>
TUPLE: email local domain ;
C: <email> email
M: email present
[ local>> ] [ domain>> ] bi
"@" swap 3append ;
TUPLE: mailbox name email ;
C: <mailbox> mailbox
M: mailbox present
[ name>> present ] [ email>> present ] [ name>> ] tri
[ "%s <%s>" sprintf ] [ nip ] if ;
EBNF: email-ebnf
tokenizer = default
nl = "\r" "\n" | "\n"
tokenizer = <foreign email-tokenizer Tok>
Atom = . ?[ ast-atom? ]? => [[ value>> ]]
String = . ?[ ast-string? ]? => [[ value>> ]]
Word = Atom | String
Phrase = Word ( Word )* => [[ flatten " " join ]]
Local-Part = Word ("." Word)* => [[ flatten concat ]]
Domain-Ref = Atom
Sub-Domain = Domain-Ref
Domain = Sub-Domain ("." Sub-Domain)* => [[ flatten concat ]]
Addr-Spec = Local-Part:l "@" Domain:d => [[ l d <email> ]]
Route-Addr = "<" Addr-Spec:as ">" => [[ as ]]
Named-Addr-Spec = Phrase? Route-Addr => [[ first2 <mailbox> ]]
Mailbox = Addr-Spec => [[ f swap <mailbox> ]] | Named-Addr-Spec
;EBNF
: >mailbox ( string -- mailbox/f )
[ email-ebnf ] [ 2drop f ] recover ;
New Annotation