lex literal 'type', 'include' token id /[A-Za-z_][A-Za-z_0-9]*/ ignore /'#' [^\n]* '\n'/ ignore /[ \t\r\n]+/ end lex token ifn_part /[a-zA-Z0-9_.\-]+/ token ifn_slash /'/'/ end def ifn_path_part [ifn_part] | [ifn_slash] def ifn_path [ifn_path_part ifn_path] | [ifn_path_part] literal '%%' lex token em_ws /( any - 33..126 )+/ end def em_item [em_ws] def prelude [em_item* '%%'] def item ['include' ifn_path] | ['type' id] def start [prelude item*] start parseStart( InputFile: stream ) { parse P: start[ InputFile ] return P.tree } start parseTxt( T: str ) { cons a: accum[] send a [T ] return a.finish() } item* concatItems( IL1: item* IL2: item* ) { for IL: item* in IL1 { if match IL [] { IL = IL2 break } } return IL1 } item* expandIncludes( ItemList: ref item* ) { for IL: item* in ItemList { if match IL ['include' FN: ifn_path Rest: item*] { S: start = parseTxt( " "%% " ) match S [em_item* '%%' IncludedItems: item*] IL = concatItems( IncludedItems Rest ) } } } int main() { S: start = parseStart(stdin) match S [em_item* '%%' ItemList: item*] expandIncludes( ItemList ) } main()