From 495344f3d853f87b619b0b79dfe877550345f12c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?= <grubba@grubba.org> Date: Sun, 30 Mar 1997 19:28:28 +0200 Subject: [PATCH] Added pikedoc-comments Rev: lib/modules/LR.pmod/Grammar_parser.pmod:1.3 Rev: lib/modules/LR.pmod/item.pike:1.2 Rev: lib/modules/LR.pmod/kernel.pike:1.2 Rev: lib/modules/LR.pmod/parser.pike:1.2 Rev: lib/modules/LR.pmod/priority.pike:1.2 Rev: lib/modules/LR.pmod/rule.pike:1.2 --- lib/modules/LR.pmod/Grammar_parser.pmod | 75 +++++++++++--- lib/modules/LR.pmod/item.pike | 41 ++++++-- lib/modules/LR.pmod/kernel.pike | 41 ++++++-- lib/modules/LR.pmod/parser.pike | 130 ++++++++++++++++++++---- lib/modules/LR.pmod/priority.pike | 35 +++++-- lib/modules/LR.pmod/rule.pike | 68 +++++++++++-- 6 files changed, 322 insertions(+), 68 deletions(-) diff --git a/lib/modules/LR.pmod/Grammar_parser.pmod b/lib/modules/LR.pmod/Grammar_parser.pmod index 69311fa79c..72c4fd6594 100755 --- a/lib/modules/LR.pmod/Grammar_parser.pmod +++ b/lib/modules/LR.pmod/Grammar_parser.pmod @@ -1,13 +1,43 @@ #!/home/grubba/src/pike/build/sol2.5/pike /* - * $Id: Grammar_parser.pmod,v 1.2 1997/03/28 14:42:43 grubba Exp $ + * $Id: Grammar_parser.pmod,v 1.3 1997/03/30 17:28:17 grubba Exp $ * * Generates a parser from a textual specification. * * Henrik Grubbstr�m 1996-12-06 */ +//. +//. File: Grammar_parser.pmod +//. RCSID: $Id: Grammar_parser.pmod,v 1.3 1997/03/30 17:28:17 grubba Exp $ +//. Author: Henrik grubbstr�m (grubba@infovav.se) +//. +//. Synopsis: Generates an LR parser from a textual specification. +//. +//. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//. +//. This module generates an LR parser from a grammar specified according +//. to the following grammar: +//. +//. 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 */ @@ -28,13 +58,13 @@ import LR; -private object(parser) _parser = parser(); +static private object(parser) _parser = parser(); /* * Scanner */ -class scan { +static private class scan { string str = ""; int pos; @@ -130,9 +160,9 @@ class scan { } } -private object(scan) scanner = scan(); +static private object(scan) scanner = scan(); -private array(string) nonterminals = ({ +static private array(string) nonterminals = ({ "translation_unit", "directives", "directive", @@ -147,17 +177,19 @@ private array(string) nonterminals = ({ "priority", }); -private object(Stack.stack) id_stack = Stack.stack(); +static private object(Stack.stack) id_stack = Stack.stack(); -private mapping(string:int) nonterminal_lookup = ([]); +static private mapping(string:int) nonterminal_lookup = ([]); -private object(parser) g; +static private object(parser) g; -private object master; +static private object master; +//. + error +//. Error code from the parsing. int error; -private int add_nonterminal(string id) +static private int add_nonterminal(string id) { int nt = nonterminal_lookup[id]; @@ -168,7 +200,7 @@ private int add_nonterminal(string id) return(nt); } -private void add_tokens(array(string) tokens) +static private void add_tokens(array(string) tokens) { /* NOOP */ #if 0 @@ -178,7 +210,7 @@ private void add_tokens(array(string) tokens) #endif /* 0 */ } -private void set_left_tokens(string ignore, int pri_val, array(string) tokens) +static private void set_left_tokens(string ignore, int pri_val, array(string) tokens) { foreach (tokens, string token) { g->set_associativity(token, -1); /* Left associative */ @@ -186,7 +218,7 @@ private void set_left_tokens(string ignore, int pri_val, array(string) tokens) } } -private string internal_symbol_to_string(int|string symbol) +static private string internal_symbol_to_string(int|string symbol) { if (intp(symbol)) { return (nonterminals[symbol]); @@ -195,7 +227,7 @@ private string internal_symbol_to_string(int|string symbol) } } -private string symbol_to_string(int|string symbol) +static private string symbol_to_string(int|string symbol) { if (intp(symbol)) { if (symbol < id_stack->ptr) { @@ -209,7 +241,7 @@ private string symbol_to_string(int|string symbol) } } -private void add_rule(int nt, string colon, array(mixed) symbols, string action) +static private void add_rule(int nt, string colon, array(mixed) symbols, string action) { if (action == ";") { action = 0; @@ -286,6 +318,14 @@ void create() _parser->compile(); } +//. - make_parser +//. +//. 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; @@ -328,6 +368,11 @@ object(parser) make_parser(string str, object|void m) return (res); } +//. - make_parser_from_file +//. +//. Compiles the file specified in the first argument into an LR parser. +//. +//. SEE ALSO: Grammar_parser.make_parser int|object(parser) make_parser_from_file(string f, object|void m) { object(files.file) f = files.file(); diff --git a/lib/modules/LR.pmod/item.pike b/lib/modules/LR.pmod/item.pike index 51f06d3f19..4da9b83369 100644 --- a/lib/modules/LR.pmod/item.pike +++ b/lib/modules/LR.pmod/item.pike @@ -1,28 +1,53 @@ /* - * $Id: item.pike,v 1.1 1997/03/03 23:50:15 grubba Exp $ + * $Id: item.pike,v 1.2 1997/03/30 17:28:20 grubba Exp $ * * An LR(0) item * * Henrik Grubbstr�m 1996-11-27 */ +//. +//. File: item.pike +//. RCSID: $Id: item.pike,v 1.2 1997/03/30 17:28:20 grubba Exp $ +//. Author: Henrik Grubbstr�m (grubba@infovav.se) +//. +//. Synopsis: An LR(0) item +//. +//. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//. +//. A partially parsed rule. +//. + import LR; /* constant kernel = (program)"kernel"; */ /* constant item = (program)"item"; */ -/* The rule */ +//. + r +//. The rule object(rule) r; -/* How long into the rule the parsing has come */ + +//. + offset +//. How long into the rule the parsing has come. int offset; -/* The state we will get if we shift */ + +//. + next_state +//. The state we will get if we shift according to this rule object /* (kernel) */ next_state; -/* Item representing this one (used for shifts) */ + +//. + master_item +//. Item representing this one (used for shifts). object /* (item) */ master_item = 0; -/* Look-ahead set for this item */ + +//. + direct_lookahead +//. Look-ahead set for this item. multiset(string) direct_lookahead = (<>); +//. + error_lookahead +//. Look-ahead set used for detecting conflicts multiset(string) error_lookahead = (<>); -/* Relation to other items (used when compiling) */ +//. + relation +//. Relation to other items (used when compiling). multiset(object /* (item) */ ) relation = (<>); -/* Depth counter (used when compiling) */ +//. + counter +//. Depth counter (used when compiling). int counter = 0; diff --git a/lib/modules/LR.pmod/kernel.pike b/lib/modules/LR.pmod/kernel.pike index f7ed03e2bb..57ac9d464a 100644 --- a/lib/modules/LR.pmod/kernel.pike +++ b/lib/modules/LR.pmod/kernel.pike @@ -1,33 +1,52 @@ /* - * $Id: kernel.pike,v 1.1 1997/03/03 23:50:16 grubba Exp $ + * $Id: kernel.pike,v 1.2 1997/03/30 17:28:22 grubba Exp $ * * Implements a LR(1) state; * * Henrik Grubbstr�m 1996-11-25 */ +//. +//. File: kernel.pike +//. RCSID: $Id: kernel.pike,v 1.2 1997/03/30 17:28:22 grubba Exp $ +//. Author: Henrik Grubbstr�m +//. +//. Synopsis: Implements an LR(1) state. +//. +//. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//. +//. State in the LR(1) state-machine. +//. + import LR; -/* Used to check if a rule already has been added when doing closures */ +//. + rules +//. Used to check if a rule already has been added when doing closures. multiset(object(rule)) rules = (<>); -/* Contains the items in this state */ +//. + items +//. Contains the items in this state. array(object(item)) items = ({}); -/* Contains the items whose next symbol is this non-terminal */ +//. + symbol_items +//. Contains the items whose next symbol is this non-terminal. mapping(int : multiset(object(item))) symbol_items = ([]); -/* The action table for this state - * - * object(kernel) SHIFT to this state on this symbol. - * object(rule) REDUCE according to this rule on this symbol. - */ +//. + action +//. The action table for this state +//. +//. 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 = ([]); /* * Functions */ +//. - add_item +//. Add an item to the state. +//. > i +//. Item to add. void add_item(object(item) i) { int|string symbol; @@ -44,6 +63,10 @@ void add_item(object(item) i) } } +//. - equalp +//. Compare with another state. +//. > state +//. State to compare with. int equalp(object /* (kernel) */ state) { /* Two states are the same if they contain the same items */ diff --git a/lib/modules/LR.pmod/parser.pike b/lib/modules/LR.pmod/parser.pike index d666df7f5f..fcfa791840 100644 --- a/lib/modules/LR.pmod/parser.pike +++ b/lib/modules/LR.pmod/parser.pike @@ -1,5 +1,5 @@ /* - * $Id: parser.pike,v 1.1 1997/03/03 23:50:18 grubba Exp $ + * $Id: parser.pike,v 1.2 1997/03/30 17:28:25 grubba Exp $ * * A BNF-grammar in Pike. * Compiles to a LALR(1) state-machine. @@ -7,6 +7,26 @@ * Henrik Grubbstr�m 1996-11-24 */ +//. +//. File: parser.pike +//. RCSID: $Id: parser.pike,v 1.2 1997/03/30 17:28:25 grubba Exp $ +//. Author: Henrik Grubbstr�m (grubba@infovav.se) +//. +//. Synopsis: LALR(1) parser and compiler. +//. +//. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//. +//. This object implements an LALR(1) parser and compiler. +//. +//. Normal use of this object would be: +//. +//. {add_rule, set_priority, set_associativity}* +//. set_scanner +//. set_symbol_to_string +//. compile +//. {parse}* +//. + /* * Includes */ @@ -39,14 +59,25 @@ * Classes */ +//. o state_queue +//. +//. This is a combined set and queue. class state_queue { - /* - * This is a combined set and queue. - */ - - int head, tail; + //. + head + //. Index of the head of the queue. + int head; + //. + tail + //. Index of the tail of the queue. + int tail; + //. + arr + //. The queue/set itself. array(object(LR.kernel)) arr=allocate(64); + //. - memberp + //. Returns the index of the state in arr if present. + //. Returns -1 on failure. + //. > state + //. State to search for. int|object(LR.kernel) memberp(object(LR.kernel) state) { int j; @@ -59,6 +90,10 @@ class state_queue { return(-1); } + //. - push_if_new + //. Pushes the state on the queue if it isn't there already. + //. > state + //. State to push. object(LR.kernel) push_if_new(object(LR.kernel) state) { int index; @@ -75,6 +110,8 @@ class state_queue { } } + //. - next + //. Return the next state from the queue. int|object(LR.kernel) next() { if (head == tail) { @@ -110,13 +147,14 @@ static private mapping(int : multiset(object(rule))) used_by = ([]); static private object(kernel) start_state; -/* Verbosity level - * 0 - none - * 1 - some - */ +//. + verbose +//. Verbosity level +//. 0 - none +//. 1 - some int verbose=1; -/* Error code */ +//. + error +//. Error code int error=0; /* Number of next rule (used only for conflict resolving) */ @@ -141,20 +179,28 @@ static private string builtin_symbol_to_string(int|string symbol) static private function(int|string : string) symbol_to_string = builtin_symbol_to_string; +//. - rule_to_string +//. Pretty-prints a rule to a string. +//. > r +//. Rule to print. string rule_to_string(object(rule) r) { - array(string) res = ({ symbol_to_string(r->nonterminal), ":\t" }); + string res = symbol_to_string(r->nonterminal) + ":\t"; if (sizeof(r->symbols)) { foreach (r->symbols, int|string symbol) { - res += ({ symbol_to_string(symbol), " " }); + res += symbol_to_string(symbol) + " "; } } else { - res += ({ "/* empty */" }); + res += "/* empty */"; } - return(res * ""); + return(res); } +//. - item_to_string +//. Pretty-prints an item to a string. +//. > i +//. Item to pretty-print. string item_to_string(object(item) i) { array(string) res = ({ symbol_to_string(i->r->nonterminal), ":\t" }); @@ -178,11 +224,17 @@ string item_to_string(object(item) i) return(res * ""); } +//. - state_to_string +//. Pretty-prints a state to a string. +//. > state +//. State to pretty-print. string state_to_string(object(kernel) state) { return (map(state->items, item_to_string) * "\n"); } +//. - cast_to_string +//. Pretty-prints the current grammar to a string. string cast_to_string() { array(string) res = ({}); @@ -205,6 +257,10 @@ string cast_to_string() return (res * ""); } +//. - cast +//. Implements casting. +//. > type +//. Type to cast to. mixed cast(string type) { if (type == "string") { @@ -215,6 +271,12 @@ mixed cast(string type) /* Here come the functions that actually do some work */ +//. - set_priority +//. Sets the priority of a terminal. +//. > terminal +//. Terminal to set the priority for. +//. > pri_val +//. Priority; higher = prefer this terminal. void set_priority(string terminal, int pri_val) { object(priority) pri; @@ -226,6 +288,12 @@ void set_priority(string terminal, int pri_val) } } +//. - set_associativity +//. Sets the associativity of a terminal. +//. > terminal +//. Terminal to set the associativity for. +//. > assoc +//. Associativity; negative - left, positive - right, zero - no associativity. void set_associativity(string terminal, int assoc) { object(priority) pri; @@ -237,7 +305,14 @@ void set_associativity(string terminal, int assoc) } } -void set_symbol_to_string(function(int|string:string) s_to_s) +//. - set_symbol_to_string +//. Sets the symbol to string conversion function. +//. The conversion function is used by the various *_to_string functions +//. to make comprehensible output. +//. > 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; @@ -246,7 +321,10 @@ void set_symbol_to_string(function(int|string:string) s_to_s) } } -/* Add a rule to the grammar */ +//. - add_rule +//. Add a rule to the grammar. +//. > r +//. Rule to add. void add_rule(object(rule) r) { array(object(rule)) rules; @@ -946,6 +1024,8 @@ static private int repair(object(kernel) state, multiset(int|string) conflicts) } } +//. - compile +//. Compiles the grammar into a parser, so that parse() can be called. int compile() { int error = 0; /* No error yet */ @@ -1161,6 +1241,22 @@ int compile() return (error); } +//. - parse +//. Parse the input according to the compiled grammar. +//. The last value reduced is returned. +//. NOTA BENE: +//. The parser must have been compiled (with compile()), and a scanner +//. been set (with set_scanner()) prior to calling this function. +//. BUGS +//. Errors should be throw()n. +//. > 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. +//. > action_object +//. Object used to resolve those actions that have been specified as +//. strings. mixed parse(function(void:string|array(string|mixed)) scanner, void|object action_object) { diff --git a/lib/modules/LR.pmod/priority.pike b/lib/modules/LR.pmod/priority.pike index abe9e1d4e8..3eeacb0898 100644 --- a/lib/modules/LR.pmod/priority.pike +++ b/lib/modules/LR.pmod/priority.pike @@ -1,22 +1,41 @@ /* - * $Id: priority.pike,v 1.1 1997/03/03 23:50:19 grubba Exp $ + * $Id: priority.pike,v 1.2 1997/03/30 17:28:27 grubba Exp $ * * Rule priority specification * * Henrik Grubbstr�m 1996-12-05 */ -/* Priority value */ +//. +//. File: priority.pike +//. RCSID: $Id: priority.pike,v 1.2 1997/03/30 17:28:27 grubba Exp $ +//. Author: Henrik Grubbstr�m (grubba@infovav.se) +//. +//. Synopsis: Rule priority specification. +//. +//. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//. +//. Specifies the priority and associativity of a rule. +//. + +//. + value +//. Priority value int value; -/* Associativity - * - * -1 - left - * 0 - none - * +1 - right - */ +//. + assoc +//. Associativity +//. +//. -1 - left +//. 0 - none +//. +1 - right int assoc; +//. - create +//. Create a new priority object. +//. > p +//. Priority. +//. > a +//. Associativity. void create(int p, int a) { value = p; diff --git a/lib/modules/LR.pmod/rule.pike b/lib/modules/LR.pmod/rule.pike index 4952dca5d3..97c9fdfc1f 100644 --- a/lib/modules/LR.pmod/rule.pike +++ b/lib/modules/LR.pmod/rule.pike @@ -1,31 +1,50 @@ /* - * $Id: rule.pike,v 1.1 1997/03/03 23:50:21 grubba Exp $ + * $Id: rule.pike,v 1.2 1997/03/30 17:28:28 grubba Exp $ * * A BNF-rule. * * Henrik Grubbstr�m 1996-11-24 */ +//. +//. File: rule.pike +//. RCSID: $Id: rule.pike,v 1.2 1997/03/30 17:28:28 grubba Exp $ +//. Author: Henrik Grubbstr�m (grubba@infovav.se) +//. +//. Synopsis: Implements a BNF rule. +//. +//. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//. +//. This object is used to represent a BNF-rule in the LR parser. +//. + /* * Object variables */ -/* Nonterminal this rule reduces to */ +//. + nonterminal +//. Non-terminal this rule reduces to. int nonterminal; -/* The actual rule */ +//. + symbols +//. 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 - */ +//. + action +//. 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 */ +//. + has_tokens +//. This rule contains tokens int has_tokens = 0; -/* This rule has this many nonnullable symbols at the moment */ +//. + num_nonnullables +//. This rule has this many non-nullable symbols at the moment. int num_nonnullables = 0; /* @@ -33,13 +52,40 @@ multiset(int) prefix_nonterminals = (<>); multiset(string) prefix_tokens = (<>); */ -/* Number of this rule (used for conflict resolving) */ +//. + number +//. Sequence number of this rule (used for conflict resolving) int number = 0; /* * Functions */ +//. - create +//. 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. +//. > nt +//. Non-terminal to reduce to. +//. > r +//. Symbol sequence that reduces to nt. +//. > 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 be +//. 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; -- GitLab