/* lil-gp Genetic Programming System, version 1.0, 11 July 1995 * Copyright (C) 1995 Michigan State University * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Douglas Zongker (zongker@isl.cps.msu.edu) * Dr. Bill Punch (punch@isl.cps.msu.edu) * * Computer Science Department * A-714 Wells Hall * Michigan State University * East Lansing, Michigan 48824 * USA * */ #include /* pretty_print_tree() * * print a tree as an S-expression, indenting functions to show * structure. */ void pretty_print_tree ( lnode *data, FILE *fil ) { lnode *l = data; int *indent; int *istep; /* indent is a table, parallel to the tree's array, of indentation values. */ indent = (int *)MALLOC ( (tree_nodes(data)+1) * sizeof(int) ); istep = indent; /* fill the indentation table. */ gen_indents ( &l, &istep, 0, 1 ); istep = indent; l = data; /* now print the tree using the indentation table. */ pretty_print_tree_recurse ( &l, &istep, fil ); fprintf ( fil, "\n" ); FREE ( indent ); } /* pretty_print_tree_recurse() * * recursive tree printer, using a table of indentations. */ void pretty_print_tree_recurse ( lnode **l, int **is, FILE *fil ) { int i; function *f; f = (**l).f; /** a positive indentation value means move to the next line and print that many spaces before the function name. */ if ( **is >= 0 ) { fprintf ( fil, "\n" ); for ( i = 0; i < **is; ++i ) fprintf ( fil, " " ); } ++*l; ++*is; /** for terminals, don't print parens. **/ if ( f->arity == 0 ) { if ( f->ephem_gen ) { /* show value of ERCs. */ fprintf ( fil, " %s", (f->ephem_str)((**l).d->d) ); ++*l; } else /* show name of other terminals. */ fprintf ( fil, " %s", f->string ); return; } /* print function name with a parenthesis. */ fprintf ( fil, " (%s", f->string ); switch ( f->type ) { case FUNC_DATA: case EVAL_DATA: /* recursively print children. */ for ( i = 0; i < f->arity; ++i ) pretty_print_tree_recurse ( l, is, fil ); break; case FUNC_EXPR: case EVAL_EXPR: /* recursively print children, ignoring skip nodes. */ for ( i = 0; i < f->arity; ++i ) { ++*l; pretty_print_tree_recurse ( l, is, fil ); } break; } /* print matching parenthesis. */ fprintf ( fil, ")" ); } /* gen_indents() * * generates a table of indentations -- positive numbers indicate skipping * to next line and indenting that much, negative indicate continuing current * line. the result should look like: * * (function terminal * (function terminal * terminal) * terminal) */ void gen_indents ( lnode **l, int **is, int start, int sameline ) { function *f = (**l).f; int i; /** sameline is true for the first child of a function. first children and terminals always go on the same line as their parent. **/ if ( sameline || f->arity == 0 ) **is = -start; else **is = start; ++*is; ++*l; if ( f->arity == 0 ) { if ( f->ephem_gen ) /* skip the value of an ERC. */ ++*l; return; } /* move forward the length of the function name plus a space plus a '('. */ start += strlen ( f->string ) + 2; switch ( f->type ) { case FUNC_DATA: case EVAL_DATA: /* generate children's indents. */ for ( i = 0; i < f->arity; ++i ) gen_indents ( l, is, start, i==0 ); break; case FUNC_EXPR: case EVAL_EXPR: /* generate children's indents, ignoring skip nodes. */ for ( i = 0; i < f->arity; ++i ) { ++*l; gen_indents ( l, is, start, i==0 ); } break; } }