pike.git / lib / modules / Parser.pmod / LR.pmod / module.pmod

version» Context lines:

pike.git/lib/modules/Parser.pmod/LR.pmod/module.pmod:1:   /* -  * $Id: module.pmod,v 1.16 2008/01/09 16:10:29 grubba Exp $ +  * $Id: module.pmod,v 1.17 2008/06/28 16:36:55 nilsson Exp $    *    * A BNF-grammar in Pike.    * Compiles to a LALR(1) state-machine.    *    * Henrik Grubbström 1996-11-24    */      #pike __REAL_VERSION__      //! LALR(1) parser generator.
pike.git/lib/modules/Parser.pmod/LR.pmod/module.pmod:132:    //! @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. -  static void create(int nt, array(string|int) r, function|string|void a) +  protected 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;
pike.git/lib/modules/Parser.pmod/LR.pmod/module.pmod:174:    //! @int    //! @value -1    //! Just errors.    //! @value 0    //! Errors and warnings.    //! @value 1    //! Also notices.    //! @endint    optional int(-1..1) verbose = 1;    -  static constant severity_kind = ([ NOTICE:"Notice", +  protected constant severity_kind = ([ NOTICE:"Notice",    WARNING:"Warning",    ERROR:"Error" ]);       void report(SeverityLevel level, string subsystem, string msg,    mixed ... args)    {    if (level > -verbose) {    werror([string(0..255)]("%s: %s: "+msg+"\n"),    severity_kind[level], subsystem, @args);    }    }       //! Create a new error handler.    //!    //! @param verbosity    //! Level of verbosity.    //!    //! @seealso    //! @[verbose] -  static void create(int(-1..1)|void verbosity) +  protected void create(int(-1..1)|void verbosity)    {    if (!zero_type(verbosity)) {    verbose = verbosity;    }    }   }      //! This object implements an LALR(1) parser and compiler.   //!   //! Normal use of this object would be:
pike.git/lib/modules/Parser.pmod/LR.pmod/module.pmod:219:   //! set_symbol_to_string   //! compile   //! {parse}*   //! @}   class Parser   {    //! The grammar itself.    mapping(int : array(Rule)) grammar = ([]);       /* Priority table for terminal symbols */ -  static mapping(string : Priority) operator_priority = ([]); +  protected mapping(string : Priority) operator_priority = ([]);    -  static multiset(int|string) nullable = (< >); +  protected multiset(int|string) nullable = (< >);      #if 0 -  static mapping(mixed : multiset(Rule)) derives = ([]); +  protected mapping(mixed : multiset(Rule)) derives = ([]);       /* Maps from symbol to which rules may start with that symbol */ -  static mapping(mixed : multiset(Rule)) begins = ([]); +  protected mapping(mixed : multiset(Rule)) begins = ([]);   #endif /* 0 */       /* Maps from symbol to the rules that use the symbol    * (used for finding nullable symbols)    */ -  static mapping(int : multiset(Rule)) used_by = ([]); +  protected mapping(int : multiset(Rule)) used_by = ([]);       //! The initial LR0 state.    Kernel start_state;       //! Error code    int lr_error=0;       /* Number of next rule (used only for conflict resolving) */ -  static int next_rule_number = 1; +  protected int next_rule_number = 1;       //! LR0 states that are already known to the compiler.    mapping(string:Kernel) known_states = ([]);       //! Compile error and warning handler.    function(SeverityLevel, string, string, mixed ...:void) error_handler =    ErrorHandler()->report;       void report(SeverityLevel level, string subsystem, string msg,    mixed ... args)
pike.git/lib/modules/Parser.pmod/LR.pmod/module.pmod:267:    error_handler(level, subsystem, msg, @args);    }       /*    * Sub-classes    */       //!    //! An LR(0) item, a partially parsed rule.    //! -  static class Item +  protected class Item    {    //! The rule    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    Kernel next_state;   
pike.git/lib/modules/Parser.pmod/LR.pmod/module.pmod:300:    //! 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;    -  static string _sprintf() +  protected string _sprintf()    {    array(string) res = ({ symbol_to_string(r->nonterminal), ":\t" });       if (offset) {    foreach(r->symbols[0..offset-1], int|string symbol) {    res += ({ symbol_to_string(symbol), " " });    }    }    res += ({ "· " });    if (offset != sizeof(r->symbols)) {
pike.git/lib/modules/Parser.pmod/LR.pmod/module.pmod:325:    if (sizeof(indices(direct_lookahead))) {    res += ({ "\t{ ",    map(indices(direct_lookahead), symbol_to_string) * ", ",    " }" });    }    return res * "";    }    }       //! Implements an LR(1) state -  static class Kernel { +  protected class Kernel {       //! Used to check if a rule already has been added when doing closures.    multiset(Rule) rules = (<>);       //! Contains the items in this state.    array(Item) items = ({});       //! Used to lookup items given rule and offset    mapping(int:Item) item_id_to_item = ([]);   
pike.git/lib/modules/Parser.pmod/LR.pmod/module.pmod:495:    i->next_state = new_state;    }    }    } else {    report(WARNING, "do_goto",    "do_goto() on unknown symbol <%s>",    symbol_to_string(symbol));    }    }    -  static string _sprintf() +  protected string _sprintf()    {    return sprintf("%{%s\n%}", items);    }    }       //! This is a queue, which keeps the elements even after they are retrieved. -  static class StateQueue { +  protected class StateQueue {       //! Index of the head of the queue.    int head;       //! Index of the tail of the queue.    int tail;       //! The queue itself.    array(Kernel) arr = allocate(64);   
pike.git/lib/modules/Parser.pmod/LR.pmod/module.pmod:546:    }       /*    * Functions    */       /* Here are some help functions */       /* Several cast to string functions */    -  static string builtin_symbol_to_string(int|string symbol) +  protected string builtin_symbol_to_string(int|string symbol)    {    if (intp(symbol)) {    return "nonterminal"+symbol;    } else {    return "\"" + symbol + "\"";    }    }    -  static function(int|string : string) symbol_to_string = builtin_symbol_to_string; +  protected 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(Rule r)    {    string res = symbol_to_string(r->nonterminal) + ":\t";       if (sizeof(r->symbols)) {
pike.git/lib/modules/Parser.pmod/LR.pmod/module.pmod:594:    //! Pretty-prints a state to a string.    //!    //! @param state    //! State to pretty-print.    string state_to_string(Kernel state)    {    return sprintf("%s", state);    }       //! Pretty-prints the current grammar to a string. -  static string _sprintf() +  protected string _sprintf()    {    array(string) res = ({});       foreach (indices(grammar), int nonterminal) {    res += ({ symbol_to_string(nonterminal) });    foreach (grammar[nonterminal], Rule r) {    res += ({ "\t: " });    if (sizeof(r->symbols)) {    foreach (r->symbols, int|string symbol) {    res += ({ symbol_to_string(symbol), " " });
pike.git/lib/modules/Parser.pmod/LR.pmod/module.pmod:829: Inside #if 0
   begins[symbol] = (< r2 >);    }    }    }    }   #endif /* 0 */    }       /* Here come the functions used by the compiler */    -  static Kernel first_state() +  protected Kernel first_state()    {    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], Rule r) {    if (!state->rules[r]) {    Item i = Item();
pike.git/lib/modules/Parser.pmod/LR.pmod/module.pmod:862:    }    }    }    return state;    }       //! Contains all states used.    //! In the queue section are the states that remain to be compiled.    StateQueue s_q;    -  static ADT.Stack item_stack; +  protected ADT.Stack item_stack;    -  static void traverse_items(Item i, +  protected void traverse_items(Item i,    function(int:void) conflict_func)    {    int depth;       item_stack->push(i);       i->counter = depth = item_stack->ptr;       foreach (indices(i->relation), Item i2) {    if (!i2->counter) {
pike.git/lib/modules/Parser.pmod/LR.pmod/module.pmod:908:    i->count = 0x7fffffff;       if (cyclic) {    report(NOTICE, "traverse_items", "Cyclic item\n%s",    item_to_string(i));    conflict_func(empty_cycle && !(sizeof(i->error_lookahead)));    }    }    }    -  static void shift_conflict(int empty) +  protected void shift_conflict(int empty)    {    empty; /* Ignored */    }    -  static void handle_shift_conflicts() +  protected 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, Item i) {    if ((i->offset != sizeof(i->r->symbols)) &&    (intp(i->r->symbols[i->offset])) &&    (!i->master_item)) {    /* Nonterminal master item */
pike.git/lib/modules/Parser.pmod/LR.pmod/module.pmod:940:       for (int index = 0; index < s_q->tail; index++) {    foreach (s_q->arr[index]->items, Item i) {    if (!i->number) {    traverse_items(i, shift_conflict);    }    }    }    }    -  static void follow_conflict(int empty) +  protected void follow_conflict(int empty)    {    empty; /* Ignored */    }    -  static void handle_follow_conflicts() +  protected 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, Item i) {    if ((i->offset != sizeof(i->r->symbols)) &&    (intp(i->r->symbols[i->offset])) &&    (!i->master_item)) {    /* Nonterminal master item */
pike.git/lib/modules/Parser.pmod/LR.pmod/module.pmod:972:       for (int index = 0; index < s_q->tail; index++) {    foreach (s_q->arr[index]->items, Item i) {    if (!i->number) {    traverse_items(i, follow_conflict);    }    }    }    }    -  static int go_through(Kernel state, int item_id, +  protected int go_through(Kernel state, int item_id,    Item current_item)    {    Item i, master;       i = state->item_id_to_item[item_id];       /* What to do if not found? */    if (!i) {    report(ERROR, "go_through",    "Item %d not found in state\n"
pike.git/lib/modules/Parser.pmod/LR.pmod/module.pmod:1017:    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 */    }    }    -  static int repair(Kernel state, multiset(int|string) conflicts) +  protected int repair(Kernel state, multiset(int|string) conflicts)    {    multiset(int|string) conflict_set = (<>);       report(NOTICE, "repair",    "Repairing conflict in state:\n%s\n"    "Conflicts on (< %s >)",    state_to_string(state),    map(indices(conflicts), symbol_to_string) * ", ");       foreach (indices(conflicts), int|string symbol) {