diff --git a/lib/7.2/modules/.autodoc b/lib/7.2/modules/.autodoc deleted file mode 100644 index 5a529781a06a7aef06aa6cb1f91ccc3fbf823d4e..0000000000000000000000000000000000000000 --- a/lib/7.2/modules/.autodoc +++ /dev/null @@ -1 +0,0 @@ -7.2:: diff --git a/lib/7.2/modules/Gmp.pmod b/lib/7.2/modules/Gmp.pmod deleted file mode 100644 index 8c7710355202e2c4d689876108ca706416d1661e..0000000000000000000000000000000000000000 --- a/lib/7.2/modules/Gmp.pmod +++ /dev/null @@ -1,9 +0,0 @@ -#pike 7.3 - -// -// Pike 7.2 backward compatibility layer. -// - -inherit Gmp; - -constant pow = predef::pow; diff --git a/lib/7.2/modules/LR.pmod/Grammar_parser.pmod b/lib/7.2/modules/LR.pmod/Grammar_parser.pmod deleted file mode 100755 index d960c24c743db392291472ca48591be612bb34e3..0000000000000000000000000000000000000000 --- a/lib/7.2/modules/LR.pmod/Grammar_parser.pmod +++ /dev/null @@ -1,385 +0,0 @@ - -#pike 7.2 - -/* - * Generates a parser from a textual specification. - * - * Henrik Grubbstr�m 1996-12-06 - */ - -//! This module generates an LR parser from a grammar specified according -//! to the following grammar: -//! -//! @pre{ -//! directives : directive ; -//! directives : directives directive ; -//! directive : declaration ; -//! directive : rule ; -//! declaration : "%token" terminals ";" ; -//! rule : nonterminal ":" symbols ";" ; -//! rule : nonterminal ":" symbols action ";" ; -//! symbols : symbol ; -//! symbols : symbols symbol ; -//! terminals : terminal ; -//! terminals : terminals terminal ; -//! symbol : nonterminal ; -//! symbol : "string" ; -//! action : "{" "identifier" "}" ; -//! nonterminal : "identifier" ; -//! terminal : "string"; -//! @} - -/* - * Includes - */ - -#include <stdio.h> - -/* - * Defines - */ - -/* #define DEBUG */ - -/* Errors during parsing */ -/* Action for rule is missing from master object */ -#define ERROR_MISSING_ACTION 256 -/* Action for rule is not a function */ -#define ERROR_BAD_ACTION 512 - -import LR; - -protected private object(parser) _parser = parser(); - -/* - * Scanner - */ - -protected private class scan { - string str = ""; - int pos; - - array|string scan() - { - while (1) { - if (pos >= sizeof(str)) { - /* EOF */ - return(""); - } else { - int start=pos++; - switch (str[start]) { - case '%': - /* Token */ - while ((pos < sizeof(str)) && - ((('A' <= str[pos]) && ('Z' >= str[pos])) || - (('a' <= str[pos]) && ('z' >= str[pos])))) { - pos++; - } - return (lower_case(str[start..pos-1])); - case '\"': - /* String */ - while ((pos < sizeof(str)) && - (str[pos] != '\"')) { - if (str[pos] == '\\') { - pos++; - } - pos++; - } - if (pos < sizeof(str)) { - pos++; - } else { - pos = sizeof(str); - } - if (start != pos-2) { - return ({ "string", str[start+1..pos-2] }); - } - /* Throw away empty strings (EOF) */ - break; - case '/': - /* Comment */ - if (str[pos] != '*') { - werror(sprintf("Bad token \"/%c\" in input\n", str[pos])); - break; - } - pos++; - while (1) { - if ((++pos >= sizeof(str)) || - (str[pos-1 .. pos] == "*/")) { - pos++; - break; - } - } - break; - case '(': - return("("); - case ')': - return(")"); - case '{': - return("{"); - case '}': - return("}"); - case ':': - return(":"); - case ';': - return(";"); - case '\n': - case '\r': - case ' ': - case '\t': - /* Whitespace */ - break; - case '0'..'9': - /* int */ - while ((pos < sizeof(str)) && - ('0' <= str[pos]) && ('9' >= str[pos])) { - pos++; - } - return (({ "int", (int)str[start .. pos-1] })); - default: - /* Identifier */ - while ((pos < sizeof(str)) && - ((('A' <= str[pos]) && ('Z' >= str[pos])) || - (('a' <= str[pos]) && ('z' >= str[pos])) || - (('0' <= str[pos]) && ('9' >= str[pos])) || - ('_' == str[pos]) || (str[pos] >= 128))) { - pos++; - } - return (({ "identifier", str[start .. pos-1] })); - } - } - } - } -} - -protected private object(scan) scanner = scan(); - -protected private array(string) nonterminals = ({ - "translation_unit", - "directives", - "directive", - "declaration", - "rule", - "symbols", - "terminals", - "symbol", - "action", - "nonterminal", - "terminal", - "priority", -}); - -protected private object(ADT.Stack) id_stack = ADT.Stack(); - -protected private mapping(string:int) nonterminal_lookup = ([]); - -protected private object(parser) g; - -protected private object master; - -//! Error code from the parsing. -int error; - -protected private int add_nonterminal(string id) -{ - int nt = nonterminal_lookup[id]; - - if (!nt) { - nt = nonterminal_lookup[id] = id_stack->ptr; - id_stack->push(id); - } - return(nt); -} - -protected private void add_tokens(array(string) tokens) -{ - /* NOOP */ -} - -protected private void set_left_tokens(string ignore, int pri_val, array(string) tokens) -{ - foreach (tokens, string token) { - g->set_associativity(token, -1); /* Left associative */ - g->set_priority(token, pri_val); - } -} - -protected private string internal_symbol_to_string(int|string symbol) -{ - if (intp(symbol)) { - return (nonterminals[symbol]); - } else { - return ("\"" + symbol + "\""); - } -} - -protected private string symbol_to_string(int|string symbol) -{ - if (intp(symbol)) { - if (symbol < id_stack->ptr) { - return (id_stack->arr[symbol]); - } else { - /* Only happens with the initial(automatic) rule */ - return ("nonterminal"+symbol); - } - } else { - return ("\""+symbol+"\""); - } -} - -protected private void add_rule(int nt, string colon, array(mixed) symbols, string action) -{ - if (action == ";") { - action = 0; - } - if ((action) && (master)) { - if (!master[action]) { - werror(sprintf("Warning: Missing action %s\n", action)); - - error |= ERROR_MISSING_ACTION; - } else if (!functionp(master[action])) { - werror(sprintf("Warning: \"%s\" is not a function in object\n", - action)); - - error |= ERROR_BAD_ACTION; - } else { - g->add_rule(rule(nt, symbols, master[action])); - return; - } - } - g->add_rule(rule(nt, symbols, action)); -} - -void create() -{ - _parser->set_symbol_to_string(internal_symbol_to_string); - - _parser->verbose = 0; - - _parser->add_rule(rule(0, ({ 1, "" }), 0)); /* translation_unit */ - _parser->add_rule(rule(1, ({ 2 }), 0)); /* directives */ - _parser->add_rule(rule(1, ({ 1, 2 }), 0)); /* directives */ - _parser->add_rule(rule(2, ({ 3 }), 0)); /* directive */ - _parser->add_rule(rule(2, ({ 4 }), 0)); /* directive */ - _parser->add_rule(rule(3, ({ "%token", 6, ";" }), - add_tokens)); /* declaration */ - _parser->add_rule(rule(3, ({ "%left", 11, 6, ";" }), - set_left_tokens)); /* declaration */ - _parser->add_rule(rule(4, ({ 9, ":", 5, ";" }), - add_rule)); /* rule */ - _parser->add_rule(rule(4, ({ 9, ":", 5, 8, ";" }), - add_rule)); /* rule */ - _parser->add_rule(rule(5, ({}), - lambda () { - return ({}); } )); /* symbols */ - _parser->add_rule(rule(5, ({ 5, 7 }), - lambda (array x, mixed|void y) { - if (y) { return (x + ({ y })); } - else { return (x); }} )); /* symbols */ - _parser->add_rule(rule(6, ({ 10 }), - lambda (string x) { - return ({ x }); } )); /* terminals */ - _parser->add_rule(rule(6, ({ 6, 10 }), - lambda (array(string) x, string y) { - return (x + ({ y })); } )); /* terminals */ - _parser->add_rule(rule(7, ({ 9 }), 0 )); /* symbol */ - _parser->add_rule(rule(7, ({ 10 }), 0 )); /* symbol */ - _parser->add_rule(rule(8, ({ "{", "identifier", "}" }), - lambda (mixed brace_l, string id, mixed brace_r) { - return (id); } )); /* action */ - _parser->add_rule(rule(8, ({ "{", "string", "}" }), - lambda (mixed brace_l, string str, mixed brace_r) { - werror(sprintf("Warning: Converting string \"%s\" " - "to identifier\n", str)); - return(str); } )); /* action */ - _parser->add_rule(rule(9, ({ "identifier" }), - add_nonterminal)); /* nonterminal */ - _parser->add_rule(rule(10, ({ "string" }), 0)); /* terminal */ - _parser->add_rule(rule(11, ({ "(", "int", ")" }), - lambda (mixed paren_l, int val, mixed paren_r) { - return (val); - } )); /* priority */ - _parser->add_rule(rule(11, ({}), 0)); /* priority */ - - _parser->compile(); -} - -//! Compiles the parser-specification given in the first argument. -//! Named actions are taken from the object if available, otherwise -//! left as is. -//! -//! @bugs -//! Returns error-code in both Grammar_parser.error and -//! return_value->error. -object(parser) make_parser(string str, object|void m) -{ - object(parser) res = 0; - - master = m; - error = 0; /* No errors yet */ - - g = parser(); - - scanner->str = str; - scanner->pos = 0; - - g->set_symbol_to_string(symbol_to_string); - - id_stack = ADT.Stack(); - - nonterminal_lookup = ([]); - -#ifdef DEBUG - _parser->verbose = 1; - g->verbose = 1; -#else - g->verbose = 0; -#endif /* DEBUG */ - - /* Default rule -- Will never be reduced */ - id_stack->push("Translation Unit"); /* Nonterminal #0 -- Start symbol */ - g->add_rule(rule(0, ({ 1, "" }), 0)); /* Rule #0 -- Start rule */ - - _parser->parse(scanner->scan); - - if ((!_parser->error) && - (!error) && - (!g->compile())) { - res = g; - } - - g = 0; /* Don't keep any references */ - - return (res); -} - -//! Compiles the file specified in the first argument into an LR parser. -//! -//! @seealso -//! @[make_parser] -int|object(parser) make_parser_from_file(string fname, object|void m) -{ - return make_parser(Stdio.read_file(fname), m); -} - -/* - * Syntax-checks and compiles the grammar files - */ -int main(int argc, array(string) argv) -{ - if (argc == 1) { - werror(sprintf("Usage:\n\t%s <files>\n", argv[0])); - } else { - int i; - - for (i=1; i < argc; i++) { - werror(sprintf("Compiling \"%s\"...\n", argv[i])); - - int|object(parser) g = make_parser_from_file(argv[i]); - if (error || !g) { - werror("Compilation failed\n"); - } else { - werror("Compilation done\n"); - } - } - } -} diff --git a/lib/7.2/modules/LR.pmod/item.pike b/lib/7.2/modules/LR.pmod/item.pike deleted file mode 100644 index 1f2798f50e4794360e57c1918ecec0e77c89e011..0000000000000000000000000000000000000000 --- a/lib/7.2/modules/LR.pmod/item.pike +++ /dev/null @@ -1,47 +0,0 @@ -/* - * An LR(0) item - * - * Henrik Grubbstr�m 1996-11-27 - */ - -#pike 7.2 - -//! -//! An LR(0) item, a partially parsed rule. -//! - -import LR; - -/* constant kernel = (program)"kernel"; */ -/* constant item = (program)"item"; */ - -//! The rule -object(rule) r; - -//! How long into the rule the parsing has come. -int offset; - -//! The state we will get if we shift according to this rule -object /* (kernel) */ next_state; - -//! Item representing this one (used for shifts). -object /* (item) */ master_item; - -//! Look-ahead set for this item. -multiset(string) direct_lookahead = (<>); - -//! Look-ahead set used for detecting conflicts -multiset(string) error_lookahead = (<>); - -//! Relation to other items (used when compiling). -multiset(object /* (item) */ ) relation = (<>); - -//! Depth counter (used when compiling). -int counter; - -//! Item identification number (used when compiling). -int number; - -//! Used to identify the item. -//! Equal to r->number + offset. -int item_id; diff --git a/lib/7.2/modules/LR.pmod/lr.pike b/lib/7.2/modules/LR.pmod/lr.pike deleted file mode 100755 index e029e2e2b40a77fc2bea18d33b0b7ebf22fe2d15..0000000000000000000000000000000000000000 --- a/lib/7.2/modules/LR.pmod/lr.pike +++ /dev/null @@ -1,183 +0,0 @@ - -/* - * An LR(1) Parser in Pike - * - * Henrik Grubbstr�m 1996-11-23 - */ - -#pike 7.2 - -import LR; - -object(parser) g; - -/* - * Test actions - */ - -int add_values(int x, mixed ignore, int y) -{ - werror(x+" + "+y+" = "+(x+y)+"\n"); - return (x+y); -} - -int mul_values(int x, mixed ignore, int y) -{ - werror(x+" * "+y+" = "+(x*y)+"\n"); - return (x*y); -} - -int get_second_value(mixed ignored, int x, mixed ... ignored_also) -{ - return(x); -} - -int concat_values(int x, int y) -{ - return (x*10 + y); -} - -int make_value(string s) -{ - return((int)s); -} - -/* - * Test grammar - */ - -array(string) nonterminals = ({ - "E'", "E", "T", "F", "id", "value", -}); - -array(array(string|int)) g_init = ({ - ({ 0, 1, "" }), - ({ 1, 1, "+", 2 }), - ({ 1, 2 }), - ({ 2, 2, "*", 3 }), - ({ 2, 3 }), - ({ 3, "(", 1, ")" }), - ({ 3, 4 }), - ({ 4, 5 }), - ({ 4, 4, 5 }), - ({ 5, "0" }), - ({ 5, "1" }), - ({ 5, "2" }), - ({ 5, "3" }), - ({ 5, "4" }), - ({ 5, "5" }), - ({ 5, "6" }), - ({ 5, "7" }), - ({ 5, "8" }), - ({ 5, "9" }), -}); - -array(int|function(mixed ...:mixed)) action_init = ({ - 0, - add_values, - 0, - mul_values, - 0, - get_second_value, - 0, - 0, - concat_values, - make_value, - make_value, - make_value, - make_value, - make_value, - make_value, - make_value, - make_value, - make_value, - make_value, -}); - -/* - * Test action - */ -string a_init(string ... args) -{ - if (sizeof(args)) { - werror(sprintf("Reducing %s => \"%s\"\n", - Array.map(args, g->symbol_to_string) * ", ", - args * "")); - return (`+(@args)); - } else { - /* Empty rule */ - werror("Reducing /* empty */ => \"\"\n"); - return(""); - } -} - -string symbol_to_string(int|string symbol) -{ - if (intp(symbol)) { - if (symbol < sizeof(nonterminals)) { - return(nonterminals[symbol]); - } else { - return("nonterminal"+symbol); - } - } else { - return("\""+symbol+"\""); - } -} - -void create() -{ - g = parser(); - - g->set_symbol_to_string(symbol_to_string); - - foreach (indices(g_init), int i) { - g->add_rule(rule(g_init[i][0], g_init[i][1..], action_init[i])); - } -} - -class scan { - /* - * Test input - */ - - array(string) s_init = ({ - "1", "*", "(", "3", "+", "2", ")", "+", "2", "*", "3", - "", - }); - - int s_pos = 0; - - string scan() - { - return(s_init[s_pos++]); - } -} - -object(scan) scanner = scan(); - -int main(int argc, array(string) argv) -{ - mixed result; - - werror("Grammar:\n\n" + (string) g); - -#if constant(_memory_usage) - werror(sprintf("Memory usage:\n%O\n", _memory_usage())); -#endif - - werror("Compiling...\n"); - - g->verbose = 0; - - g->compile(); - - werror("Compilation finished!\n"); - -#if constant(_memory_usage) - werror(sprintf("Memory usage:\n%O\n", _memory_usage())); -#endif - - result = g->parse(scanner->scan); - - werror(sprintf("Result of parsing: \"%s\"\n", result + "")); -} diff --git a/lib/7.2/modules/LR.pmod/parser.pike b/lib/7.2/modules/LR.pmod/parser.pike deleted file mode 100644 index 76a84d020fad3d91004d8977dbbc84bf1e96edec..0000000000000000000000000000000000000000 --- a/lib/7.2/modules/LR.pmod/parser.pike +++ /dev/null @@ -1,1520 +0,0 @@ -/* - * A BNF-grammar in Pike. - * Compiles to a LALR(1) state-machine. - * - * Henrik Grubbstr�m 1996-11-24 - */ - -#pike 7.2 - -//! This object implements an LALR(1) parser and compiler. -//! -//! Normal use of this object would be: -//! -//! @pre{ -//! {add_rule, set_priority, set_associativity}* -//! set_symbol_to_string -//! compile -//! {parse}* -//! @} - -/* - * Includes - */ - -import Array; - -/* - * Defines - */ - -/* Errors during parsing */ -/* Unexpected EOF */ -#define ERROR_EOF 1 -/* Syntax error in input */ -#define ERROR_SYNTAX 2 -/* Shift-Reduce or Reduce-Reduce */ -#define ERROR_CONFLICTS 4 -/* Action is missing from action object */ -#define ERROR_MISSING_ACTION 8 -/* Action is not a function */ -#define ERROR_BAD_ACTION_TYPE 16 -/* Action invoked by name, but no object given */ -#define ERROR_NO_OBJECT 32 -/* Scanner not set */ -#define ERROR_NO_SCANNER 64 -/* Missing definition of nonterminal */ -#define ERROR_MISSING_DEFINITION 128 - -import LR; - -/* - * Classes - */ - -//! Implements an LR(1) state -class kernel { - - //! Used to check if a rule already has been added when doing closures. - multiset(object(rule)) rules = (<>); - - //! Contains the items in this state. - array(object(item)) items = ({}); - - //! Used to lookup items given rule and offset - mapping(int:object(item)) item_id_to_item = ([]); - - //! Contains the items whose next symbol is this non-terminal. - mapping(int : multiset(object(item))) symbol_items = ([]); - - //! The action table for this state - //! - //! @pre{ - //! object(kernel) SHIFT to this state on this symbol. - //! object(rule) REDUCE according to this rule on this symbol. - //! @} - mapping(int|string : object(kernel)|object(rule)) action = ([]); - - //! The symbols that closure has been called on. - multiset closure_set = (<>); - - /* - * Functions - */ - - //! Add an item to the state. - void add_item(object(item) i) - { - int|string symbol; - - items += ({ i }); - item_id_to_item[i->item_id] = i; - - if (i->offset < sizeof(i->r->symbols)) { - symbol = i->r->symbols[i->offset]; - - if (symbol_items[symbol]) { - symbol_items[symbol][i] = 1; - } else { - symbol_items[symbol] = (< i >); - } - } - } - - //! Make the closure of this state. - //! - //! @param nonterminal - //! Nonterminal to make the closure on. - void closure(int nonterminal) - { - closure_set[nonterminal] = 1; - if (grammar[nonterminal]) { - foreach (grammar[nonterminal], object(rule) r) { - if (!rules[r]) { - - object(item) new_item = item(); - - new_item->r = r; - new_item->item_id = r->number; - - // Not needed, since 0 is the default. - // new_item->offset = 0; - // rules[r] is set by the post-increment above. - rules[r] = 1; - - add_item(new_item); - - if (sizeof(r->symbols) && intp(r->symbols[0]) && - !closure_set[r->symbols[0]]) { - closure(r->symbols[0]); - } - } - } - } else { - werror(sprintf("Error: Definition missing for non-terminal %s\n", - symbol_to_string(nonterminal))); - error |= ERROR_MISSING_DEFINITION; - } - } - - //! Make the goto-set of this state. - multiset(int|string) goto_set() - { - multiset(int|string) set = (<>); - - foreach (items, object(item) i) { - if (i->offset != sizeof(i->r->symbols)) { - set[i->r->symbols[i->offset]] = 1; - } - } - - if (verbose) { - werror(sprintf("goto_set()=> (< %s >)\n", - map(indices(set), symbol_to_string) * ", ")); - } - - return (set); - } - - //! Generates the state reached when doing goto on the specified symbol. - //! i.e. it compiles the LR(0) state. - //! - //! @param symbol - //! Symbol to make goto on. - object(kernel) do_goto(int|string symbol) - { - multiset(object(item)) items; - - if (verbose) { - werror(sprintf("Performing GOTO on <%s>\n", symbol_to_string(symbol))); - } - - items = symbol_items[symbol]; - if (items) { - array(int) item_ids = Array.map(sort(indices(items)->item_id), - `+, 1); - string kernel_hash = sprintf("%@4c", item_ids); - - object(kernel) new_state = known_states[kernel_hash]; - - if (!new_state) { - known_states[kernel_hash] = new_state = kernel(); - - foreach (indices(items), object(item) i) { - int|string lookahead; - - object(item) new_item = item(); - object(rule) r; - int offset = i->offset; - - new_item->offset = ++offset; - new_item->r = r = i->r; - new_item->item_id = r->number + offset; - - new_state->add_item(new_item); - - if ((offset != sizeof(r->symbols)) && - intp(lookahead = r->symbols[offset]) && - !new_state->closure_set[lookahead]) { - new_state->closure(lookahead); - } - } - - s_q->push(new_state); - } else { - // werror("Known state\n"); - } - /* DEBUG */ - - if (verbose) { - werror(sprintf("GOTO on %s generated state:\n%s\n", - symbol_to_string(symbol), - state_to_string(new_state))); - } - - /* !DEBUG */ - - if (items) { - foreach (indices(items), object(item) i) { - i->next_state = new_state; - } - } - } else { - werror(sprintf("WARNING: do_goto() on unknown symbol <%s>\n", - symbol_to_string(symbol))); - } - } - -}; - -//! This is a queue, which keeps the elements even after they are retrieved. -class state_queue { - - //! Index of the head of the queue. - int head; - - //! Index of the tail of the queue. - int tail; - - //! The queue itself. - array(object(kernel)) arr = allocate(64); - - //! Pushes the state on the queue. - //! - //! @param state - //! State to push. - object(kernel) push(object(kernel) state) - { - if (tail == sizeof(arr)) { - arr += allocate(tail); - } - arr[tail++] = state; - - return(state); - } - - //! Return the next state from the queue. - int|object(kernel) next() - { - if (head == tail) { - return(0); - } else { - return(arr[head++]); - } - } -} - -//! The grammar itself. -mapping(int|string : array(object(rule))) grammar = ([]); - -/* Priority table for terminal symbols */ -protected private mapping(string : object(priority)) operator_priority = ([]); - -protected private multiset(mixed) nullable = (< >); - - -/* Maps from symbol to which rules use that symbol - * (used for finding nullable symbols) - */ -protected private mapping(int : multiset(object(rule))) used_by = ([]); - -//! The initial LR0 state. -object(kernel) start_state; - -//! Verbosity level -//! -//! @int -//! @value 0 -//! None -//! @value 1 -//! Some -//! @endint -int verbose=1; - -//! Error code -int error=0; - -/* Number of next rule (used only for conflict resolving) */ -protected private int next_rule_number = 1; - -//! LR0 states that are already known to the compiler. -mapping(string:object(kernel)) known_states = ([]); - -/* - * Functions - */ - -/* Here are some help functions */ - -/* Several cast to string functions */ - -protected private string builtin_symbol_to_string(int|string symbol) -{ - if (intp(symbol)) { - return("nonterminal"+symbol); - } else { - return("\"" + symbol + "\""); - } -} - -protected private function(int|string : string) symbol_to_string = builtin_symbol_to_string; - -//! Pretty-prints a rule to a string. -//! -//! @param r -//! Rule to print. -string rule_to_string(object(rule) r) -{ - string res = symbol_to_string(r->nonterminal) + ":\t"; - - if (sizeof(r->symbols)) { - foreach (r->symbols, int|string symbol) { - res += symbol_to_string(symbol) + " "; - } - } else { - res += "/* empty */"; - } - return(res); -} - -//! Pretty-prints an item to a string. -//! -//! @param i -//! Item to pretty-print. -string item_to_string(object(item) i) -{ - array(string) res = ({ symbol_to_string(i->r->nonterminal), ":\t" }); - - if (i->offset) { - foreach(i->r->symbols[0..i->offset-1], int|string symbol) { - res += ({ symbol_to_string(symbol), " " }); - } - } - res += ({ "� " }); - if (i->offset != sizeof(i->r->symbols)) { - foreach(i->r->symbols[i->offset..], int|string symbol) { - res += ({ symbol_to_string(symbol), " " }); - } - } - if (sizeof(indices(i->direct_lookahead))) { - res += ({ "\t{ ", - map(indices(i->direct_lookahead), symbol_to_string) * ", ", - " }" }); - } - return(res * ""); -} - -//! Pretty-prints a state to a string. -//! -//! @param state -//! State to pretty-print. -string state_to_string(object(kernel) state) -{ - return (map(state->items, item_to_string) * "\n"); -} - -//! Pretty-prints the current grammar to a string. -string cast_to_string() -{ - array(string) res = ({}); - - foreach (indices(grammar), int nonterminal) { - res += ({ symbol_to_string(nonterminal) }); - foreach (grammar[nonterminal], object(rule) r) { - res += ({ "\t: " }); - if (sizeof(r->symbols)) { - foreach (r->symbols, int|string symbol) { - res += ({ symbol_to_string(symbol), " " }); - } - } else { - res += ({ "/* empty */" }); - } - res += ({ "\n" }); - } - res += ({ "\n" }); - } - return (res * ""); -} - -//! Implements casting. -//! -//! @param type -//! Type to cast to. -mixed cast(string type) -{ - if (type == "string") { - return(cast_to_string()); - } - throw(({ sprintf("Cast to %s not supported\n", type), backtrace() })); -} - -/* Here come the functions that actually do some work */ - -//! Sets the priority of a terminal. -//! -//! @param terminal -//! Terminal to set the priority for. -//! @param pri_val -//! Priority; higher = prefer this terminal. -void set_priority(string terminal, int pri_val) -{ - object(priority) pri; - - if (pri = operator_priority[terminal]) { - pri->value = pri_val; - } else { - operator_priority[terminal] = priority(pri_val, 0); - } -} - -//! Sets the associativity of a terminal. -//! -//! @param terminal -//! Terminal to set the associativity for. -//! @param assoc -//! Associativity; negative - left, positive - right, zero - no associativity. -void set_associativity(string terminal, int assoc) -{ - object(priority) pri; - - if (pri = operator_priority[terminal]) { - pri->assoc = assoc; - } else { - operator_priority[terminal] = priority(0, assoc); - } -} - -//! Sets the symbol to string conversion function. -//! The conversion function is used by the various *_to_string functions -//! to make comprehensible output. -//! -//! @param s_to_s -//! Symbol to string conversion function. -//! If zero or not specified, use the built-in function. -void set_symbol_to_string(void|function(int|string:string) s_to_s) -{ - if (s_to_s) { - symbol_to_string = s_to_s; - } else { - symbol_to_string = builtin_symbol_to_string; - } -} - -//! Add a rule to the grammar. -//! -//! @param r -//! Rule to add. -void add_rule(object(rule) r) -{ - int|string symbol; - - /* DEBUG */ - if (verbose) { - werror("Adding rule: " + rule_to_string(r) + "\n"); - } - - /* !DEBUG */ - - r->number = next_rule_number; - /* Reserve space for the items generatable from this rule. */ - next_rule_number += sizeof(r->symbols) + 1; - - /* First add the rule to the grammar */ - if (grammar[r->nonterminal]) { - grammar[r->nonterminal] += ({ r }); - } else { - grammar[r->nonterminal] = ({ r }); - } - - /* Then see if it is nullable */ - if (!r->has_tokens) { - object(ADT.Stack) new_nullables = ADT.Stack(1024); - - foreach (r->symbols, symbol) { - if (nullable[symbol]) { - r->num_nonnullables--; - } else { - if (used_by[symbol]) { - if (used_by[symbol][r]) { - /* Only count a symbol once */ - r->num_nonnullables--; - } else { - used_by[symbol][r] = 1; - } - } else { - used_by[symbol] = (< r >); - } - } - } - - if (!(r->num_nonnullables)) { - /* This rule was nullable */ - new_nullables->push(r->nonterminal); - - while (new_nullables->ptr) { - symbol = new_nullables->pop(); - if (verbose) { - werror(sprintf("Nulling symbol %s\n", - symbol_to_string(symbol))); - } - nullable[symbol] = 1; - if (used_by[symbol]) { - foreach (indices(used_by[symbol]), object(rule) r2) { - if (!(--r2->num_nonnullables)) { - new_nullables->push(r2->nonterminal); - } - } - used_by[symbol] = 0; /* No more need for this info */ - } - } - } - } else { - /* Check if it's an operator */ - foreach(r->symbols, symbol) { - if (operator_priority[symbol]) { - r->pri = operator_priority[symbol]; - } - } - } - - /* The info calculated from this point is not at the moment used - * by the compiler - */ -} - -/* Here come the functions used by the compiler */ - -protected private object(kernel) first_state() -{ - object(kernel) state = kernel(); - - array(int) first_state_item_ids = sort(grammar[0]->number); - string kernel_hash = sprintf("%@4c", first_state_item_ids); - known_states[kernel_hash] = state; - - foreach (grammar[0], object(rule) r) { - if (!state->rules[r]) { - object(item) i = item(); - - i->r = r; - // Not needed since 0 is the default. - // i->offset = 0; - i->item_id = r->number; - - state->add_item(i); - state->rules[r] = 1; /* Since this is an item with offset 0 */ - - if ((sizeof(r->symbols)) && - (intp(r->symbols[0]))) { - state->closure(r->symbols[0]); - } - } - } - return(state); -} - -//! Contains all states used. -//! In the queue-part are the states that remain to be compiled. -object(state_queue) s_q; - -protected private object(ADT.Stack) item_stack; - -protected private void traverse_items(object(item) i, - function(int:void) conflict_func) -{ - int depth; - - item_stack->push(i); - - i->counter = depth = item_stack->ptr; - - foreach (indices(i->relation), object(item) i2) { - if (!i2->counter) { - traverse_items(i2, conflict_func); - } - if (i->counter > i2->counter) { - i->counter = i2->counter; - } - - i->direct_lookahead |= i2->direct_lookahead; - } - - if (i->number == depth) { - int cyclic = 0; - int empty_cycle = 1; - object(item) i2; - - while ((i2 = item_stack->pop()) != i) { - - i2->number = 0x7fffffff; - - i2->direct_lookahead = i->direct_lookahead; - - cyclic = 1; - empty_cycle &= !(sizeof(i2->error_lookahead)); - } - i->count = 0x7fffffff; - - if (cyclic) { - if (verbose) { - werror(sprintf("Cyclic item\n%s\n", - item_to_string(i))); - } - conflict_func(empty_cycle && !(sizeof(i->error_lookahead))); - } - } -} - -protected private void shift_conflict(int empty) -{ - /* Ignored */ -} - -protected private void handle_shift_conflicts() -{ - item_stack = ADT.Stack(131072); - - /* Initialize the counter */ - for (int index = 0; index < s_q->tail; index++) { - foreach (s_q->arr[index]->items, object(item) i) { - if ((i->offset != sizeof(i->r->symbols)) && - (intp(i->r->symbols[i->offset])) && - (!i->master_item)) { - /* Nonterminal master item */ - i->counter = 0; - } else { - i->counter = 0x7fffffff; - } - } - } - - for (int index = 0; index < s_q->tail; index++) { - foreach (s_q->arr[index]->items, object(item) i) { - if (!i->number) { - traverse_items(i, shift_conflict); - } - } - } -} - -protected private void follow_conflict(int empty) -{ -} - -protected private void handle_follow_conflicts() -{ - item_stack = ADT.Stack(131072); - - /* Initialize the counter */ - for (int index = 0; index < s_q->tail; index++) { - foreach (s_q->arr[index]->items, object(item) i) { - if ((i->offset != sizeof(i->r->symbols)) && - (intp(i->r->symbols[i->offset])) && - (!i->master_item)) { - /* Nonterminal master item */ - i->counter = 0; - } else { - i->counter = 0x7fffffff; - } - } - } - - for (int index = 0; index < s_q->tail; index++) { - foreach (s_q->arr[index]->items, object(item) i) { - if (!i->number) { - traverse_items(i, follow_conflict); - } - } - } -} - -protected private int go_through(object(kernel) state, int item_id, - object(item) current_item) -{ - object(item) i, master; - - i = state->item_id_to_item[item_id]; - - /* What to do if not found? */ - if (!i) { - werror(sprintf("go_through: item %d not found in state\n" - "%s\n", - item_id, - state_to_string(state))); - werror(sprintf("Backtrace:\n%s\n", describe_backtrace(backtrace()))); - return(0); - } - - if (i->master_item) { - master = i->master_item; - } else { - master = i; - } - - if (i->offset < sizeof(i->r->symbols)) { - if (go_through(i->next_state, item_id + 1, current_item)) { - /* Nullable */ - if ((master->offset < sizeof(master->r->symbols)) && - (intp(master->r->symbols[master->offset]))) { - /* Don't include ourselves */ - if (master != current_item) { - master->relation[current_item] = 1; - } - } - return(nullable[i->r->symbols[i->offset]]); - } else { - return (0); /* Not nullable */ - } - } else { - /* At end of rule */ - master->relation[current_item] = 1; - return (1); /* Always nullable */ - } -} - -protected private int repair(object(kernel) state, multiset(int|string) conflicts) -{ - multiset(int|string) conflict_set = (<>); - - if (verbose) { - werror(sprintf("Repairing conflict in state:\n%s\n" - "Conflicts on (< %s >)\n", - state_to_string(state), - map(indices(conflicts), symbol_to_string) * ", ")); - } - - foreach (indices(conflicts), int|string symbol) { - /* Initialize some vars here */ - int reduce_count = 0; - int shift_count = 0; - int reduce_rest = 0; - int shift_rest = 0; - int only_operators = 1; - object(priority) shift_pri, reduce_pri, pri; - object(rule) min_rule = 0; - int conflict_free; - - /* Analyse the items */ - /* This loses if there are reduce-reduce conflicts, - * or shift-shift conflicts - */ - foreach (state->items, object(item) i) { - if (i->offset == sizeof(i->r->symbols)) { - if (i->direct_lookahead[symbol]) { - /* Reduction */ - reduce_count++; - if (pri = i->r->pri) { - if (!reduce_pri || (pri->value > reduce_pri->value)) { - reduce_pri = pri; - } - } else { - only_operators = 0; - } - - if ((!min_rule) || (i->r->number < min_rule->number)) { - min_rule = i->r; - } - } - } else if (!intp(i->r->symbols[i->offset])) { - if (i->r->symbols[i->offset] == symbol) { - /* Shift */ - shift_count++; - - if (operator_priority[symbol]) { - shift_pri = operator_priority[symbol]; - } else { - only_operators = 0; - } - } - } - } - - if (only_operators) { - if (reduce_pri->value > shift_pri->value) { - pri = reduce_pri; - } else { - pri = shift_pri; - } - - foreach (state->items, object(item) i) { - if (i->offset == sizeof(i->r->symbols)) { - /* Reduce */ - if (i->direct_lookahead[symbol]) { - object(priority) new_pri; - if ((new_pri = i->r->pri)->value < pri->value) { - if (verbose) { - werror(sprintf("Ignoring reduction of item\n%s\n" - "on lookahead %s (Priority %d < %d)\n", - item_to_string(i), - symbol_to_string(symbol), - new_pri->value, pri->value)); - } - i->direct_lookahead[symbol] = 0; - if (!sizeof(indices(i->direct_lookahead))) { - i->direct_lookahead = (<>); - } - } else if ((pri->assoc >= 0) && - (shift_pri->value == pri->value)) { - if (verbose) { - werror(sprintf("Ignoring reduction of item\n%s\n" - "on lookahead %s (Right associative)\n", - item_to_string(i), - symbol_to_string(symbol))); - } - i->direct_lookahead[symbol] = 0; - if (!sizeof(indices(i->direct_lookahead))) { - i->direct_lookahead = (<>); - } - } else { - if (verbose) { - werror(sprintf("Kept item\n%s\n" - "on lookahead %s\n", - item_to_string(i), - symbol_to_string(symbol))); - } - reduce_rest++; - } - } - } else if (i->r->symbols[i->offset] == symbol) { - /* Shift */ - if (shift_pri->value < pri->value) { - if (verbose) { - werror(sprintf("Ignoring shift on item\n%s\n" - "on lookahead %s (Priority %d < %d)\n", - item_to_string(i), - symbol_to_string(symbol), - i->r->pri->value, pri->value)); - } - i->direct_lookahead = (<>); - i->next_state = 0; - } else if ((pri->assoc <= 0) && - (reduce_pri->value == pri->value)) { - if (verbose) { - werror(sprintf("Ignoring shift on item\n%s\n" - "on lookahead %s (Left associative)\n", - item_to_string(i), - symbol_to_string(symbol))); - } - i->direct_lookahead = (<>); - i->next_state = 0; - } else { - if (verbose) { - werror(sprintf("Kept item\n%s\n" - "on lookahead %s\n", - item_to_string(i), - symbol_to_string(symbol))); - } - shift_rest++; - } - } - } - } else { - /* Not only operators */ - if (shift_count) { - /* Prefer shifts */ - foreach (state->items, object(item) i) { - if (i->offset == sizeof(i->r->symbols)) { - /* Reduction */ - if (i->direct_lookahead[symbol]) { - if (verbose) { - werror(sprintf("Ignoring reduction on item\n%s\n" - "on lookahead %s (can shift)\n", - item_to_string(i), - symbol_to_string(symbol))); - } - i->direct_lookahead[symbol] = 0; - if (!sizeof(indices(i->direct_lookahead))) { - i->direct_lookahead = (<>); - } - } - } else { - /* Shift */ - if (i->r->symbols[i->offset] == symbol) { - if (verbose) { - werror(sprintf("Kept item\n%s\n" - "on lookahead (shift)%s\n", - item_to_string(i), - symbol_to_string(symbol))); - } - shift_rest++; - } - } - } - } else { - /* Select the first reduction */ - foreach (state->items, object(item) i) { - if (i->r == min_rule) { - if (verbose) { - werror(sprintf("Kept item\n%s\n" - "on lookahead %s (first rule)\n", - item_to_string(i), - symbol_to_string(symbol))); - } - reduce_rest++; - } else { - if (verbose) { - werror(sprintf("Ignoring reduction on item\n%s\n" - "on lookahead %s (not first rule)\n", - item_to_string(i), - symbol_to_string(symbol))); - } - i->direct_lookahead[symbol] = 0; - if (!sizeof(indices(i->direct_lookahead))) { - i->direct_lookahead = (<>); - } - } - } - } - } - - conflict_free = 0; - - if (reduce_rest > 1) { - if (shift_rest) { - werror(sprintf("Error: Shift-Reduce-Reduce conflict on lookahead %s\n", - symbol_to_string(symbol))); - } else { - werror(sprintf("Error: Reduce-Reduce conflict on lookahead %s\n", - symbol_to_string(symbol))); - } - } else if (reduce_rest) { - if (shift_rest) { - werror(sprintf("Error: Shift-Reduce conflict on lookahead %s\n", - symbol_to_string(symbol))); - } else { - /* REDUCE - * - * No other rule left -- conflict resolved! - */ - conflict_free = 1; - } - } else { - /* SHIFT - * - * All reductions removed -- conflict resolved! - */ - conflict_free = 1; - } - if (conflict_free) { - if (reduce_count > 1) { - if (shift_count) { - if (only_operators) { - if (verbose) { - werror(sprintf("Repaired Shift-Reduce-Reduce conflict on %s\n", - symbol_to_string(symbol))); - } - } else { - werror(sprintf("Warning: Repaired Shift-Reduce-Reduce conflict on %s\n", - symbol_to_string(symbol))); - } - } else { - if (only_operators) { - if (verbose) { - werror(sprintf("Repaired Reduce-Reduce conflict on %s\n", - symbol_to_string(symbol))); - } - } else { - werror(sprintf("Warning: Repaired Reduce-Reduce conflict on %s\n", - symbol_to_string(symbol))); - } - } - } else if (reduce_count) { - if (shift_count) { - if (only_operators) { - if (verbose) { - werror(sprintf("Repaired Shift-Reduce conflict on %s\n", - symbol_to_string(symbol))); - } - } else { - werror(sprintf("Warning: Repaired Shift-Reduce conflict on %s\n", - symbol_to_string(symbol))); - } - } else { - /* No conflict */ - if (verbose) { - werror(sprintf("No conflict on symbol %s (Plain REDUCE)\n", - symbol_to_string(symbol))); - } - } - } else { - /* No conflict */ - if (verbose) { - werror(sprintf("No conflict on symbol %s (SHIFT)\n", - symbol_to_string(symbol))); - } - } - - } else { - /* Still conflicts left on this symbol */ - conflict_set[symbol] = 1; - } - } - - if (sizeof(indices(conflict_set))) { - werror(sprintf("Still conflicts remaining in state\n%s\n" - "on symbols (< %s >)\n", - state_to_string(state), - map(indices(conflict_set), symbol_to_string) * ", ")); - return (ERROR_CONFLICTS); - } else { - if (verbose) { - werror("All conflicts removed!\n"); - } - return (0); - } -} - -//! Compiles the grammar into a parser, so that parse() can be called. -int compile() -{ - int error = 0; /* No error yet */ - int state_no = 0; /* DEBUG INFO */ - object(kernel) state; - multiset(int|string) symbols, conflicts; - - s_q = state_queue(); - s_q->push(first_state()); - - /* First make LR(0) states */ - -#ifdef LR_PROFILE - werror(sprintf("LR0: %f\n", gauge { -#endif /* LR_PROFILE */ - - while (state = s_q->next()) { - - if (verbose) { - werror(sprintf("Compiling state %d:\n%s", state_no++, - state_to_string(state) + "\n")); - } - - /* Probably better implemented as a stack */ - foreach (indices(state->goto_set()), int|string symbol) { - state->do_goto(symbol); - } - } -#ifdef LR_PROFILE - })); -#endif /* LR_PROFILE */ - - /* Compute nullables */ - /* Done during add_rule */ - if (verbose) { - werror(sprintf("Nullable nonterminals: (< %s >)\n", - map(indices(nullable), symbol_to_string) * ", ")); - } - -#ifdef LR_PROFILE - werror(sprintf("Master items: %f\n", gauge { -#endif /* LR_PROFILE */ - - /* Mark Transition and Reduction master items */ - for (int index = 0; index < s_q->tail; index++) { - mapping(int|string : object(item)) master_item =([]); - - foreach (s_q->arr[index]->items, object(item) i) { - if (i->offset < sizeof(i->r->symbols)) { - /* This is not a reduction item, which represent themselves */ - int|string symbol = i->r->symbols[i->offset]; - - if (!(i->master_item = master_item[symbol])) { - master_item[symbol] = i; - } - } - } - } - -#ifdef LR_PROFILE - })); -#endif /* LR_PROFILE */ - - /* Probably OK so far */ - -#ifdef LR_PROFILE - werror(sprintf("LA sets: %f\n", gauge { -#endif /* LR_PROFILE */ - - /* Calculate look-ahead sets (DR and relation) */ - for (int index = 0; index < s_q->tail; index++) { - foreach (s_q->arr[index]->items, object(item) i) { - if ((!i->master_item) && (i->offset != sizeof(i->r->symbols)) && - (intp(i->r->symbols[i->offset]))) { - /* This is a non-terminal master item */ - foreach (i->next_state->items, object(item) i2) { - int|string symbol; - - if (!i2->master_item) { - /* Master item */ - if (i2->offset != sizeof(i2->r->symbols)) { - if (intp(symbol = i2->r->symbols[i2->offset])) { - if (nullable[symbol]) { - /* Add the item to the look-ahead relation set */ - i->relation[i2] = 1; - } - } else { - /* Add the string to the direct look-ahead set (DR) */ - i->direct_lookahead[symbol] = 1; - } - } - } - } - } - } - } - -#ifdef LR_PROFILE - })); -#endif /* LR_PROFILE */ - -#ifdef LR_PROFILE - werror(sprintf("Handle shift: %f\n", gauge { -#endif /* LR_PROFILE */ - - /* Handle SHIFT-conflicts */ - handle_shift_conflicts(); - -#ifdef LR_PROFILE - })); -#endif /* LR_PROFILE */ - -#ifdef LR_PROFILE - werror(sprintf("Check shift: %f\n", gauge { -#endif /* LR_PROFILE */ - - /* Check the shift sets */ - /* (Is this needed?) - * Yes - initializes error_lookahead - */ - for (int index = 0; index < s_q->tail; index++) { - foreach (s_q->arr[index]->items, object(item) i) { - if ((!i->master_item) && - (i->offset != sizeof(i->r->symbols)) && - (intp(i->r->symbols[i->offset]))) { - i->error_lookahead = copy_value(i->direct_lookahead); - } - } - } - -#ifdef LR_PROFILE - })); -#endif /* LR_PROFILE */ - -#ifdef LR_PROFILE - werror(sprintf("Lookback sets: %f\n", gauge { -#endif /* LR_PROFILE */ - - /* Compute lookback-sets */ - for (int index = 0; index < s_q->tail; index++) { - array(object(item)) items = s_q->arr[index]->items; - // Set up a lookup table to speedup lookups later. - mapping(int:array(object(item))) lookup = ([]); - foreach (items, object(item) i) { - if (!i->offset) { - if (!lookup[i->r->nonterminal]) { - lookup[i->r->nonterminal] = ({ i }); - } else { - lookup[i->r->nonterminal] += ({ i }); - } - } - } - foreach (items, object(item) transition) { - int|string symbol; - - if ((!transition->master_item) && - (transition->offset != sizeof(transition->r->symbols)) && - (intp(symbol = transition->r->symbols[transition->offset]))) { - /* Master item and - * Not a reduction item and - * next symbol is a NonTerminal - */ - if (!lookup[symbol]) { - // Foo? Shouldn't these always exist since we've made - // a closure earlier? - werror(sprintf("WARNING: No item for symbol <%s>\n" - "in state:\n" - "%s\n", - symbol_to_string(symbol), - state_to_string(s_q->arr[index]))); - continue; - } - - /* Find items which can reduce to the nonterminal from above */ - foreach (lookup[symbol], object(item) i) { - if (sizeof(i->r->symbols)) { - if (go_through(i->next_state, i->item_id + 1, transition)) { - /* Nullable */ - object(item) master = i; - if (i->master_item) { - master = i->master_item; - } - /* Is this a nonterminal transition? */ - if ((master->offset != sizeof(master->r->symbols)) && - (intp(master->r->symbols[master->offset]))) { - /* Don't include ourselves */ - if (master != transition) { - master->relation[transition] = 1; - } - } - } - } else { - i->relation[transition] = 1; - } - } - } - } - } - -#ifdef LR_PROFILE - })); -#endif /* LR_PROFILE */ - -#ifdef LR_PROFILE - werror(sprintf("Handle follow: %f\n", gauge { -#endif /* LR_PROFILE */ - - /* Handle follow-conflicts */ - handle_follow_conflicts(); - -#ifdef LR_PROFILE - })); -#endif /* LR_PROFILE */ - -#ifdef LR_PROFILE - werror(sprintf("Compute LA: %f\n", gauge { -#endif /* LR_PROFILE */ - - /* Compute the lookahead (LA) */ - for (int index = 0; index < s_q->tail; index++) { - foreach (s_q->arr[index]->items, object(item) i) { - if (i->offset == sizeof(i->r->symbols)) { - /* Reduction item (always a master item) */ - - /* Calculate Look-ahead for all items in look-back set */ - - i->direct_lookahead=`|(i->direct_lookahead, - @indices(i->relation)->direct_lookahead); - } - } - } - -#ifdef LR_PROFILE - })); -#endif /* LR_PROFILE */ - - /* Probably OK from this point onward */ - -#ifdef LR_PROFILE - werror(sprintf("Check conflicts: %f\n", gauge { -#endif /* LR_PROFILE */ - - /* Check for conflicts */ - for (int index = 0; index < s_q->tail; index++) { - object(kernel) state = s_q->arr[index]; - - conflicts = (<>); - symbols = (<>); - - foreach (state->items, object(item) i) { - if (i->offset == sizeof(i->r->symbols)) { - /* Reduction */ - conflicts |= i->direct_lookahead & symbols; - symbols |= i->direct_lookahead; - } else if (!i->master_item) { - string|int symbol; - - /* Only master items, since we get Shift-Shift conflicts otherwise */ - - if (!intp(symbol = i->r->symbols[i->offset])) { - /* Shift on terminal */ - if (symbols[symbol]) { - conflicts[symbol] = 1; - } else { - symbols[symbol] = 1; - } - } - } - } - if (sizeof(conflicts)) { - /* Repair conflicts */ - // int ov = verbose; - // verbose = 1; - error = repair(state, conflicts); - // verbose = ov; - } else if (verbose) { - werror(sprintf("No conflicts in state:\n%s\n", - state_to_string(s_q->arr[index]))); - } - } - -#ifdef LR_PROFILE - })); -#endif /* LR_PROFILE */ - -#ifdef LR_PROFILE - werror(sprintf("Compile actions: %f\n", gauge { -#endif /* LR_PROFILE */ - - /* Compile action tables */ - for (int index = 0; index < s_q->tail; index++) { - object(kernel) state = s_q->arr[index]; - - state->action = ([]); - - foreach (state->items, object(item) i) { - if (i->next_state) { - /* SHIFT */ - state->action[i->r->symbols[i->offset]] = i->next_state; - } else { - foreach (indices(i->direct_lookahead), int|string symbol) { - state->action[symbol] = i->r; - } - } - } - } - start_state = s_q->arr[0]; - -#ifdef LR_PROFILE - })); -#endif /* LR_PROFILE */ - -#ifdef LR_PROFILE - werror("DONE\n"); -#endif /* LR_PROFILE */ - - return (error); -} - -//! Parse the input according to the compiled grammar. -//! The last value reduced is returned. -//! -//! @note -//! The parser must have been compiled (with compile()) -//! prior to calling this function. -//! -//! @bugs -//! Errors should be throw()n. -//! -//! @param scanner -//! The scanner function. It returns the next symbol from the input. -//! It should either return a string (terminal) or an array with -//! a string (terminal) and a mixed (value). -//! EOF is indicated with the empty string. -//! -//! @param action_object -//! Object used to resolve those actions that have been specified as -//! strings. -mixed parse(object|function(void:string|array(string|mixed)) scanner, - void|object action_object) -{ - object(ADT.Stack) value_stack = ADT.Stack(4096); - object(ADT.Stack) state_stack = ADT.Stack(4096); - object(kernel) state = start_state; - - string input; - mixed value; - - error = 0; /* No parse error yet */ - - if (!functionp(scanner) && - !(objectp(scanner) && functionp(scanner->`()))) { - werror("parser->parse(): scanner not set!\n"); - error = ERROR_NO_SCANNER; - return(0); - } - - value = scanner(); - - if (arrayp(value)) { - input = value[0]; - value = value[1]; - } else { - input = value; - } - - while (1) { - mixed a = state->action[input]; - - if (object_program(a) == rule) { - - if (verbose) { - werror(sprintf("Reducing according to rule\n%s\n", - rule_to_string(a))); - } - - if (a->action) { - /* REDUCE */ - string|function (mixed ...:mixed) func = 0; - - if (stringp(func = a->action)) { - if (action_object) { - func = action_object[a->action]; - if (!functionp(func)) { - if (!func) { - werror(sprintf("Missing action \"%s\" in object\n", - a->action)); - error |= ERROR_MISSING_ACTION; - } else { - werror(sprintf("Bad type (%O) for action \"%s\" in object\n", - typeof(func), a->action)); - error |= ERROR_BAD_ACTION_TYPE; - func = 0; - } - } - } else { - werror(sprintf("Missing object for action \"%s\"\n", - a->action)); - error |= ERROR_NO_OBJECT; - func = 0; - } - } - if (func) { - if (sizeof(a->symbols)) { - value_stack->push(func(@value_stack->pop(sizeof(a->symbols)))); - state = state_stack->pop(sizeof(a->symbols))[0]; - } else { - value_stack->push(a->action()); - } - } else { - // Default action. - if (sizeof(a->symbols)) { - if (sizeof(a->symbols) > 1) { - value_stack->quick_pop(sizeof(a->symbols) - 1); - } - state = state_stack->pop(sizeof(a->symbols))[0]; - } else { - value_stack->push(0); - } - } - } else { - // Default action. - if (sizeof(a->symbols)) { - if (sizeof(a->symbols) > 1) { - value_stack->quick_pop(sizeof(a->symbols) - 1); - } - state = state_stack->pop(sizeof(a->symbols))[0]; - } else { - value_stack->push(0); - } - } - - state_stack->push(state); - state = state->action[a->nonterminal]; /* Goto */ - } else if (a) { - /* SHIFT or ACCEPT */ - if (input == "") { - /* Only the final state is allowed to shift on ""(EOF) */ - /* ACCEPT */ - return(value_stack->pop()); - } - /* SHIFT */ - if (verbose) { - werror(sprintf("Shifting \"%s\", value \"%O\"\n", input, value)); - } - value_stack->push(value); - state_stack->push(state); - state = a; - - value = scanner(); - - if (arrayp(value)) { - input = value[0]; - value = value[1]; - } else { - input = value; - } - } else { - /* ERROR */ - if (input = "") { - /* At end of file */ - error |= ERROR_EOF; - - if (value_stack->ptr != 1) { - if (value_stack->ptr) { - werror(sprintf("Error: Bad state at EOF -- Throwing \"%O\"\n", - value_stack->pop())); - state=state_stack->pop(); - } else { - werror(sprintf("Error: Empty stack at EOF!\n")); - return (0); - } - } else { - werror("Error: Bad state at EOF\n"); - return(value_stack->pop()); - } - } else { - error |= ERROR_SYNTAX; - - werror("Error: Bad input: \""+input+"\"(\""+value+"\")\n"); - - value = scanner(); - - if (arrayp(value)) { - input = value[0]; - value = value[1]; - } else { - input = value; - } - } - } - } -} diff --git a/lib/7.2/modules/LR.pmod/priority.pike b/lib/7.2/modules/LR.pmod/priority.pike deleted file mode 100644 index 753997bc8e883b1950f3e9bb1a3162e30a74e9d9..0000000000000000000000000000000000000000 --- a/lib/7.2/modules/LR.pmod/priority.pike +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Rule priority specification - * - * Henrik Grubbstr�m 1996-12-05 - */ - -#pike 7.2 - -//! -//! Specifies the priority and associativity of a rule. -//! - -//! Priority value -int value; - -//! Associativity -//! -//! @int -//! @value -1 -//! Left -//! @value 0 -//! None -//! @value 1 -//! Right -//! @endint -int assoc; - -//! Create a new priority object. -//! -//! @param p -//! Priority. -//! @param a -//! Associativity. -void create(int p, int a) -{ - value = p; - assoc = a; -} diff --git a/lib/7.2/modules/LR.pmod/rule.pike b/lib/7.2/modules/LR.pmod/rule.pike deleted file mode 100644 index 1db0e3b56147689628301fe3fe83d8b11512359f..0000000000000000000000000000000000000000 --- a/lib/7.2/modules/LR.pmod/rule.pike +++ /dev/null @@ -1,99 +0,0 @@ -/* - * A BNF-rule. - * - * Henrik Grubbstr�m 1996-11-24 - */ - -#pike 7.2 - -//! -//! This object is used to represent a BNF-rule in the LR parser. -//! - -/* - * Object variables - */ - -//! Non-terminal this rule reduces to. -int nonterminal; - -//! The actual rule -array(string|int) symbols; - -//! Action to do when reducing this rule. -//! function - call this function. -//! string - call this function by name in the object given to the parser. -//! The function is called with arguments corresponding to the values of -//! the elements of the rule. The return value of the function will be -//! the value of this non-terminal. The default rule is to return the first -//! argument. -function|string action; - -/* Variables used when compiling */ - -//! This rule contains tokens -int has_tokens = 0; - -//! This rule has this many non-nullable symbols at the moment. -int num_nonnullables = 0; - -/* -multiset(int) prefix_nonterminals = (<>); -multiset(string) prefix_tokens = (<>); -*/ - -//! Sequence number of this rule (used for conflict resolving) -//! Also used to identify the rule. -int number = 0; - -//! Priority and associativity of this rule. -object /* (priority) */ pri; - -/* - * Functions - */ - -//! Create a BNF rule. -//! -//! @example -//! The rule -//! -//! rule : nonterminal ":" symbols ";" { add_rule }; -//! -//! might be created as -//! -//! rule(4, ({ 9, ";", 5, ";" }), "add_rule"); -//! -//! where 4 corresponds to the nonterminal "rule", 9 to "nonterminal" -//! and 5 to "symbols", and the function "add_rule" is too be called -//! when this rule is reduced. -//! -//! @param nt -//! Non-terminal to reduce to. -//! @param r -//! Symbol sequence that reduces to nt. -//! @param a -//! Action to do when reducing according to this rule. -//! function - Call this function. -//! string - Call this function by name in the object given to the parser. -//! The function is called with arguments corresponding to the values of -//! the elements of the rule. The return value of the function will become -//! the value of this non-terminal. The default rule is to return the first -//! argument. -void create(int nt, array(string|int) r, function|string|void a) -{ - mixed symbol; - - nonterminal = nt; - symbols = r; - action = a; - - foreach (r, symbol) { - if (stringp(symbol)) { - has_tokens = 1; - break; - } - } - - num_nonnullables = sizeof(r); -} diff --git a/lib/7.2/modules/LR.pmod/scanner.pike b/lib/7.2/modules/LR.pmod/scanner.pike deleted file mode 100644 index 76c423797d2b3af1fc0daa80488e6ff570eedbac..0000000000000000000000000000000000000000 --- a/lib/7.2/modules/LR.pmod/scanner.pike +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Scanner using reg-exps. - * - * Henrik Grubbstr�m 1996-12-16 - */ - -#pike 7.2 diff --git a/lib/7.2/modules/Parser.pmod/XML.pmod/Tree.pmod b/lib/7.2/modules/Parser.pmod/XML.pmod/Tree.pmod deleted file mode 100644 index ef2512e019bb80c4dd447e96cb707787ca406d89..0000000000000000000000000000000000000000 --- a/lib/7.2/modules/Parser.pmod/XML.pmod/Tree.pmod +++ /dev/null @@ -1,16 +0,0 @@ -#pike 7.7 - -inherit Parser.XML.Tree; - -// There was no simple_parse_input in 7.2. - -Node parse_input (string data, void|int(0..1) no_fallback, - void|int(0..1) force_lowercase, - void|mapping(string:string) predefined_entities, - void|int(0..1) parse_namespaces, - ParseFlags|void flags) -{ - return ::parse_input (data, no_fallback, force_lowercase, - predefined_entities, parse_namespaces, - flags | PARSE_COMPAT_ALLOW_ERRORS_7_2); -} diff --git a/lib/7.2/modules/Parser.pmod/XML.pmod/module.pmod b/lib/7.2/modules/Parser.pmod/XML.pmod/module.pmod deleted file mode 100644 index 51a73e6415c38a586271a525277c61a946e3ad6e..0000000000000000000000000000000000000000 --- a/lib/7.2/modules/Parser.pmod/XML.pmod/module.pmod +++ /dev/null @@ -1,23 +0,0 @@ -#pike 7.7 - -class Simple -{ - inherit Parser.XML.Simple; - - protected void create() - { - compat_allow_errors ("7.2"); - // Got no inherited create. - } -} - -class Validating -{ - inherit Parser.XML.Validating; - - protected void create() - { - compat_allow_errors ("7.2"); - // Got no inherited create. - } -} diff --git a/lib/7.2/modules/Protocols.pmod/LDAP.pmod/client.pike b/lib/7.2/modules/Protocols.pmod/LDAP.pmod/client.pike deleted file mode 100644 index 3cb75e1bba0999b138b5b5a3d96beff9d37e28be..0000000000000000000000000000000000000000 --- a/lib/7.2/modules/Protocols.pmod/LDAP.pmod/client.pike +++ /dev/null @@ -1,53 +0,0 @@ -/* - Compatibility code for 7.2- - */ - -#pike 7.3 - -inherit Protocols.LDAP.client; - -int bind(string|void dn, string|void password) { - - return !::bind(dn, password); -} - - -object|int search (string|void filter, int|void attrsonly, - array(string)|void attrs) { - - return ::search(filter, attrs, attrsonly); -} - - -int modify (string dn, mapping(string:array(mixed)) attropval) { - - ::modify(dn, attropval); - return ldap_errno; -} - -int delete (string dn) { - - ::delete(dn); - return ldap_errno; -} - -int compare (string dn, array(string) aval) { - - ::compare(dn, aval); - return ldap_errno; -} - - -int add (string dn, mapping(string:array(string)) attrs) { - - ::add(dn, attrs); - return ldap_errno; -} - - -int modifydn (string dn, string newrdn, int deleteoldrdn, - string|void newsuperior) { - - ::modifydn(dn, newrdn, deleteoldrdn, newsuperior); - return ldap_errno; -} diff --git a/lib/7.2/modules/String.pmod b/lib/7.2/modules/String.pmod deleted file mode 100644 index 0cabffcc42e67a6ff4a419fa1b1d27571a48692a..0000000000000000000000000000000000000000 --- a/lib/7.2/modules/String.pmod +++ /dev/null @@ -1,263 +0,0 @@ -#pike 7.2 - -#define BEGIN 32 - -constant Buffer = __builtin.Buffer; - -//! @decl string count(string haystack, string needle) -//! -//! This function counts the number of times the @[needle] -//! can be found in @[haystack]. -//! -//! @note -//! Intersections between needles are not counted, ie -//! @tt{count("....","..")@} is @tt{2@}. -//! - -constant count=__builtin.string_count; - -//! @decl int width(string s) -//! -//! Returns the width in bits (8, 16 or 32) of the widest character -//! in @[s]. -//! - -constant width=__builtin.string_width; - -/* - * Implode an array of strings to an english 'list' - * ie. ({"foo","bar","gazonk"}) becomes "foo, bar and gazonk" - */ - -//! This function implodes a list of words to a readable string. -//! If the separator is omitted, the default is <tt>"and"</tt>. -//! If the words are numbers they are converted to strings first. -//! -//! @seealso -//! @[`*()] -//! -string implode_nicely(array(string|int|float) foo, string|void separator) -{ - if(!separator) separator="and"; - foo=(array(string))foo; - switch(sizeof(foo)) - { - case 0: return ""; - case 1: return ([array(string)]foo)[0]; - default: return foo[0..sizeof(foo)-2]*", "+" "+separator+" "+foo[-1]; - } -} - -//! Convert the first character in @[str] to upper case, and return the -//! new string. -//! -//! @seealso -//! @[lower_case()], @[upper_case()] -//! -string capitalize(string str) -{ - return upper_case(str[0..0])+str[1..sizeof(str)]; -} - -//! Convert the first character in each word (separated by spaces) in -//! @[str] to upper case, and return the new string. -//! -string sillycaps(string str) -{ - return Array.map(str/" ",capitalize)*" "; -} - -//! This function multiplies @[str] by @[num]. The return value is the same -//! as appending @[str] to an empty string @[num] times. -//! -//! @note -//! This function is obsolete, since this functionality has been incorporated -//! into @[`*()]. -//! -//! @seealso -//! @[`*()] -//! -string strmult(string str, int num) -{ - num*=strlen(str); - while(strlen(str) < num) str+=str; - return str[0..num-1]; -} - -/* - * string common_prefix(array(string) strs) - * { - * if(!sizeof(strs)) - * return ""; - * - * for(int n = 0; n < sizeof(strs[0]); n++) - * for(int i = 1; i < sizeof(strs); i++) - * if(sizeof(strs[i]) <= n || strs[i][n] != strs[0][n]) - * return strs[0][0..n-1]; - * - * return strs[0]; - * } - * - * This function is a slightly optimised version based on the code - * above (which is far more suitable for an implementation in C). - */ - -//! Find the longest common prefix from an array of strings. -//! -string common_prefix(array(string) strs) -{ - if(!sizeof(strs)) - return ""; - - string strs0 = strs[0]; - int n, i; - - catch - { - for(n = 0; n < sizeof(strs0); n++) - for(i = 1; i < sizeof(strs); i++) - if(strs[i][n] != strs0[n]) - return strs0[0..n-1]; - }; - - return strs0[0..n-1]; -} - -//! A helper class to optimize iterative string build-up for speed. Can help up -//! performance noticably when dealing with buildup of huge strings by reducing -//! the time needed for rehashing the string every time it grows. -//! @deprecated String.Buffer -class String_buffer { - array(string) buffer=allocate(BEGIN); - int ptr=0; - - protected void fix() - { - string tmp=buffer*""; - buffer=allocate(strlen(tmp)/128+BEGIN); - buffer[0]=tmp; - ptr=1; - } - - //! Get the contents of the buffer. - string get_buffer() - { - if(ptr != 1) fix(); - return buffer[0]; - } - - //! Append the string @[s] to the buffer. - void append(string s) - { - if(ptr==sizeof(buffer)) fix(); - buffer[ptr++]=s; - } - - //! - mixed cast(string to) - { - if(to=="string") return get_buffer(); - return 0; - } - - //! Clear the buffer. - void flush() - { - buffer=allocate(BEGIN); - ptr=0; - } -}; - - -// Do a fuzzy matching between two different strings and return a -// "similarity index". The higher, the closer the strings match. - -protected int low_fuzzymatch(string str1, string str2) -{ - string tmp1, tmp2; - int offset, length; - int fuzz; - fuzz = 0; - while(strlen(str1) && strlen(str2)) - { - /* Now we will look for the first character of tmp1 in tmp2 */ - if((offset = search(str2, str1[0..0])) != -1) - { - tmp2 = str2[offset..]; - /* Ok, so we have found one character, let's check how many more */ - tmp1 = str1; - length = 1; - while(1) - { - //*(++tmp1)==*(++tmp2) && *tmp1 - if(length < strlen(tmp1) && length < strlen(tmp2) && - tmp1[length] == tmp2[length]) - length++; - else - break; - } - if(length >= offset) - { - fuzz += length; - str1 = str1[length..]; - str2 = str2[length + offset..]; - continue; - } - } - if(strlen(str1)) - str1 = str1[1..]; - } - return fuzz; -} - -//! This function compares two strings using a fuzzy matching -//! routine. The higher the resulting value, the better the strings match. -//! -//! @seealso -//! @[Array.diff()], @[Array.diff_compare_table()] -//! @[Array.diff_longest_sequence()] -//! -int fuzzymatch(string a, string b) -{ - int fuzz; - - if(a == b) - { - fuzz = 100; - } else { - fuzz = low_fuzzymatch(a, b); - fuzz += low_fuzzymatch(b, a); - fuzz = fuzz*100/(strlen(a)+strlen(b)); - } - - return fuzz; -} - -//! Trim leading and trailing spaces and tabs from the string @[s]. -//! -string trim_whites(string s) -{ - if (stringp(s)) { - sscanf(s, "%*[ \t]%s", s); - string rev = reverse(s); - sscanf(rev, "%*[ \t]%s", rev); - return s[..strlen(rev) - 1]; - } - - return s; -} - -//! Trim leading and trailing white spaces characters (@tt{" \t\r\n"@}) from -//! the string @[s]. -//! -string trim_all_whites(string s) -{ - if (stringp(s)) { - sscanf(s, "%*[ \t\r\n]%s", s); - string rev = reverse(s); - sscanf(rev, "%*[ \t\r\n]%s", rev); - return s[..strlen(rev) - 1]; - } - - return s; -} diff --git a/lib/7.2/modules/Thread.pmod b/lib/7.2/modules/Thread.pmod deleted file mode 100644 index 27584cf923f30784f240d0a0576affa9ef119d65..0000000000000000000000000000000000000000 --- a/lib/7.2/modules/Thread.pmod +++ /dev/null @@ -1,28 +0,0 @@ -#pike 7.3 - -// -// Pike 7.2 backward compatibility layer. -// - -#pragma no_deprecation_warnings - -inherit Thread; - -#if constant(thread_create) - -class Condition -{ - inherit Thread::Condition; - - // Old-style wait(). - void wait(void|Mutex m) - { - if (!m) { - m = Mutex(); - m->lock(); - } - ::wait(m); - } -} - -#endif /* !constant(thread_create) */ diff --git a/lib/7.2/modules/__default.pmod b/lib/7.2/modules/__default.pmod deleted file mode 100644 index 5d4b3a1096169523c54ae0deb8e8b7ac27d7d28e..0000000000000000000000000000000000000000 --- a/lib/7.2/modules/__default.pmod +++ /dev/null @@ -1,156 +0,0 @@ -// Compatibility namespace - -#pike 7.3 - -//! Pike 7.2 compatibility. -//! -//! The symbols in this namespace will appear in -//! programs that use @expr{#pike 7.2@} or lower. - -//! @decl inherit 7.4:: - -//! Remove the last segment from @[path]. -//! -//! This implementation differs from @[predef::dirname()] -//! in that it will return @expr{""@} for the input @expr{"/"@} -//! while @[predef::dirname()] will return @expr{"/"@}. -//! -//! @seealso -//! @[predef::dirname()] -string dirname(string path) -{ - array(string) tmp = explode_path(path); - return tmp[..sizeof(tmp)-2]*"/"; -} - -//! High-resolution sleep (Pike 7.2 compatibility). -//! -//! Sleep @[t] seconds. This function was renamed to @[delay()] -//! in Pike 7.3. -//! -//! @note -//! This function will busy-wait if the sleep-interval is short. -//! -//! @deprecated delay -//! -//! @seealso -//! @[predef::sleep()], @[delay()] -void sleep(float|int t, void|int abort) -{ - delay(t, abort); -} - -#if constant(Yp.default_domain) -//! Get the default YP domain (Pike 7.2 compatibility). -//! This function was removed in Pike 7.3, use -//! @[Yp.default_domain()] instead. -//! -//! @deprecated Yp.default_domain -//! -//! @seealso -//! @[Yp.default_domain()] -string default_yp_domain() { - return Yp.default_domain(); -} -#endif - -//! Instantiate a program (Pike 7.2 compatibility). -//! -//! A new instance of the class @[prog] will be created. -//! All global variables in the new object be initialized, and -//! then @[lfun::create()] will be called with @[args] as arguments. -//! -//! This function was removed in Pike 7.3, use -//! @expr{((program)@[prog])(@@@[args])@} -//! instead. -//! -//! @deprecated -//! -//! @seealso -//! @[destruct()], @[compile_string()], @[compile_file()], @[clone()] -//! -object new(string|program prog, mixed ... args) -{ - if(stringp(prog)) - { - if(program p=(program)(prog, backtrace()[-2][0])) - return p(@args); - else - error("Failed to find program %s.\n", prog); - } - return prog(@args); -} - -//! @decl object clone(string|program prog, mixed ... args) -//! -//! Alternate name for the function @[new()] (Pike 7.2 compatibility). -//! -//! This function was removed in Pike 7.3, use -//! @expr{((program)@[prog])(@@@[args])@} -//! instead. -//! -//! @deprecated -//! -//! @seealso -//! @[destruct()], @[compile_string()], @[compile_file()], @[new()] - -function(string|program, mixed ... : object) clone = new; - -// spider -#pragma no_deprecation_warnings -#define SPIDER(X) constant X = spider.##X - -//! @ignore -SPIDER(_low_program_name); -SPIDER(set_start_quote); -SPIDER(set_end_quote); -SPIDER(parse_accessed_database); -SPIDER(_dump_obj_table); -SPIDER(parse_html); -SPIDER(parse_html_lines); -SPIDER(discdate); -SPIDER(stardate); -SPIDER(get_all_active_fd); -SPIDER(fd_info); -//! @endignore - -object master() -{ - return __REAL_VERSION__::master()->get_compat_master(7, 2); -} - -protected Mapping.ShadowedMapping compat_all_constants = - Mapping.ShadowedMapping(predef::all_constants(), - ([ -#define ADD(X) #X: X - - ADD(all_constants), - ADD(dirname), -#if constant(Yp.default_domain) - ADD(default_yp_domain), -#endif - ADD(new), - ADD(clone), - - ADD(master), - - // spider - ADD(_low_program_name), - ADD(set_start_quote), - ADD(set_end_quote), - ADD(parse_accessed_database), - ADD(_dump_obj_table), - ADD(parse_html), - ADD(parse_html_lines), - ADD(discdate), - ADD(stardate), - ADD(get_all_active_fd), - ADD(fd_info), - ]), 1); - -mapping(string:mixed) all_constants() -{ - // Intentional lie in the return type. - mixed x = compat_all_constants; - return x; -} diff --git a/lib/7.2/modules/system.pmod b/lib/7.2/modules/system.pmod deleted file mode 100644 index 168d9550779431bc90f6904b86034733bc3cfdb0..0000000000000000000000000000000000000000 --- a/lib/7.2/modules/system.pmod +++ /dev/null @@ -1,5 +0,0 @@ -#pike __REAL_VERSION__ - -// this module is to allow the system module to be called system. - -inherit _system; diff --git a/lib/7.2/modules/testsuite.in b/lib/7.2/modules/testsuite.in deleted file mode 100644 index 8812d361efe93d6464476f987878fc8f295b5cb2..0000000000000000000000000000000000000000 --- a/lib/7.2/modules/testsuite.in +++ /dev/null @@ -1,64 +0,0 @@ -START_MARKER(7.2) - -test_any([[ - return objectp(String.String_buffer()); -]], 1) -test_do([[ - String.String_buffer()->append("foo") -]]) -test_do([[add_constant("Flurp", String.String_buffer());]]) -test_do(Flurp->append("test")) -test_do(Flurp->append("test")) -test_eq((string)Flurp,"testtest") -test_do( add_constant("Flurp") ) - -test_any([[ - return String.strmult("foo",4); -]], "foofoofoofoo") - -test_compile_error_any([[ - class X { - int i = 17; - class Y { - constant i = 18; - mixed f (int i) {return ({i, Y::i, X::i});} - } - } -]]) - -test_program([[ - class A { - int i = 17; - } - class X { - inherit A: Y; - class Y { - constant i = 18; - mixed f() {return Y::i;} - } - } - int a() {return X()->Y()->f() == 17;} -]]) - -test_eval_error([[ - compile_string (#" - #pike 7.2 - string p = \"g\"; - mixed f (string p) {return global::p;}"); -]]) - -test_compile_error([[ - mixed a() {return global.Parser.HTML;} -]], 0); - -test_compile_any([[ - class X {int x; int f() {return local::x;}} -]]) - -// - new/clone -test_true([[ objectp(new(compile_string("int foo() { return 17; }"))) ]]) -test_eq([[new(compile_string("int foo() { return 17; }"))->foo() ]],17) -test_true([[ objectp(clone(compile_string("int foo() { return 17; }"))) ]]) -test_eq([[clone(compile_string("int foo() { return 17; }"))->foo() ]],17) - -END_MARKER