Re: Suspend the parser
Cheng-Chang Wu <chengchangwu-/[email protected]>
| Newsgroups | gmane.comp.lang.eiffel.gobo.general |
|---|---|
| Message-ID | <[email protected]> |
Attached files are removed in last email? Here are they again. --- Cheng-Chang Wu <chengchangwu-/[email protected]> wrote: > For my application the proccess must jump out from > the > parser and jump in later. I've written a feature > 'suspend' to save the local variables of feature > 'parse', and redefined feature 'parse' so when it is > called next time, it can resume its job. > > I am not sure if I've done it right. Maybe someone > have interest to look in the two attached classes. > class CNC_PARSER_SKELETON inherit YY_NEW_PARSER_SKELETON redefine parse end feature -- Status report is_suspended: BOOLEAN is do Result := yy_parsing_status = yySuspended end feature {YY_PARSER_ACTION} -- Element change suspend is -- Suspend parsing. do yy_parsing_status := yySuspended ensure suspended: is_suspended end feature -- Parsing parse is -- Parse input stream. -- Set `syntax_error' to True if -- parsing has not been successful. local yystacksize: INTEGER yystate: INTEGER yyn: INTEGER yychar1: INTEGER index, yyss_top: INTEGER yy_goto: INTEGER do -- This routine is implemented with a loop whose body -- is a big inspect instruction. This is a mere -- translation of C gotos into Eiffel. Needless to -- say that I'm not very proud of this piece of code. -- However I performed some benchmarks and the results -- were that this implementation runs amazingly faster -- than an alternative implementation with no loop nor -- inspect instructions and where every branch of the -- old inspect instruction was written in a separate -- routine. I think that the performance penalty is due -- to the routine call overhead and the depth of the call -- stack. Anyway, I prefer to provide you with a big and -- ugly but fast parsing routine rather than a nice and -- slow version. I hope you won't blame me for that! :-) from if yy_parsing_status = yySuspended then yystacksize := suspended_state.yystacksize yystate := suspended_state.yystate yyn := suspended_state.yyn yychar1 := suspended_state.yychar1 index := suspended_state.index yyss_top := suspended_state.yyss_top yy_goto := suspended_state.yy_goto yy_parsing_status := yyContinue else error_count := 0 yy_lookahead_needed := True yyerrstatus := 0 yy_init_value_stacks yyssp := -1 yystacksize := yyss.count yy_parsing_status := yyContinue yy_goto := yyNewstate end until yy_parsing_status /= yyContinue loop inspect yy_goto when yyNewstate then yyssp := yyssp + 1 if yyssp >= yystacksize then yystacksize := yystacksize + yyInitial_stack_size yyss := FIXED_INTEGER_ARRAY_.resize (yyss, yystacksize) debug ("GEYACC") std.error.put_string ("Stack (yyss) size increased to ") std.error.put_integer (yystacksize) std.error.put_character ('%N') end end debug ("GEYACC") std.error.put_string ("Entering state ") std.error.put_integer (yystate) std.error.put_character ('%N') end yyss.put (yystate, yyssp) -- Do appropriate processing given the current state. -- Read a lookahead token if one is needed. yyn := yypact.item (yystate) -- First try to decide what to do without reference -- lookahead token. if yyn = yyFlag then yy_goto := yyDefault else -- Not known => get a lookahead token if don't -- already have one. if yy_lookahead_needed then debug ("GEYACC") std.error.put_string ("Reading a token%N") end read_token yy_lookahead_needed := False end -- Convert token to internal form (in `yychar1') -- for indexing tables. if last_token > yyEof then debug ("GEYACC") std.error.put_string ("Next token is ") std.error.put_integer (last_token) std.error.put_character ('%N') end -- Translate lexical token `last_token' into -- geyacc internal token code. if last_token <= yyMax_token then yychar1 := yytranslate.item (last_token) else yychar1 := yyNsyms end yyn := yyn + yychar1 elseif last_token = yyEof then -- This means end of input. debug ("GEYACC") std.error.put_string ("Now at end of input.%N") end yychar1 := 0 else -- An error occurred in the scanner. debug ("GEYACC") std.error.put_string ("Error in scanner.%N") end error_count := error_count + 1 yy_do_error_action (yystate) abort -- Skip next conditional instruction: yyn := -1 end if (yyn < 0 or yyn > yyLast) or else yycheck.item (yyn) /= yychar1 then yy_goto := yyDefault else yyn := yytable.item (yyn) -- `yyn' is what to do for this token type in -- this state: -- Negative => reduce, -`yyn' is rule number. -- Positive => shift, `yyn' is new state. -- New state is final state => don't bother to -- shift, just return success. -- 0, or most negative number => error. if yyn < 0 then if yyn = yyFlag then yy_goto := yyErrlab else yyn := -yyn yy_goto := yyReduce end elseif yyn = 0 then yy_goto := yyErrlab elseif yyn = yyFinal then accept else -- Shift the lookahead token. debug ("GEYACC") std.error.put_string ("Shifting token ") std.error.put_integer (last_token) std.error.put_character ('%N') end -- Discard the token being shifted -- unless it is eof. if last_token > yyEof then yy_lookahead_needed := True end yy_push_last_value (yychar1) -- Count tokens shifted since error; -- after three, turn off error status. if yyerrstatus /= 0 then yyerrstatus := yyerrstatus - 1 end yystate := yyn check newstate: yy_goto = yyNewstate end end end end when yyDefault then -- Do the default action for the current state. yyn := yydefact.item (yystate) if yyn = 0 then yy_goto := yyErrlab else yy_goto := yyReduce end when yyReduce then -- Do a reduction. `yyn' is the number of a rule -- to reduce with. debug ("GEYACC") std.error.put_string ("Reducing via rule #") std.error.put_integer (yyn) std.error.put_character ('%N') end yy_do_action (yyn) if yy_parsing_status = yyContinue then -- Now "shift" the result of the reduction. -- Determine what state that goes to, -- based on the state we popped back to -- and the rule number reduced by. yyn := yyr1.item (yyn) yyss_top := yyss.item (yyssp) index := yyn - yyNtbase yystate := yypgoto.item (index) + yyss_top if (yystate >= 0 and yystate <= yyLast) and then yycheck.item (yystate) = yyss_top then yystate := yytable.item (yystate) else yystate := yydefgoto.item (index) end yy_goto := yyNewstate elseif yy_parsing_status = yySuspended then if suspended_state = Void then create suspended_state.make end suspended_state.set_yystacksize (yystacksize) suspended_state.set_yystate (yystate) suspended_state.set_yyn (yyn) suspended_state.set_yychar1 (yychar1) suspended_state.set_index (index) suspended_state.set_yyss_top (yyss_top) suspended_state.set_yy_goto (yy_goto) elseif yy_parsing_status = yyError_raised then -- Handle error raised explicitly by an action. yy_parsing_status := yyContinue yy_goto := yyErrlab -- else -- Accepted or aborted. end when yyErrlab then -- Detect error. if yyerrstatus = 3 then -- If just tried and failed to reuse lookahead -- token after an error, discard it. Return -- failure if at end of input. if last_token <= yyEof then abort else debug ("GEYACC") std.error.put_string ("Discarding token ") std.error.put_integer (last_token) std.error.put_character ('%N') end yy_lookahead_needed := True yy_goto := yyErrhandle end else if yyerrstatus = 0 then -- If not already recovering from an error, -- report this error. error_count := error_count + 1 yy_do_error_action (yystate) end yyerrstatus := 3 yy_goto := yyErrhandle end when yyErrhandle then -- Handle error. yyn := yypact.item (yystate) if yyn = yyFlag then yy_goto := yyErrpop else yyn := yyn + yyTerror if (yyn < 0 or yyn > yyLast) or else yycheck.item (yyn) /= yyTerror then yy_goto := yyErrpop else yyn := yytable.item (yyn) if yyn < 0 then if yyn = yyFlag then yy_goto := yyErrpop else yyn := -yyn yy_goto := yyReduce end elseif yyn = 0 then yy_goto := yyErrpop elseif yyn = yyFinal then accept else yy_push_error_value yystate := yyn yy_goto := yyNewstate end end end when yyErrpop then -- Pop the current state because it cannot handle -- the error token. if yyssp = 0 then abort else yy_pop_last_value (yystate) yyssp := yyssp - 1 yystate := yyss.item (yyssp) yy_goto := yyErrhandle end end end if yy_parsing_status /= yySuspended then yy_clear_all end rescue debug ("GEYACC") std.error.put_line ("Entering rescue clause of parser") end abort yy_clear_all end feature {NONE} -- Constants yySuspended: INTEGER is unique feature {NONE} -- Suspended state suspended_state: CNC_PARSER_SUSPENDED_STATE end class CNC_PARSER_SUSPENDED_STATE create {CNC_PARSER_SKELETON} make feature {NONE} -- Initialization make is do end feature {CNC_PARSER_SKELETON} -- Access yystacksize: INTEGER yystate: INTEGER yyn: INTEGER yychar1: INTEGER index: INTEGER yyss_top: INTEGER yy_goto: INTEGER feature {CNC_PARSER_SKELETON} -- Setting set_yystacksize (v: INTEGER) is do yystacksize := v ensure yystacksize_set: yystacksize = v end set_yystate (v: INTEGER) is do yystate := v ensure yystate_set: yystate = v end set_yyn (v: INTEGER) is do yyn := v ensure yyn_set: yyn = v end set_yychar1 (v: INTEGER) is do yychar1 := v ensure yychar1_set: yychar1 = v end set_index (v: INTEGER) is do index := v ensure index_set: index = v end set_yyss_top (v: INTEGER) is do yyss_top := v ensure yyss_top_set: yyss_top = v end set_yy_goto (v: INTEGER) is do yy_goto := v ensure yy_goto_set: yy_goto = v end end __________________________________ Start your day with Yahoo! - Make it your home page! http://www.yahoo.com/r/hs ------------------------ Yahoo! Groups Sponsor --------------------~--> Get Bzzzy! (real tools to help you find a job). Welcome to the Sweet Life. http://us.click.yahoo.com/A77XvD/vlQLAA/TtwFAA/saFolB/TM --------------------------------------------------------------------~-> To Post a message, send it to: [email protected] To Unsubscribe, send a blank message to: [email protected] Yahoo! Groups Links <*> To visit your group on the web, go to: http://groups.yahoo.com/group/gobo-eiffel/ <*> To unsubscribe from this group, send an email to: [email protected] <*> Your use of Yahoo! Groups is subject to: http://docs.yahoo.com/info/terms/