@q file: macros.w@> @q% Copyright Dave Bone 1998 - 2015@> @q% /*@> @q% This Source Code Form is subject to the terms of the Mozilla Public@> @q% License, v. 2.0. If a copy of the MPL was not distributed with this@> @q% file, You can obtain one at http://mozilla.org/MPL/2.0/.@> @q% */@> @** Macro definitions.\fbreak I use macros of \CPLUSPLUS/ and |cweb| variety. Their use covers terminal constructor initialization, tracing of flow control events, parse stack configuration and syntax directed directives, utilities to deal with specific parse situations or results, and aid macros to debug grammars. As log trace files can be volumous, i placed within each logged message the macro variable's name that controls its output. For example, |YACCO2_MSG__| controls signalling between threads as in wait-for-wakeup message from one of the called threads etc. I'll see how refined this is by use of an UNIX shell's scripting language like ``bash'' with piping. I'll let u posted. @*2 Copyright. @= // copyright @*2 |EXTERNAL_GPSing| macro is used to print out T's external file.\fbreak The external file comes from |tok_can| container use that registers the external files processed with |FILE_TBL__|. A created T has a subscript reference into this stack. Sanity check must exist against the |FILE_TBL__| registrar or a possible out-of-subscript error could be thrown. One misuse is to process the ``command line'' input where the input is written to a holding file. A hardwiring of 1 for the file is used as the ``holding file'' is the first file inputted to |Yacco2|. But if the holding file name is illegal, a T error of ``bad file inputted'' created with this file reference as crap. The other potential error is the CLI inputted file is non existent and creating the error T referenced to the holding file which has not been registered with |FILE_TBL__| thru |tok_can| container create also becomes poop-poop. Now u defined an Error\_handler grammar to trace out those errors expecting to see the traced output with the external file name and its contents line references. Say the ``holding file'' exists with the command line data placed there but never registered the holding file with the |tok_can|. Hence the {\bf non registering of the CLI holding file} will not be printed by the parser / Error processing grammar. See the ``./grammar-testsuite/testout.pdf'' program as an example of ``command line processing'' to avoid the above errors. @d EXTERNAL_GPSing(TOK__) if(TOK__->tok_co_ords__.external_file_id__ < yacco2::FILE_TBL__.size()){ yacco2::lrclog << yacco2::FILE_TBL__[TOK__->tok_co_ords__.external_file_id__].c_str(); }else { yacco2::lrclog << " EXTERNAL_GPSing - No external file registered to use" << " stack subscript: " << TOK__->tok_co_ords__.external_file_id__; } @*2 |FILE_LINE| macro source file co-ordinates for tracing.\fbreak Add the file and line number to the dynamic tracing output. Allows one to go to the source code if things are askew. Gum stuck to your shoe but hey it's an indication. @d FILE_LINE ' ' << __FILE__ << ": " << __LINE__ @*2 |T_CTOR| macro is used by the terminal defs supplied to the grammar.\fbreak When a terminal definition needs to be customized, the grammar writer can roll his own class definition. It just initializes the base variables within the class constructor's implementation. Its name is composed of |T| indicating for terminals, and the |CTOR| uses the \CPLUSPLUS/ naming convention to indicate that it belongs to the class constructor. Please have a look at Yacco2's |yacco2_k_symbols.lex| file that defines the lr constants definitions for a demonstration of use. For the moment there are 5 parameters: A..E. Originally there was more to handle the push-pop-lookahead functors. From Yacco2's use, these functors were never needed. It was only during my Master's thesis that they got their 15 minutes of fame. \ptindent{Parameter A: provides the terminal's literal name for tracing} \ptindent{Parameter B is the enumerated value} It is symbolically gened by prefixing an |T_| to the `\CPLUSPLUS/' name of the terminal and ending it off with a |_| suffix. This is described in |Enumeration of Alphabets|. \ptindent{Parameter C is the address of the class destructor function or nil} I know, this should be automatically detected by Yacco2's parse generator but for now this is reality: still outstanding. |parser__| is the associated parser for the grammar used by the grammar's rules. As the |CAbs_lr1_sym| is a base structure for both the terminals and rules of the grammar, it has no associated parser for the terminals as terminals are nomadic by nature. Normally |tok_co_ords__|'s attributes are overriden by a raw character co-ordinates. Terminals are composites of other basic entities like raw character terminals. \ptindent{Parameter D is auto delete boolean value of ON or OFF} \ptindent{Parameter E is auto abort boolean value of ON or OFF} An auto delete attribute indicates that the terminal is deleted when popped from the parse stack. When an abort of a parse occurs, this attribute when turned on indicates that the object should be deleted. It's a `clean up your own mess' attribute. Both paramaters relate to the terminal's `AD' and `AB' grammatical attributes. An example of |T_CTOR| use is:\fbreak \ptindent{|T_CTOR|("labeled-stmt",|T_T_labeled_stmt_|,|&dtor_T_labeled_stmt|,OFF,ON)} |T_CTOR_RW| macro handles the raw character terminals. The additional 2 parameters F, and G are the source file index and character position within the file. Please look at Yacco2's |yacco2_characters.lex| file to see an example of |T_CTOR_RW| use. The |Yacco2| runtime environment maintains an index of files included into the source grammar. |FILE_TBL__| is a vector of file index and the external filename literal. |FILE_CNT__| is the matching external variable used by the include file grammar that stacks them when nested include statements come into and out of scope. From the raw character classes, the GPS of the character is passed in as parameters. A specialized |tok_can| template for `file to raw character' object mapping handles this task. @*2 |T_CTOR|, |T_CTOR_RW| macros. @d T_CTOR(A,B,C,D,E) :CAbs_lr1_sym(A,C,B,D,E) @d T_CTOR_RW(A,B,C,D,E,F,G) :CAbs_lr1_sym(A,C,B,D,E,F,G) @*2 Define |YACCO2_define_trace_variables|.\fbreak See ``The \CPLUSPLUS/ preprocessor coding game'' regarding the individual tracing variable functionality. @d YACCO2_define_trace_variables() int yacco2::YACCO2_T__(OFF); int yacco2::YACCO2_TLEX__(OFF); int yacco2::YACCO2_MSG__(OFF); int yacco2::YACCO2_TH__(OFF); int yacco2::YACCO2_AR__(OFF); int yacco2::YACCO2_THP__(OFF); int yacco2::YACCO2_MU_TRACING__(OFF); int yacco2::YACCO2_MU_TH_TBL__(OFF); int yacco2::YACCO2_MU_GRAMMAR__(OFF); @*2 Token placement macros.\fbreak They are used by the grammar writer within syntax directed code sections of a grammar to place a token into appropriate queues:\fbreak \ptindent{recycle container --- used to delete or re-integrate tokens back into a parse stream} \ptindent{accept container --- tokens returned by launched threads for arbitration} \ptindent{producer container - tokens outputted for other parse stages} \ptindent{error container --- a container of accrued error tokens} \ptindent{supplier of tokens --- token stream that a grammar parses} @*3 |ADD_TOKEN_TO_RECYCLE_BIN|.\fbreak This is a holding pen for possibly re-use of the token that has been pulled out of the token stream. It is a minor facility but has poco merit. @d ADD_TOKEN_TO_RECYCLE_BIN(Token) rule_info__.parser__->add_token_to_recycle_bin(Token) @*3 |DELETE_T_SYM| macro.\fbreak This macro deletes a T when passed by pointer. It only allows Tes that are from either Error or Meta-terminal classes. This guards against the erasing of preallocated Tes of LR k or RC (raw chacacter) classes. They are preallocated from the memory heap for speed. It checks whether the symbol's |dtor__| static method is present and calls it. This allows a delete chain calling of other dependents or other dependencies when the |destructor| directive is used within the T grammar definition. Why this route to T symbol deletes rather than c++'s dtor: |~T()|? Mixed into the fray is my |AB| abort parse stack cleanup. Whether its of any use this is my experiment. It required the stack frame pointer as the 2nd parameter. For the just plain way to deletes, this macro eases the complaints without the stack frame pointer. Depending on how your compiler/translator runs, deleting of Tes could be left to the process teardown. If your language recognizer is always on and being invoked like an Internet protocol, then T hygiene is required or those memory leaks will haunt u. @d DELETE_T_SYM(T) if(T != 0){ if(T->enumerated_id__ > END_OF_RC_ENUMERATE){ if(T->dtor__ != 0){ (*T->dtor__)(T,0);// stack frame 0 } delete T; } } @*3 Add token to an accept queue: |RSVP|, |RSVP_FSM|, |RSVP_WLA| macros.\fbreak |RSVP| places a token into the calling grammar's accept queue that requested this thread. It can be placed anywhere in the syntax directed code of the grammar except within the grammar's fsm context where you use the |RSVP_FSM| macro. The |RSVP_WLA| allows u to override the lookahead bounds instead of taking as default the current token. A quick review of messages, threads, and accept tokens:\fbreak \ptindent{the calling grammar: 1:m launching of threads} \ptindent{accept queue: 0:m potential tokens returned by launched threads} \ptindent{1 wakeup event to calling grammar by thread finished last in execution} Arbitration is used by the caller grammar when it is re-activated by an event (message) from the thread finishing last in execution order: the status message ``accept parallel parse'' is posted to just wake up the calling grammar regardless of the overall parse success by the launched threads. It is the |th_accepting_cnt__| that determines whether the threads were successful or not. It only occurs when there are items in the accept queue. If none of the launched threads are successful in their parsing, then the calling grammar will attempt to go through its conditional parsing (non-determinism). Arbitration is the associated code within the grammar's fsm state that launched the threads. It rules on possibly more than one accept token being returned. A little french spices up this ho-hum macro. Why is there an accepted token position? Remember the current token in the thread's parse stream is now the future position in the token stream to continue parsing from for the calling grammar. In a long stream of characters that makes up the accept token, usually its the start token's position passed to the called thread that is used to GPS it's position within the token stream. The current token context ( I call the ``lookahead context'') is provided by the last 2 parameters for the |Caccept_parse|. It is this lookahead context of the accepted token that is used to continue parsing within the calling grammar. The arbitrated token is parallel shifted and its accompaning lookahead boundry is then used to reduce the parallel shift's subrule expression. All other potential accept tokens are flushed out of the accept queue. @d RSVP(Token) rule_info__.parser__->pp_rsvp__.fill_it(*rule_info__.parser__ ,*Token,Token->tok_co_ords__.rc_pos__ ,*rule_info__.parser__->current_token__ ,rule_info__.parser__->current_token_pos__) @d RSVP_WLA(Token,LATOK,LAPOS) rule_info__.parser__->pp_rsvp__.fill_it(*rule_info__.parser__ ,*Token,Token->tok_co_ords__.rc_pos__ ,*LATOK ,LAPOS) @d RSVP_FSM(Token) parser__->pp_rsvp__.fill_it(*parser__ ,*Token,Token->tok_co_ords__.rc_pos__ ,*parser__->current_token__,parser__->current_token_pos__) @*3 |ADD_TOKEN_TO_PRODUCER_QUEUE|.\fbreak This allows one to output from a parse a terminal stream that becomes a supplier queue for another grammar to parse. @d ADD_TOKEN_TO_PRODUCER_QUEUE(TOKEN) rule_info__.parser__->add_token_to_producer(TOKEN) @*3 |ADD_TOKEN_TO_ERROR_QUEUE| and |ADD_TOKEN_TO_ERROR_QUEUE_FSM|.\fbreak This becomes a holding queue that can be processed by a error grammar. It's a nice way to format parsing errors. It is the context that determines which macro to use. @d ADD_TOKEN_TO_ERROR_QUEUE(TOKEN) rule_info__.parser__->add_token_to_error_queue(TOKEN) @d ADD_TOKEN_TO_ERROR_QUEUE_FSM(TOKEN) parser__->add_token_to_error_queue(TOKEN) @*2 Generated finite state automaton macros.\fbreak They are included in the \CPLUSPLUS/ code of each rule emitted by Yacco2. Their names are sufficient to explain their intent. Why the wrapping of the macros within the @@$=$ ... @@$>$ construct instead of a plain macro ``|#define|'' definition? Glad u asked. The |cweave| version ``7.5.5'' on a Mac emits code that |pdftex| Version 3.141592-1.30.4-2.2 honks: too many {$``\}''$} or {``\$''}. So this is my workaround until i have time to get a higher version of cweave. Note: the |cweb| Microsoft flavour works. More rumblings from within my quest to port Yacco2. Screw the port. i need to read it.\fbreak Brought back |cweb| macros as they work on the Mac now. @d ssNEW_TRACEss(ssPss,ssQss) yacco2::lrclog << "\t!!!!! new adr: " << (void*)ssPss << " " << #ssQss << ' '<<__FILE__<<':'<<__LINE__<< std::endl; yacco2::lrclog << "\tfile: " << __FILE__ << " line: " << __LINE__ << std::endl; @d ssP_TRACEss(ssPss,ssQss) yacco2::lrclog << '\t' << Parse_env->thread_no__ << "\t!!!!! new adr: " << (void*)ssPss << " " << #ssQss <thread_no__ << rule_info__.parser__->fsm_tbl__->id__ << "::" << id__ << "::op()\n"; } } @d sstrace_rulesss if(yacco2::YACCO2_TLEX__){ bool to_trace_or_not_to = trace_parser_env(rule_info__.parser__,FORCE_STK_TRACE); if(to_trace_or_not_to == true){ yacco2::lrclog << "\tYACCO2_TLEX__::" << rule_info__.parser__->thread_no__ << "::" << rule_info__.parser__->fsm_tbl__->id__ << "::" << id__ << "::op()\n"; } } @d sstrace_sub_rulesss if(yacco2::YACCO2_TLEX__){ bool to_trace_or_not_to = trace_parser_env(rule_info__.parser__,FORCE_STK_TRACE); if(to_trace_or_not_to == true){ yacco2::lrclog << "\tYACCO2_TLEX__::" << rule_info__.parser__->thread_no__ << "::" << rule_info__.parser__->fsm_tbl__->id__ << "::" << id__ << "::op()\n"; } } @d sstrace_stack_rtnsss @/ if(yacco2::YACCO2_TLEX__){ @/ bool to_trace_or_not_to = trace_parser_env(Parse_env,FORCE_STK_TRACE)); if(to_trace_or_not_to == true){ yacco2::lrclog << "\tYACCO2_TLEX__::" << Parse_env->thread_no__ << "::" << Parse_env->fsm_tbl__->id__ << "::op() sym: " << id__ << FILE_LINE<< std::endl; } } @*2 Pushdown automaton's flow control macros.\fbreak They are placed in stragetic places for operations accept, reduce, shift, and abort. As there are many points being traced, a little explanation is required to give some semblance of order. The messages outputted go to a log file named `tracings.log'. What type of name is this? The prefix 1 sorts the file to the top of a directory. The balance of the name was an attempt to say lr output of clog type. Ugh. This will be changed. Messages logged fall into the parsing configuration that tries to give a semblance of a stack. It prints the stack content in bottomup order. A sample of the trace is:\fbreak \ptindent{|..1500::rule_def_phrase.lex::1--identifier-> 3|} The dots indicate the number of items on the stack to be displayed, followed by the thread's identity --- a runtime thread number and the grammar's name being traced. Following this are the stacked items displayed in bottom-to-top order. Each item contains the finite state that it is in, a vector containing the stacked item and the finite state's shift into state no. Other traces will try to output regular sentences so that they can be parsed by a grammar or a scripting language. This will allow one to digest intelligently the interplay between the grammar, and the appropriate running threads. As there are many threads simultaneously running, this will help in consolidating the reported tracings. @^ To do canonize the traced output@> @*3 |T_0| trace remove items from the parse stack. @= if(YACCO2_TH__){ if(fsm_tbl__->debug__ == ON){ @; yacco2::lrclog << "YACCO2_TH__::" << thread_no__ << "::" << fsm_tbl__->id__ << ":: Popping items from stack # to pop: " << No_to_remove << FILE_LINE<< std::endl; @; } } @*3 |T_0a| trace finished removing items from the parse stack. @= if(YACCO2_TH__){ if(fsm_tbl__->debug__ == ON){ @; yacco2::lrclog << "YACCO2_TH__::" << thread_no__ << "::" << fsm_tbl__->id__ << ":: Finished Popping items from stack" << FILE_LINE<< std::endl; @; } } @*3 |T_1| trace the parse stack if the grammar is requesting to be debugged. The returned debug switch's value is dropped. @= if(YACCO2_TH__){ bool to_trace_or_not_to = trace_parser_env(this,COND_STK_TRACE); } @*3 |T_2| trace when an epsilon rule is being reduced. @= if(YACCO2_TH__){ bool to_trace_or_not_to = trace_parser_env(this,COND_STK_TRACE); if(to_trace_or_not_to == YES){ @; yacco2::lrclog << "\tYACCO2_TH__::" << thread_no__ << "::" << fsm_tbl__->id__ << "::epsilon" << FILE_LINE<< std::endl; @; } } @*3 |T_3| trace the state no when popped from the parse stack. @= if(YACCO2_TH__){ bool to_trace_or_not_to = trace_parser_env(this,COND_STK_TRACE); if(to_trace_or_not_to == YES){ @; yacco2::lrclog << "\tYACCO2_TH__::" << thread_no__; yacco2::lrclog << "::" << fsm_tbl__->id__ << "::popped state:: "; yacco2::lrclog << pr->state__->state_no__ << FILE_LINE<< std::endl; @; } } @*3 |T_4| trace when invisible shift symbol popped from stack.\fbreak Because this symbol is universal, ?? chk why zeroed instead of not having AD on? @= if(YACCO2_TH__){ bool to_trace_or_not_to = trace_parser_env(this,COND_STK_TRACE); if(to_trace_or_not_to == YES){ @; yacco2::lrclog << "\tYACCO2_TH__::" << thread_no__ << "::" << fsm_tbl__->id__ << "::exposed rule/terminal:: NULL due to invisible shift" << FILE_LINE<< std::endl; @; } } @*3 |T_5| trace exposed symbol on parse stack. @= if(YACCO2_TH__){ bool to_trace_or_not_to = trace_parser_env(this,COND_STK_TRACE); if(to_trace_or_not_to == YES){ @; yacco2::lrclog << "\tYACCO2_TH__::" << thread_no__ << "::" << fsm_tbl__->id__ << "::exposed rule/terminal:: " << parse_stack__.top__->symbol__->id__ << ' ' << parse_stack__.top__->symbol__ << FILE_LINE<< std::endl; @; } } @*3 |T_6| trace top item on the parse stack when auto-delete switch on.\fbreak This is the grammatical attribute AD requesting deletion when popped from the parse stack. @= if(YACCO2_TH__){ bool to_trace_or_not_to = trace_parser_env(this,COND_STK_TRACE); if(to_trace_or_not_to == YES){ if(parse_stack__.top__->symbol__->auto_delete__ == YES){ @; yacco2::lrclog << "\tYACCO2_TH__::" << thread_no__ << "::" << fsm_tbl__->id__ << "::AD deleting exposed rule/terminal:: " << parse_stack__.top__->symbol__->id__ << ' ' << parse_stack__.top__->symbol__ << FILE_LINE<< std::endl; @; } } } @*3 |T_6a| trace top item on the parse stack when auto-abort switch on.\fbreak This occurs usually at abort time of a threaded parse. It can occur when the grammar writer has not removed the appropriate objects from being checked by a destructor directive for deletion in a grammar rule. @= if(YACCO2_TH__){ bool to_trace_or_not_to = trace_parser_env(this,COND_STK_TRACE); if(to_trace_or_not_to == YES){ if(parse_stack__.top__->symbol__->affected_by_abort__ == YES){ @; yacco2::lrclog << "\tYACCO2_TH__::" << thread_no__ << "::" << fsm_tbl__->id__ << "::AB deleting exposed rule/terminal:: " << parse_stack__.top__->symbol__->id__ << ' ' << parse_stack__.top__->symbol__ << FILE_LINE<< std::endl; @; } } } @*3 |T_7| trace when threading failed: try straight parse. @= if(YACCO2_TH__){ bool to_trace_or_not_to = trace_parser_env(this,COND_STK_TRACE); if(to_trace_or_not_to == YES){ @; yacco2::lrclog << "YACCO2_TH__::" << thread_no__ << "::" << fsm_tbl__->id__ << "::############# TRY STRAIGHT try_straight_due_to_aborted_parallel" << " reset token pos: " << current_token_pos__ << " reset token: " << current_token__->id__ << FILE_LINE<< std::endl; yacco2::lrclog << "\tYACCO2_TH__::" << thread_no__ << "::GPS RESET FILE: "; EXTERNAL_GPSing(current_token()) yacco2::lrclog << " GPS RESET LINE: " << current_token()->tok_co_ords__.line_no__ << " GPS RESET CHR POS: " << current_token()->tok_co_ords__.pos_in_line__ << FILE_LINE<< std::endl; @; } } @*3 |T_7| trace when proc call failed: try straight parse. @= if(YACCO2_TH__){ bool to_trace_or_not_to = trace_parser_env(this,COND_STK_TRACE); if(to_trace_or_not_to == YES){ @; yacco2::lrclog << "YACCO2_TH__::" << thread_no__ << "::" << fsm_tbl__->id__ << "::############# TRY STRAIGHT try_straight_due_to_aborted_parallel" << " reset token pos: " << current_token_pos__ << " reset token: " << current_token__->id__ << FILE_LINE<< std::endl; yacco2::lrclog << "\tYACCO2_TH__::" << thread_no__ << "::GPS RESET FILE: "; EXTERNAL_GPSing(current_token()) yacco2::lrclog << " GPS RESET LINE: " << current_token()->tok_co_ords__.line_no__ << " GPS RESET CHR POS: " << current_token()->tok_co_ords__.pos_in_line__ << FILE_LINE<< std::endl; @; } } @*3 |T_11| straight parse error.\fbreak How and why NIL pointer? protects when the @= if(YACCO2_TH__){ bool to_trace_or_not_to = trace_parser_env(this,COND_STK_TRACE); if(to_trace_or_not_to == YES){ @; yacco2::lrclog << "\tYACCO2_TH__::" << thread_no__ << "::" << fsm_tbl__->id__ << "::"; yacco2::lrclog << "#############straight parse-error current token " << '"' << current_token()->id__ << '"' << " pos: " << current_token_pos__ << FILE_LINE<< std::endl; yacco2::lrclog << "\tYACCO2_TH__::" << thread_no__ << "::GPS RESET FILE: "; EXTERNAL_GPSing(current_token()) yacco2::lrclog << " GPS RESET LINE: " << current_token()->tok_co_ords__.line_no__ << " GPS RESET CHR POS: " << current_token()->tok_co_ords__.pos_in_line__ << FILE_LINE<< std::endl; @; } } @*3 |T_14| trace parallel parse thread startup communication. @= if(YACCO2_TH__){ bool to_trace_or_not_to = trace_parser_env(this,COND_STK_TRACE); if(to_trace_or_not_to == YES){ @; yacco2::lrclog << "YACCO2_TH__::" << "requestor of parallelism* : " << " pp id: " << thread_no__ << "::" << thread_name() << " parallel PP started: " << pe->thread_fnct_name__ << FILE_LINE<< std::endl; @; } } @*3 |T_17| trace accepted token info. @= if(YACCO2_TH__){ bool to_trace_or_not_to = trace_parser_env(this,COND_STK_TRACE); if(to_trace_or_not_to == YES){ @; yacco2::lrclog << "\tYACCO2_TH__::" << thread_no__ << "::||||||||||ACCEPTED token POS: " << arbitrated_token__->accept_token_pos__ << " token*: " << arbitrated_token__->accept_token__ << " token: " << arbitrated_token__->accept_token__->id__ << std::endl; yacco2::lrclog << "\tYACCO2_TH__::" << thread_no__ << "::GPS FILE: "; EXTERNAL_GPSing(arbitrated_token__->accept_token__) yacco2::lrclog << " GPS LINE: " << arbitrated_token__->accept_token__->tok_co_ords__.line_no__ << " GPS CHR POS: " << arbitrated_token__->accept_token__->tok_co_ords__.pos_in_line__ << FILE_LINE<< std::endl; yacco2::lrclog << "\tYACCO2_TH__::" << thread_no__ << "::||||||||||ACCEPTED la token POS: " << arbitrated_token__->la_token_pos__ << " la token: " << arbitrated_token__->la_token__->id__ << std::endl; yacco2::lrclog << "\t" << thread_no__ << "::GPS LA FILE: "; EXTERNAL_GPSing(arbitrated_token__->la_token__) yacco2::lrclog << " GPS LA LINE: " << arbitrated_token__->la_token__->tok_co_ords__.line_no__ << " GPS LA CHR POS: " << arbitrated_token__->la_token__->tok_co_ords__.pos_in_line__ << FILE_LINE<< std::endl; @; } } @*3 Trace re-aligned token stream la boundry info. @= if(YACCO2_TH__){ bool to_trace_or_not_to = trace_parser_env(this,COND_STK_TRACE); if(to_trace_or_not_to == YES){ @; yacco2::lrclog << "\tYACCO2_TH__::" << thread_no__ << "::|||re-aligned token stream la boundry POS: " << current_token_pos__ << " la token: " << current_token__->id__ << FILE_LINE<< std::endl; yacco2::lrclog << "\tYACCO2_TH__::" << thread_no__ << "::GPS RE-ALIGN FILE: "; EXTERNAL_GPSing(current_token__) yacco2::lrclog << " GPS RE-ALIGN LINE: " << current_token__->tok_co_ords__.line_no__ << " GPS RE-ALIGN CHR POS: " << current_token__->tok_co_ords__.pos_in_line__ << FILE_LINE<< std::endl; @; } } @*3 |T_18| trace requesting grammar's received message from a thread. @= if(YACCO2_TH__){ if(no_requested_ths_to_run__ > 1){ bool to_trace_or_not_to = trace_parser_env(this,COND_STK_TRACE); if(to_trace_or_not_to == YES){ @; yacco2::lrclog << "YACCO2_TH__::" << thread_no__ << "::" << fsm_tbl__->id__ << "::" << "parallel parsing received message from id:" << from_thread__->thread_no__ << "::" << from_thread__->thread_name() << FILE_LINE<< std::endl; @; } } } @*3 |T_22| and |T_22a| trace returned thread accept info. @= if(YACCO2_TH__){ bool to_trace_or_not_to = trace_parser_env(this,COND_STK_TRACE); if(to_trace_or_not_to == YES){ if(current_token()!= 0){ @; yacco2::lrclog << "YACCO2_TH__::" << thread_no__ << "::"; yacco2::lrclog << fsm_tbl__->id__ << "::"; yacco2::lrclog << "accept-parallel-parse current token " << '"' << current_token()->id__ << '"' << " pos: " << current_token_pos__ << FILE_LINE<< std::endl; yacco2::lrclog << "YACCO2_TH__::" << " accept tok: " << pp_rsvp__.accept_token__->id__ << " tok pos: " << pp_rsvp__.accept_token_pos__ << " la tok: " << pp_rsvp__.la_token__->id__ << " la tok pos: " << pp_rsvp__.la_token_pos__ << FILE_LINE<< std::endl; yacco2::lrclog << " thru fsm-> parser*: " << fsm_tbl__->parser() << std::endl; yacco2::lrclog << "\tYACCO2_TH__::" << thread_no__ << "::GPS ACCEPT FILE: "; EXTERNAL_GPSing(pp_rsvp__.accept_token__) yacco2::lrclog << " GPS ACCEPT LINE: " << pp_rsvp__.accept_token__->tok_co_ords__.line_no__ << " GPS ACCEPT CHR POS: " << pp_rsvp__.accept_token__->tok_co_ords__.pos_in_line__ << FILE_LINE<< std::endl; yacco2::lrclog << "\tYACCO2_TH__::" << thread_no__ << "::GPS ACCEPT LA FILE: "; EXTERNAL_GPSing(pp_rsvp__.la_token__) yacco2::lrclog << " GPS ACCEPT LA LINE: " << pp_rsvp__.la_token__->tok_co_ords__.line_no__ << " GPS ACCEPT LA CHR POS: " << pp_rsvp__.la_token__->tok_co_ords__.pos_in_line__ << FILE_LINE<< std::endl; @; } } } @*3 |T_23| trace parallel parse current token when an error has occured. @= if(YACCO2_TH__){ bool to_trace_or_not_to = trace_parser_env(this,COND_STK_TRACE); if(to_trace_or_not_to == YES){ if(current_token()){ @; yacco2::lrclog << "YACCO2_TH__::" << thread_no__ << "::"; yacco2::lrclog << fsm_tbl__->id__ << "::"; yacco2::lrclog << "YACCO2_TH__::" << "#############parallel parse-error current token " << current_token()->id__ << " pos: " << current_token_pos__ << " enum id: " << current_token()->enumerated_id__ << FILE_LINE<< std::endl; yacco2::lrclog << "\tYACCO2_TH__::" << thread_no__ << "::GPS RESET FILE: "; EXTERNAL_GPSing(current_token()) yacco2::lrclog << " GPS RESET LINE: " << current_token()->tok_co_ords__.line_no__ << " GPS RESET CHR POS: " << current_token()->tok_co_ords__.pos_in_line__ << FILE_LINE<< std::endl; @; } } } @*3 |T_23| trace proc call parse current token when an error has occured. @= if(YACCO2_TH__){ bool to_trace_or_not_to = trace_parser_env(this,COND_STK_TRACE); if(to_trace_or_not_to == YES){ if(current_token()){ @; yacco2::lrclog << "YACCO2_TH__::" << thread_no__ << "::"; yacco2::lrclog << fsm_tbl__->id__ << "::"; yacco2::lrclog << "YACCO2_TH__::" << "#############parallel parse-error current token " << current_token()->id__ << " pos: " << current_token_pos__ << " enum id: " << current_token()->enumerated_id__ << FILE_LINE<< std::endl; yacco2::lrclog << "\tYACCO2_TH__::" << thread_no__ << "::GPS RESET FILE: "; EXTERNAL_GPSing(current_token()) yacco2::lrclog << " GPS RESET LINE: " << current_token()->tok_co_ords__.line_no__ << " GPS RESET CHR POS: " << current_token()->tok_co_ords__.pos_in_line__ << FILE_LINE<< std::endl; @; } } } @*3 |T_24| trace before parallel parse thread message count reduced. This allows one to see if threading mutexes etc are behaving. @= if(YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << thread_no__ << "::"; yacco2::lrclog << fsm_tbl__->id__ << "::"; yacco2::lrclog << " called thread reducing thread active count of caller thread " << pp_requesting_parallelism__->thread_no__ << "::" << pp_requesting_parallelism__->fsm_tbl__->id__ << " active thread count::" << pp_requesting_parallelism__->th_active_cnt__ << FILE_LINE<< std::endl; @; } @*3 |T_25| trace parallel parse current token when an error has occured. @= if(YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << thread_no__ << "::"; yacco2::lrclog << fsm_tbl__->id__ << "::"; yacco2::lrclog << " called thread after reducing thread active count of caller thread " << pp_requesting_parallelism__->thread_no__ << "::" << pp_requesting_parallelism__->fsm_tbl__->id__ << " active thread count::" << pp_requesting_parallelism__->th_active_cnt__ << FILE_LINE<< std::endl; @; } @*2 Message macros.\fbreak They trace the correspondence between various threads. Here are the thread relationships:\fbreak \ptindent{grammar calling its spawned threads} \ptindent{launched threads to the grammar requesting thread service} These macros are very verbous but it allows one to analyse whether messages have been dropped. Typically dropped messages come about when an event depends on a specific result and the order of execution within the threads can change the current terminal mapping such that executing produces possibly an aborted thread parse. For example when a terminal is fetched with dynamic symbol table evaluation taking place, depending on the sequence execution of the threads errant terminal delivery can occur. This is a critical region problem between the competing threads. To fix the problem, either eliminate the competition of threads between themselves by blending into one thread the competing grammatical sentences, or use a MUTEX to tame the eradic behavior. To control messaging back to the requesting grammar when all threads have finished processing, an activity thread count under the control of its MUTEX is referenced by each launched thread. The responsibility of who responds back to the grammar requesting parallelism when all threads are done be it success or failure, is left to the individual threads launched. When a thread finishes work, it goes into the critical region of the requesting grammar and decrements the active thread count. It also checks if the activity count is zero indicating that it is the last thread in the house to lock up so wake up the requesting grammar. @*3 |TT_1| trace thread waiting for message. @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << thread_no__ << "::" << thread_name() << " -->WAIT_FOR_EVENT " << " # threads to run:: " << no_requested_ths_to_run__ << " # active threads: " << th_active_cnt__ << " # competing threads: " << no_competing_pp_ths__ << FILE_LINE<< std::endl; @; } @*3 |TT_2| trace message received.\fbreak Protect against procedure call that has wound down and destroyed itself before the calling grammar can trace it. Only trace returned call from threads. @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << thread_no__ << "::" << thread_name() << " MESSAGE RECEIVED from " << from_thread__->thread_no__ << "::" << from_thread__->thread_name() << FILE_LINE<< std::endl; @; } @*3 |TT_4| trace posting from - to thread info. @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << From_thread.thread_no__ << "::" << From_thread.thread_name() << " -----> Posting message to: " << To_thread.thread_no__ << "::" << To_thread.thread_name() << FILE_LINE<< std::endl; @; } @*3 |TT_4a| trace signaled grammar to wakeup. @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << From_thread.thread_no__ << "::" << From_thread.thread_name() << " -----> before SIGNAL_COND_VAR() to signal wakeup grammar for: " << To_thread.thread_no__ << "::" << To_thread.thread_name() << FILE_LINE<< std::endl; @; } @*3 |TT_4b| trace wakened grammar with its acquired mutex. @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << From_thread.thread_no__ << "::" << From_thread.thread_name() << " -----> after SIGNAL_COND_VAR() to waken grammar of " << To_thread.thread_no__ << "::" << To_thread.thread_name() << FILE_LINE<< std::endl; @; } @*3 |TT_4c| trace trying to acquire grammar's mutex. @= if(yacco2::YACCO2_MU_GRAMMAR__){ @; yacco2::lrclog << "YACCO2_MU_GRAMMAR__::" << parser.thread_no__ << "::" << parser.fsm_tbl__->id__ << "::" << " trying to acquire mutex" << Text << FILE_LINE<< std::endl; @; } @*3 |TT_4d| trace acquired grammar's mutex. @= if(yacco2::YACCO2_MU_GRAMMAR__){ @; yacco2::lrclog << "YACCO2_MU_GRAMMAR__::" << parser.thread_no__ << "::" << parser.fsm_tbl__->id__ << "::" << " acquired mutex" << Text << FILE_LINE<< std::endl; @; } @*3 |TT_4e| trace trying to release grammar's mutex. @= if(yacco2::YACCO2_MU_GRAMMAR__){ @; yacco2::lrclog << "YACCO2_MU_GRAMMAR__::" << parser.thread_no__ << "::" << parser.fsm_tbl__->id__ << "::" << " trying to release mutex" << Text << FILE_LINE<< std::endl; @; } @*3 |TT_4f| trace released grammar's mutex. @= if(yacco2::YACCO2_MU_GRAMMAR__){ @; yacco2::lrclog << "YACCO2_MU_GRAMMAR__::" << parser.thread_no__ << "::" << parser.fsm_tbl__->id__ << "::" << " released mutex" << Text << FILE_LINE<< std::endl; @; } @*3 |TT_5| trace start thread. @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << thread_no__ << "::" << fsm_tbl__->id__ << " --> start threads" << FILE_LINE<< std::endl; @; } @*3 |TT_6| trace of found thread in thread pool waiting to be run.\fbreak The pool of threads is dynmically built by thread requests. When a thread finishes work, instead of stopping, it goes into hibernation with an appropriate status indicating its availability. This is an optimization to speed up parallel processing. There can be many threads of the same name waiting for work due to recursion. @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << thread_no__ << "::--> parallel thread worker fnd in thread table CALL WORKER: " << tb->grammar_s_parser__->thread_name() << " thread obj*:" << tb->grammar_s_parser__ << " parm*: " << tb->grammar_s_parser__->pp_requesting_parallelism__ << FILE_LINE<< std::endl; @; } @*3 |TT_7| due to recursion trace no thread available in thread pool.\fbreak This comes about when a thread calls a thread who calls a previous thread. I call this situation ``nested parallelism''. The grammar of Pascal's railroad diagrams is an example of such situations. It is detected due to the thread (thread id number) already has an entry in the thread pool but there are no available threads ready to run so... launch another thread. @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << thread_no__ << "::" << pe->thread_fnct_name__ << " --> parallel thread fnd in thread table BUT ALL ARE BUSY " << FILE_LINE<< std::endl; @; } @*3 |TT_8| trace thread not found in global thread pool.\fbreak @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << thread_no__ << "::" << pe->thread_fnct_name__ << " --> parallel thread NOT fnd in thread table" << FILE_LINE<< std::endl; @; } @*3 Trace start thread by procedure call instead of threading. @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << thread_no__ << "::" << thread_name() << " calling PROC::" //|<< pe->thread_fnct_name__| << " --> before procedure call" << FILE_LINE<< std::endl; @; } @*3 Trace return from procedure call instead of threading. @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << thread_no__ << "::" << thread_name() << " returned from PROC::" //|<< pe->thread_fnct_name__| << " result: " << rslt << FILE_LINE<< std::endl; @; } @*3 Trace thread idle before setting waiting for work. @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << this->grammar_s_parser__->thread_no__ << "::" << this->grammar_s_parser__->thread_name() << " th_blk*: " << this << "this pp*: " << this->grammar_s_parser__ << "pp*: " << grammar_s_parser__ << "pp^th blk*: " << &grammar_s_parser__->th_blk__ << " #: " << thd_id__ << " st: " << status__ << " before setting waiting for work" << ' ' << grammar_s_parser__->thread_no__ << "::" << grammar_s_parser__->fsm_tbl__->id__ << FILE_LINE<< std::endl; @; } @*3 Trace thread idle after setting waiting for work. @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << this->grammar_s_parser__->thread_no__ << "::" << this->grammar_s_parser__->thread_name() << " th_blk*: " << this << "this pp*: " << this->grammar_s_parser__ << "pp*: " << grammar_s_parser__ << "pp^th blk*: " << &grammar_s_parser__->th_blk__ << " #: " << thd_id__ << " st: " << status__ << " after setting waiting for work " << grammar_s_parser__->thread_no__ << "::" << grammar_s_parser__->fsm_tbl__->id__ << FILE_LINE<< std::endl; @; } @*3 Trace thread being created. @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << this->grammar_s_parser__->thread_no__ << "::" << this->grammar_s_parser__->thread_name() << " th_blk*: " << this << " pp this: " << this->grammar_s_parser__ << " this^pp^th_blk: " << &this->grammar_s_parser__->th_blk__ << "pp*: " << grammar_s_parser__ << "pp^th blk*: " << &grammar_s_parser__->th_blk__ << " #: " << thd_id__ << " thread created " << grammar_s_parser__->thread_no__ << "::" << grammar_s_parser__->thread_name() << " of grammar: " << grammar_s_parser__->fsm_tbl__->id__ << FILE_LINE<< std::endl; @; } @*3 Trace threads in launched list. @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << tb->grammar_s_parser__->thread_no__ << "::" << tb->grammar_s_parser__->thread_name() << " th_blk*: " << this << " th_blk*: " << tb << " grammar parser: " << tb->grammar_s_parser__ << " #: " << tb->thd_id__ << " st: " << tb->status__ << " thds in launched list " << FILE_LINE<< std::endl; yacco2::lrclog << "------->" << tb->grammar_s_parser__->thread_no__ << "::" << tb->grammar_s_parser__->fsm_tbl__->id__ << FILE_LINE<< std::endl; @; } @*3 Trace thread to be launched. @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << "pe*: " << pe << " thread name: " << pe->thread_fnct_name__ << " thread proc*: " << pe->thread_fnct_ptr__ << " thread id: " << pe->thd_id__ << FILE_LINE<< std::endl; @; } @*3 All threads reported back.\fbreak @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << thread_no__ << "::" << thread_name() << " all threads reported back " << " Caller parser::" << pp_requesting_parallelism__->thread_no__ << "::" << pp_requesting_parallelism__->thread_name() << " # competing thds: " << pp_requesting_parallelism__->no_requested_ths_to_run__ << " # active thds: " << pp_requesting_parallelism__->th_active_cnt__ << FILE_LINE<< std::endl; @; } @*3 NOT all threads reported back.\fbreak @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << thread_no__ << "::" << thread_name() << " NOT all threads reported back " << " Caller parser::" << pp_requesting_parallelism__->thread_no__ << "::" << pp_requesting_parallelism__->thread_name() << " # competing thds: " << pp_requesting_parallelism__->no_requested_ths_to_run__ << " # active thds: " << pp_requesting_parallelism__->th_active_cnt__ << FILE_LINE<< std::endl; @; } @*3 Call procedure but in use.\fbreak @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << thread_no__ << "::" << thread_name() << " PROC CALL ALREADY IN USE so call its thread " << " Caller parser::" << pp_requesting_parallelism__->thread_no__ << "::" << pp_requesting_parallelism__->thread_name() << FILE_LINE<< std::endl; @; } @** Arbitrator macros.\fbreak These are the syntax directed code directives within a grammar's rules that arbitrate between the returned results of that finite state's configuration. They are gened as individual procedures per finite state configuration due to parallelism. To refine this family of message traces, they test whether their grammar has the debug switch turned on. @*2 |TAR_1| trace the starting of arbitration. @= @; @ @= if(yacco2::YACCO2_AR__){ //|trace_parser_env(Caller_pp,FORCE_STK_TRACE);| @; yacco2::lrclog << "YACCO2_AR__::" << Caller_pp->thread_no__ << "::" << ar_name << " start arbitrating" << FILE_LINE<< std::endl; yacco2::lrclog << "YACCO2_AR__::" << "number of accept tokens: " << Caller_pp->th_accepting_cnt__ << FILE_LINE<< std::endl; int ii = 1; for(;ii<=Caller_pp->th_accepting_cnt__;++ii){ yacco2::lrclog<< "YACCO2_AR__::" <<"\t terminal in accept queue: " <pp_accept_queue__[ii].accept_token__->id__ <<" token pos: " <pp_accept_queue__[ii].accept_token_pos__ << FILE_LINE<; } @*2 |TAR_2| trace no arbitration required.\fbreak This occurs when only 1 accept terminal is in the accept queue @= @; @ @= if(yacco2::YACCO2_AR__){ //|trace_parser_env(Caller_pp,FORCE_STK_TRACE);| @; yacco2::lrclog << "YACCO2_AR__::" << Caller_pp->thread_no__ << "::" << ar_name << " No Arbitration required" << FILE_LINE<< std::endl; yacco2::lrclog << "YACCO2_AR__::" << "number of accept tokens: " << Caller_pp->th_accepting_cnt__ << FILE_LINE<< std::endl; int ii = 1; for(;ii <= Caller_pp->th_accepting_cnt__;++ii){ yacco2::lrclog<<"\t YACCO2_AR__:: terminal in accept queue: " << Caller_pp->pp_accept_queue__[ii].accept_token__->id__ <<" token pos: " <pp_accept_queue__[ii].accept_token_pos__ << FILE_LINE<; } @*2 |TAR_3| trace stopped arbitrating.\fbreak This occurs when only 1 accept terminal is in the accept queue @= if(yacco2::YACCO2_AR__){ //|bool to_trace_or_no_to = trace_parser_env(Caller_pp,FORCE_STK_TRACE);| @; yacco2::lrclog << "YACCO2_AR__::" << Caller_pp->thread_no__ << "::" << ar_name << " stop arbitrating" << FILE_LINE<< std::endl; @; } @** TLEX macros --- roll-your-own tracing macros.\fbreak These are ``roll your own'' macros for when the going get rough and tough, and you don't have a bloody clue. At least you can leave some tracks of your own originality. Good luck and this is said with sincerity as I probably needed them once. The grammar writer can put them inside the grammar's syntax directed code directives. They basically give the parallel details on the thread, critical region etc. The passed in parameter is what the grammar writer wants to display. Basic, crude but may be helpful. Before going this route though, the other macro traces should be adequate. Other forms of tracings using |yacco2::lrclog| or |cout| are rudimentary but also effective. @+= #define sstrace_parallel_supportss(ssPROC_NAME) \ if(yacco2::YACCO2_TLEX__){\ Parser* _ap = parser_of_parallel_support(); \ yacco2::lrclog << "YACCO2_TLEX__::" << pthread_self() << "::" \ << _ap->fsm_tbl__->id__ << "::" \ << ' ' << #ssPROC_NAME << " this:: " << this << std::endl; \ yacco2::lrclog << "\tYACCO2_TLEX__:: parser_of_parallel_support:: " \ << _ap \ << FILE_LINE<< std::endl; \ yacco2::lrclog << "\tself thread id:: " << thread_no__\ << FILE_LINE<< std::endl; \ yacco2::lrclog \ << "\tYACCO2_TLEX__:: embedded thread id:: " \ << embedded_thread_no()\ << FILE_LINE<< std::endl;\ } @*2 Print interplay between requesting grammar and launched thread. A roll your own descriptor is passed to the macro. @+= #define sstrace_parallel_support_envss(ssPROC_NAME) \ if(yacco2::YACCO2_TLEX__){\ yacco2::lrclog << "YACCO2_TLEX__::" << GetCurrentThreadid__ << "::" \ << fsm_tbl__->id__ << "::" \ << ' ' << #ssPROC_NAME << " this:: " << this \ << FILE_LINE<< std::endl; \ yacco2::lrclog << "\tYACCO2_TLEX__:: self thread id:: "\ << thread_no__ \ << FILE_LINE<< std::endl;\ } @*2 |trace_parser_env| traces the parsing stack.\fbreak It check whether the thread has its debug switch on. If it does, it does its own thing. It returns the thread's debug grammar switch for other trace macros to test whether they should do their trace dance. @^ To do - parsing stack dump. canonize output trace!@> @+= extern bool trace_parser_env(Parser* parser, bool Trace_type); @ Print parse stack prefix. @= @; for(UINT x=1;x<=parser->parse_stack__.top_sub__;++x) yacco2::lrclog << "."; yacco2::lrclog << parser->thread_no__; yacco2::lrclog << "::"; yacco2::lrclog << parser->fsm_tbl__->id__ << "::"; @; @*3 Print items on parse stack in FILO order. @= @; Cparse_record* i = parser->parse_stack__.first_sf__; Cparse_record* ie = parser->parse_stack__.top__; for(int xxx(1);i != ie;i=parser->parse_stack__.sf_by_sub(++xxx)){ yacco2::lrclog << i->state__->state_no__ << "--"; CAbs_lr1_sym* sym = i->symbol__; if(sym) yacco2::lrclog << sym->id__ << "-> "; else yacco2::lrclog << "ZEROED OUT SYMBOL" << "-> "; } yacco2::lrclog << ie->state__->state_no__; yacco2::lrclog << FILE_LINE<< std::endl; @; @*3 Should grammar be traced?.\fbreak The debug switch supplied by the grammar is checked. If it's turned on then allow tracing. This check lowers the volume outputted. It's a spot check on `what the hell is going wrong' with my grammar. @= if(Trace_type == COND_STK_TRACE){ if (parser->fsm_tbl__->debug__ == OFF) return NO; } @*2 |trace_parser_env| implementation.\fbreak There are 2 contexts that stack tracing can take place:\fbreak \ptindent{1) within the grammar controlled by YACCO2\_TH\_\_ trace variable} \ptindent{2) forced stack trace used by other trace variables} @= extern bool yacco2::trace_parser_env(Parser* parser,bool Trace_type){ @; @; @; @; @; return YES; } @*2 Trace pp start info.\fbreak This is the tabloid giving all the gory details about the parallel thread, its requesting grammar, and the starting token stream to-be-parsed. @= if(yacco2::YACCO2_MSG__){ @; sprintf(ma,pp_start,pp_parser.thread_no__,pp_thread_entry.thread_fnct_name__); yacco2::lrclog << ma; Parser* pp_ = pp_parser.pp_requesting_parallelism__; yacco2::lrclog << "YACCO2_MSG__::" << pp_parser.thread_no__ << "::" << pp_parser.thread_name() << " requesting parser*: " << pp_ << FILE_LINE<< std::endl; yacco2::lrclog << "\tYACCO2_MSG__::" << pp_parser.thread_no__ << "::" << pp_parser.thread_name() << " Caller's # threads to run:: " << pp_->no_requested_ths_to_run__ << " Caller's # active threads: " << pp_->th_active_cnt__ << " Self # competing threads: " << pp_parser.no_competing_pp_ths__ << FILE_LINE<< std::endl; yacco2::lrclog << "\tYACCO2_MSG__::" << pp_parser.thread_no__ << "::" << pp_parser.thread_name() << " passed token*: " << pp_->current_token() << '"' << pp_parser.current_token()->id__ << '"' << " pos: " << pp_parser.current_token_pos__ << FILE_LINE<< std::endl; yacco2::lrclog << "\t\t::GPS FILE: "; EXTERNAL_GPSing(pp_parser.current_token__) yacco2::lrclog << " GPS LINE: " << pp_parser.current_token__->tok_co_ords__.line_no__ << " GPS CHR POS: " << pp_parser.current_token__->tok_co_ords__.pos_in_line__ << FILE_LINE<< std::endl; @; } if(yacco2::YACCO2_T__){ @; yacco2::lrclog << "YACCO2_T__::" << pp_parser.thread_no__ << "::" << pp_parser.thread_name() << " token*: " << pp_parser.current_token__ << " enum: " << pp_parser.current_token__->enumerated_id__ << " pos: " << pp_parser.current_token_pos__ << ' ' << '"' << pp_parser.current_token__->id__ << '"' << FILE_LINE<< std::endl; yacco2::lrclog << "\t\t::GPS FILE: "; EXTERNAL_GPSing(pp_parser.current_token__) yacco2::lrclog << " GPS LINE: " << pp_parser.current_token__->tok_co_ords__.line_no__ << " GPS CHR POS: " << pp_parser.current_token__->tok_co_ords__.pos_in_line__ << FILE_LINE<< std::endl; yacco2::lrclog << "\tGPS LINE: " << pp_parser.current_token()->tok_co_ords__.line_no__ << " GPS CHR POS: " << pp_parser.current_token()->tok_co_ords__.pos_in_line__ << FILE_LINE<< std::endl; @; } @*2 Trace procedure pp start info.\fbreak This is the tabloid giving all the gory details about the parallel thread, its requesting grammar, and the starting token stream to-be-parsed. @= if(yacco2::YACCO2_MSG__){ @; sprintf(ma,pp_start,proc_parser->thread_no__,called_proc_name); yacco2::lrclog << ma; Parser* pp_ = proc_parser->pp_requesting_parallelism__; yacco2::lrclog << "YACCO2_MSG__::" << proc_parser->thread_no__ << "::" << proc_parser->thread_name() << " requesting parser*: " << pp_ << FILE_LINE<< std::endl; yacco2::lrclog << "\tYACCO2_MSG__::PROC::" << proc_parser->thread_no__ << "::" << proc_parser->thread_name() << " Caller's # threads to run:: " << pp_->no_requested_ths_to_run__ << " Caller's # active threads: " << pp_->th_active_cnt__ << " Self # competing threads: " << proc_parser->no_competing_pp_ths__ << FILE_LINE<< std::endl; yacco2::lrclog << "\tYACCO2_MSG__::PROC::" << proc_parser->thread_no__ << "::" << proc_parser->thread_name() << " passed token*: " << pp_->current_token() << '"' << proc_parser->current_token()->id__ << '"' << " pos: " << proc_parser->current_token_pos__ << FILE_LINE<< std::endl; yacco2::lrclog << "\t\t::GPS FILE: "; EXTERNAL_GPSing(proc_parser->current_token__) yacco2::lrclog << " GPS LINE: " << proc_parser->current_token__->tok_co_ords__.line_no__ << " GPS CHR POS: " << proc_parser->current_token__->tok_co_ords__.pos_in_line__ << FILE_LINE<< std::endl; @; } if(yacco2::YACCO2_T__){ @; yacco2::lrclog << "YACCO2_T__::" << proc_parser->thread_no__ << "::" << proc_parser->thread_name() << " token*: " << proc_parser->current_token__ << " enum: " << proc_parser->current_token__->enumerated_id__ << " pos: " << proc_parser->current_token_pos__ << ' ' << '"' << proc_parser->current_token__->id__ << '"' << FILE_LINE<< std::endl; yacco2::lrclog << "\t\t::GPS FILE: "; EXTERNAL_GPSing(proc_parser->current_token__) yacco2::lrclog << " GPS LINE: " << proc_parser->current_token__->tok_co_ords__.line_no__ << " GPS CHR POS: " << proc_parser->current_token__->tok_co_ords__.pos_in_line__ << FILE_LINE<< std::endl; @; } @*2 Trace stop of parallel parse message. @= if(yacco2::YACCO2_MSG__){ @; sprintf(ma,pp_stop,pp_parser.thread_no__,pp_thread_entry.thread_fnct_name__); yacco2::lrclog << ma; @; } @*2 Trace pp's last symbol on stack set as autodelete. @= if(yacco2::YACCO2_TH__){ THREAD_NO tid = pp_parser.thread_no__; @; yacco2::lrclog << "YACCO2_TH__:: " << "sym to be deleted: " << tid << "::" << pp_parser.fsm_tbl__->id__ << "::" << sym->id__ << FILE_LINE<< std::endl; @; } @*2 Trace procedure pp's last symbol on stack set as autodelete. @= if(yacco2::YACCO2_TH__){ THREAD_NO tid = proc_parser->thread_no__; @; yacco2::lrclog << "YACCO2_TH__:: " << "sym to be deleted: " << tid << "::" << proc_parser->fsm_tbl__->id__ << "::" << sym->id__ << FILE_LINE<< std::endl; @; } @*2 Trace parallel thread waiting-to-do-work. @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << pp_parser.thread_no__ << "::" << pp_thread_entry.thread_fnct_name__ << " ==>PP waiting for work: " << FILE_LINE<< std::endl; @; } @*2 Trace pp received go start working message. @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << pp_parser.thread_no__ << "::" << pp_thread_entry.thread_fnct_name__ << " ==>PP go process work: " << FILE_LINE<< std::endl; @; } @*2 Trace pp finished working. @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::" << pp_parser.thread_no__ << "::" << pp_thread_entry.thread_fnct_name__ << " ==>PP finished working" << FILE_LINE<< std::endl; @; } @*2 Trace procedure pp finished working. @= if(yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_MSG__::PROC::" << proc_parser->thread_no__ << "::" << called_proc_name << " ==>procedure finished working" << FILE_LINE<< std::endl; @; } @*2 Trace raw characters. @= if(yacco2::YACCO2_TLEX__){ @; yacco2::lrclog << "YACCO2_TLEX__:: " << "chr: " << Char << " File: " << File_no << " Pos: " << Pos << FILE_LINE<< std::endl; @; } @** Thread performance macros.\fbreak They allow one to see how the thread library stops and starts the threads by their output. @*2 Entered into waiting for an event. @= if(yacco2::YACCO2_THP__ || yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_THP__ || yacco2::YACCO2_MSG__::" << parser.thread_no__ << "::" << parser.thread_name() << " COND_WAIT entered into Wait on event " << FILE_LINE<< std::endl; @; } @*2 Exit out of waiting for an event. @= if(yacco2::YACCO2_THP__ || yacco2::YACCO2_MSG__){ @; yacco2::lrclog << "YACCO2_THP__ || yacco2::YACCO2_MSG__::" << parser.thread_no__ << "::" << parser.thread_name() << " COND_WAIT exit on event " <<" cv_cond: "<< parser.cv_cond__ << " no competing thds: " << parser.no_competing_pp_ths__ <<" no active thds: " << parser.from_thread__->th_active_cnt__ << " from: " << parser.from_thread__->thread_no__ << "::" << parser.from_thread__->thread_name() << FILE_LINE<< std::endl; @; } @*2 Before |SIGNAL_COND_VAR|. @= clock_t start_; if(yacco2::YACCO2_THP__ || yacco2::YACCO2_MSG__){ start_ = clock(); @; yacco2::lrclog << "YACCO2_THP__ || yacco2::YACCO2_MSG__::" << parser.thread_no__ << "::" << parser.thread_name() << " to signal SIGNAL_COND_VAR: " << To_thread.thread_no__ << "::" << To_thread.thread_name() << FILE_LINE<< std::endl; @; } @*2 After |SIGNAL_COND_VAR|. @= if(yacco2::YACCO2_THP__ || yacco2::YACCO2_MSG__){ @; clock_t stop_ = clock(); yacco2::lrclog << "YACCO2_THP__ || yacco2::YACCO2_MSG__::" << parser.thread_no__ << "::" << parser.thread_name() << " after SIGNAL_COND_VAR : " << stop_ - start_ << " to: "<< To_thread.thread_no__ << "::" << To_thread.thread_name() << FILE_LINE<< std::endl; @; } @*2 Before |CREATE_THREAD|. @= clock_t start_ = clock(); if(yacco2::YACCO2_THP__){ @; yacco2::lrclog << "YACCO2_THP__:: " << Parser_requesting_parallelism.thread_no__ << "::" << Parser_requesting_parallelism.thread_name() << " before CREATE_THREAD" << FILE_LINE<< std::endl; @; } @*2 After |CREATE_THREAD|. @= if(yacco2::YACCO2_THP__){ @; clock_t stop_ = clock(); yacco2::lrclog << "YACCO2_THP__:: " << Parser_requesting_parallelism.thread_no__ << "::" << Parser_requesting_parallelism.thread_name() << " after CREATE_THREAD: " << stop_ - start_ << FILE_LINE<< std::endl; @; }