##### LM ##### 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 ) { return parse start[ InputFile ] } start parseTxt( T: str ) { cons a: accum[] send a [T] eos return a.tree } item* concatItems( IL1: item* IL2: item* ) { for IL: item* in IL1 { if match IL [] { IL = IL2 break } } return IL1 } item* expandIncludes( ItemList: ref ) { 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() ##### IN ##### %% include smtp.vpt ##### EXP #####