#include "soul.h"
static string chunk;
static mapping soul_data;
void error(string msg) {
write(msg + "\n");
if (chunk) {
write(" at " + chunk[0 .. 70] + "\n");
}
destruct(this_object());
}
varargs void
update_commands(string file, mapping soul_mapping) {
string soul_definition, *soul_cmds;
/*
* This is horrible. The alternatives are worse.
*/
soul_definition = read_file(file);
if (soul_definition) {
soul_data = soul_mapping;
soul_definition = implode(explode(soul_definition, "\t"), "");
soul_cmds = explode(soul_definition, "\n");
soul_cmds = map_array(soul_cmds, "remove_indentation", this_object());
soul_cmds = explode(implode(soul_cmds, ""), "$$");
filter_array(soul_cmds, "distribute_decoding", this_object());
} else {
error("read_file("+file+") failed");
}
}
string remove_whitespace(string str) {
while (sscanf(str, " %s", str));
sscanf(str, " %s", str);
sscanf(str, " %s", str);
return str;
}
string remove_indentation(string str) {
str = remove_whitespace(str);
if (!(['(' : 1, '[' : 1, '*' : 1])[str[0]]) {
return str;
}
return " " + str;
}
void distribute_decoding(string chunk) {
call_out("define_action", 0, chunk);
}
mixed parse_chunk(); /* Arrrgh primal scream hate prototypes */
void parse_assoc(mapping map) {
string index;
mixed value;
/*
* An assoc is on the form (index value) where only value may recurse.
*/
if (sscanf(chunk, "(%s %s", index, chunk) < 2) {
error("parse_assoc() failed at sscanf()");
}
value = parse_chunk();
chunk = extract(chunk, 1);
if (map == soul_data) {
write ("Adding soul_command : " + index + ".\n");
}
map[index] = value;
}
string *parse_array() {
string values;
/*
* The array is of format [val1 val2 val3] where none may recurse.
*/
if (sscanf(chunk, "[%s]%s", values, chunk) != 2) {
error("parse_array() failed at sscanf()");
}
return map_array(explode(values, " "), "fix_macros", this_object());
}
mixed fix_macros(string foo) {
if (foo[0] == '$') {
switch(foo) {
case "$ADJ" : return ADJ;
case "$TP_NAME" : return TP_NAME;
case "$OB_NAME" : return OB_NAME;
case "$TP_PRONOUN" : return TP_PRONOUN;
case "$OB_PRONOUN" : return OB_PRONOUN;
case "$TP_POSS" : return TP_POSSESSIVE;
case "$OB_POSS" : return OB_POSSESSIVE;
case "$TP_NPOSS" : return TP_NPOSS;
case "$OB_NPOSS" : return OB_NPOSS;
case "$OB_FOO" : return OB_FOO;
case "$TP_FOO" : return TP_FOO;
}
}
return foo;
}
mapping parse_mapping() {
mapping map;
int i;
/*
* The mapping is of format *( assoc assoc assoc )
* Here we must singlestep and trust the other routines to be robust!
*/
map = ([ ]);
if (!sscanf(chunk, "*(%s", chunk)) {
error("sscanf in parse_mapping failed");
}
while ((chunk = remove_whitespace(chunk))[0] != ')') {
parse_assoc(map);
}
chunk = extract(chunk, 1);
return map;
}
mixed parse_chunk() {
string value;
chunk = remove_whitespace(chunk);
switch(chunk[0]) {
case '*' : return parse_mapping();
case '[' : return parse_array();
case '(' : error("parse_assoc() wanted from parse_chunk()");
}
if (sscanf(chunk, "%s)%s", value, chunk) == 2) {
return value;
}
error("sscanf() failed in parse_chunk");
}
void define_action(string cmd_def) {
chunk = remove_whitespace(cmd_def);
parse_assoc(soul_data);
}