lex token c_single_lit /( 'L'? "'" ( [^'\\\n] | '\\' any )* "'" )/ token c_double_lit /( 'L'? '"' ( [^"\\\n] | '\\' any )* '"' )/ token sym / ';' | ',' | '=' | '(' | ')' | ':' | '&' | '*' | '[' | ']' | '~' | '+' | '-' | '/' | '<' | '>' | '|' | '^' | '%' | '!' | '?' | '.' | '#'/ # Identifiers token c_id /( [a-zA-Z_] [a-zA-Z0-9_]* )/ # Comments and whitespace. token comm_c /( '/*' (any | '\n')* :>> '*/' )/ token comm_cxx /( '//' any* :> '\n' )/ token ws /( any - 33..126 )+/ end def c_token [c_single_lit] | [c_double_lit] | [sym] | [c_id] | [comm_c] | [comm_cxx] | [ws] def c_token_list [c_token c_token_list] | [c_token] # Can parse this, use ful for single constructs. def c [c_token*] literal '%%' lex literal '{', '}' literal 'protocol', 'client', 'server', 'port', 'by', 'tcp', 'udp' token id /[A-Za-z_][A-Za-z_0-9]*/ token number /[0-9]+/ ignore /'/*' any* :>> '*/'/ ignore /[ \t\r\n]+/ end def tcp_by_port ['tcp' 'by' 'port'] def udp_by_port ['udp' 'by' 'port'] def attribute ['client' id] | ['server' id] | ['port' number] | ['udp' id] | [tcp_by_port] | [udp_by_port] def tcp_protocol ['tcp' 'protocol' id '{' attribute* '}'] def udp_protocol ['udp' 'protocol' id '{' attribute* '}'] def protocol [tcp_protocol] | [udp_protocol] def program [c '%%' protocol*] alias output accum def port Port: int Protocol: str [] # Parse the input. parse PP: program[ stdin ] P: program = PP.tree Output: output Output = construct output [] # Take off the leading C from the input file and send it out. match P [C: c '%%' protocol*] Output << [$C] Output << "#include " print( Output.finish() )