# # Character classes # rl CTL /0..31 | 127/ rl CR /13/ rl LF /10/ rl SP /32/ rl HT /9/ rl CHAR /0..127/ rl separators / '(' | ')' | '<' | '>' | '@' | ',' | ';' | ':' | '\\' | '"' | '/' | '[' | ']' | '?' | '=' | '{' | '}' | SP | HT / rl token_char /CHAR - CTL - separators/ # # Literal tokens # literal 'HTTP/', ' ', ':' token CRLF /CR LF/ # # Request Line # token method /token_char+/ token request_uri /(^SP)+/ token http_number /digit+ '.' digit+/ def http_version [ 'HTTP/' http_number ] def request_line [method ' ' request_uri ' ' http_version CRLF] # # Header # token field_name /token_char+/ lex field_value { token fv_plain /(^(CR|LF))*/ token fv_ext /CR LF (SP|HT)/ token fv_term /CR LF/ } def fv [fv_plain] | [fv_ext] def field_value [fv* fv_term] def header [field_name ':' field_value] # # Request # def request [request_line header* CRLF] parse R: request*( stdin ) if !R { print( error() ) exit( 1 ) } for FV: fv in R { if match FV [fv_ext] FV = cons fv " " } print( R )