/*
 * "syntax hilighting"
 *
 * well, not really, but it does colorize keywords and stuff.
 *
 * Just a quick hack to show a way of doing this with parse_string
 *
 * Bugs: it doesn't handle quoted strings
 *       it doesn't handle comments
 *       and probably some others
 */

string grammar;

/*
 * build a grammar
 *
 * Call this after changing the data mapping or other parts of the grammar
 * (and recompiling if appropriate)
 *
 */
void build_grammar() {
  mapping data;
  string *keys;
  int x, y, num_keys, sz;
  
  /*
   * in a mapping, so we could later add/remove things to color 'classes' without
   * having to recompile
   */
  data = ([
    "statements" : ({
      "break", "case", "continue", "default", "do", "else",
      "for", "foreach", "goto", "if", "in", "inherit", "return",
      "sizeof", "switch", "while"
    }),
    "pre_comp" : ({
      "#define", "#else", "#endif", "#if", "#ifdef", "#include" 
    }),
    "types" : ({
      "char", "enum", "float", "int", "array", "private",
      "mapping", "mixed", "object", "static", "string",
      "typedef", "union", "varargs", "void"
    }),
    "kfuns" : ({
      "acos", "act_mxp", "add_action", "all_inventory", "allocate",
      "allocate_buffer", "allocate_mapping", "asin", "assemble_class", "atan",
      "author_stats", "bind", "bufferp", "cache_stats", "call_other",
      "call_out_info", "call_stack", "ceil", "children", "classp", "clear_bit",
      "this_object", "this_player", "throw", "time", "to_float", "to_int", "typeof",
      "undefinedp", "unique_array", "unique_mapping", "upper_case", "uptime",
      "userp", "values", "variables", "virtualp", "write_buffer", "write_bytes",
      "write_file", "zonetime"
    }),
    "safuns" : ({
      "abs", "absolute_path", "absolute_value", "add", "add_article",
      "add_event", "add_maps", "add_sky_event", "admin_email", "adminp",
      "append_line", "architecture", "archp", "arrange_string", "arrcmp", "assistp",
      "valid_timezone", "version", "visibility", "visible", "web_translate",
      "wild_card", "wipe_inv", "wizardp", "wrap", "write", "year"
    }),
    "lfuns" : ({
      "eventTellHist","CanRemoveItem","GetDummyItems","direct_annihilate_liv",
      "direct_listen_to_str_word_obj","direct_missile_liv","GetVoteStatus",
      "GetRiders","GetLivingMaxCarry","CanManipulate","SaveObject","GetCreatorBirth",
      "GetRandomLimb","direct_createfix","RestoreLimb","eventSteal","direct_remedy_liv",
      "eventQueueCommand"
    })
  ]);

  /*
   * the different kinds of keywords/statements
   */
  keys = map_indices( data );

  /*
   * Handling of quoted strings could be added here
   */
  grammar = "";

  /*
   * Loop through all keys of the data mapping
   */
  for( x = 0, num_keys = sizeof( keys ); x < num_keys; x++ ) {
    /*
     * loop through the list of words for each key
     */
    for( y = 0, sz = sizeof( data[keys[x]] ); y < sz; y++ ) {
      /*
       * add key=/word/ to the grammar
       */
      grammar += keys[x] + "=/"+data[keys[x]][y]+"/ ";
    }
  }

  /*
   * a token that matches everything else, followed by
   * some stuff to define what a stream of tokens looks like,
   * followed by production rules to map different classes to
   * their colors.
   */
  grammar += "unknown = nomatch "+
             "line: words " +
             "words: word " +
             "words: words word " +
             "word: green " +
             "word: blue " +
             "word: red " +
             "word: cyan " +
             "word: magenta " +
             "word: yellow " +
             "word: unknown " +
             "green: statements ? greenme " +
             "blue: pre_comp ? blueme " +
             "red: types ? redme " +
             "cyan: kfuns ? cyanme " +
             "magenta: safuns ? magentame " +
             "yellow: lfuns ? yellowme";

}

/*
 * Some functions that handle adding the colors
 */
mixed * greenme( mixed * arg ) {
  return ({ "%^GREEN%^" + arg[0] + "%^RESET%^" });
}

mixed * blueme( mixed * arg ) {
  return ({ "%^BLUE%^" + arg[0] + "%^RESET%^" });
}

mixed * redme( mixed * arg ) {
  return ({ "%^RED%^" + arg[0] + "%^RESET%^" });
}

mixed * cyanme( mixed * arg ) {
  return ({ "%^CYAN%^" + arg[0] + "%^RESET%^" });
}

mixed * magentame( mixed * arg ) {
  return ({ "%^MAGENTA%^" + arg[0] + "%^RESET%^" });
}

mixed * yellowme( mixed * arg ) {
  return ({ "%^YELLOW%^" + arg[0] + "%^RESET%^" });
}

/*
 * call this with a filename
 */
void testme( string file ) {
  string stuff;

  if(!grammar) {
    build_grammar();
    write("built grammar: "+grammar);
  }
  stuff = read_file( file );

  write( implode( parse_string( grammar, stuff ), "" ) );
}

