/******************************************************************************/ #include "stdafx.h" namespace EE{ namespace Edit{ /******************************************************************************/ // WRITE COMMANDS /******************************************************************************/ static Str TextTokens(Memc &tokens, Int from, Int to) { Str text; TOKEN_TYPE last_type=TOKEN_NONE; for(Int i=from; i<=to; i++) { Token &token=*tokens[i]; if(MustSeparate(last_type, token.type))text+=' '; text+=token; last_type=token.type; } return text; } /****************************************************************************** static void ListCommands(FileText &ft, Memc &cmds, Memc &tokens) { FREPA(cmds) { Str line; Command &cmd=cmds[i]; switch( cmd.type) { case CMD_INSTRUCT : line=S+ TextTokens(tokens, cmd. raw_range.x, cmd. raw_range.y)+";"; break; case CMD_IF : line=S+"if(" +TextTokens(tokens, cmd.cond_range.x, cmd.cond_range.y)+")"; break; case CMD_FOR : line=S+"for(" +TextTokens(tokens, cmd.init_range.x, cmd.init_range.y)+"; "+TextTokens(tokens, cmd.cond_range.x, cmd.cond_range.y)+"; "+TextTokens(tokens, cmd.step_range.x, cmd.step_range.y)+")"; break; case CMD_WHILE : line=S+"while(" +TextTokens(tokens, cmd.cond_range.x, cmd.cond_range.y)+")"; break; case CMD_DO : line= "do" ; break; case CMD_SWITCH : line=S+"switch("+TextTokens(tokens, cmd. raw_range.x, cmd. raw_range.y)+")"; break; case CMD_RETURN : line=S+"return "+TextTokens(tokens, cmd. raw_range.x, cmd. raw_range.y)+";"; break; case CMD_BREAK : line=S+"break;" ; break; case CMD_CONTINUE : line=S+"continue;" ; break; case CMD_GOTO : line=S+"goto " +TextTokens(tokens, cmd. raw_range.x, cmd. raw_range.y)+";"; break; case CMD_GOTO_COND : line=S+"if(" +TextTokens(tokens, cmd.cond_range.x, cmd.cond_range.y)+")goto @"+cmd.label_index+";"; break; case CMD_GOTO_COND_N: line=S+"if(!" +TextTokens(tokens, cmd.cond_range.x, cmd.cond_range.y)+")goto @"+cmd.label_index+";"; break; case CMD_LABEL : line=S+"@" +cmd.label_index+":"; break; } if(line.is())ft.putLine(line); if(cmd.cmds.elms()) { ft++; ListCommands(ft, cmd.cmds, tokens); ft--; } if(cmd.cmds_false.elms()) { ft.putLine("else"); ft++; ListCommands(ft, cmd.cmds_false, tokens); ft--; } if(cmd.type==CMD_DO)ft.putLine(S+"while("+TextTokens(tokens, cmd.cond_range.x, cmd.cond_range.y)+");"); } } /****************************************************************************** static void ListFunction(FileText &ft, Symbol &func, Memc &cmds) { if(func.source) { ft.putLine(SEP_LINE); ft.putLine(func.definition()); ft++; ListCommands(ft, cmds, func.source->tokens); ft--; } } /******************************************************************************/ // READ COMMANDS /******************************************************************************/ static void ReadInstruction(Source &source, Int &token_index, Symbol &set_parent, Memc &cmds, Memc &msgs, CMD_TYPE type) // read until ; encountered (eat the ';'), if { or } then don't set its parents set error and return { Memc &tokens=source.tokens; for(Int start=token_index; token_index=start : true) // don't process empty instruction ";" when processing CMD_INSTRUCT { Command &cmd=cmds.New(); cmd.type=type; cmd.raw_range.set(start, end); } return; } } } /******************************************************************************/ static Bool ReadCommand(Source &source, Int &token_index, Symbol &set_parent, Memc &cmds, Memc &msgs) { Memc &tokens=source.tokens; if(InRange(token_index, tokens)) { Token &token=*tokens[token_index++]; token.parent=&set_parent; if(token.type==TOKEN_KEYWORD) { if(token=="if") // spaces will be: "if(cond_space)true_space;else false_space;", 'true_space' and 'false_space' are child of 'cond_space' { Command &cmd=cmds.New(); cmd.type=CMD_IF; if(InRange(token_index, tokens)) // check for "(condition)" after 'if' { Token &token=*tokens[token_index]; if(token!='(')msgs.New().error(S+"'if' should be followed by '(' : \"if(..)\", while encountered '"+token+"'", &token);else { token.parent=&set_parent; token_index++; // 'token_index' now points after '(' Symbol *cond_space=source.createSpace(set_parent, token_index); cmd._for.cond_range.x=token_index; Bool valid=false; for(Int round_level=0, bracket_level=0, semicolons=0; token_indexfull_name+SEP : S)+'@'+token).set(func, Symbol::LABEL, token_index-1, &source); if(token.symbol->valid>1)msgs.New().error("Label redefinition", &source, token_index-1); // name used more than once else func->children.add(token.symbol()); // add to children list Command &cmd=cmds.New(); cmd.type=CMD_LABEL; cmd.raw_range.set(token_index-1, token_index-1); // label: tokens[token_index++]->parent=&set_parent; return true; } ReadInstruction(source, --token_index, set_parent, cmds, msgs, CMD_INSTRUCT); return true; } return false; } /******************************************************************************/ void ReadCommands(Source &source, Int &token_index, Symbol &set_parent, Memc &cmds, Memc &msgs) { for(; ReadCommand(source, token_index, set_parent, cmds, msgs); ); } /******************************************************************************/ Int Command::startTokenIndex() { switch(type) { case CMD_INSTRUCT : return raw_range.x; case CMD_GROUP : return raw_range.x-1; case CMD_IF : return _for.cond_range.x-2; // 'if' , '(' case CMD_FOR : return _for.init_range.x-2; // 'for' , '(' case CMD_WHILE : return _for.cond_range.x-2; // 'while' , '(' case CMD_DO : return cmds.elms() ? cmds[0].startTokenIndex()-1 : _for.cond_range.x-3; // x ? 'do' : 'do', 'while', '(' case CMD_SWITCH : return raw_range.x-2; // 'switch', '(' case CMD_RETURN : return raw_range.x-1; // 'return' case CMD_BREAK : return raw_range.x-1; // 'break' case CMD_CONTINUE : return raw_range.x-1; // 'continue' case CMD_GOTO : return raw_range.x-1; // 'goto' case CMD_GOTO_COND : return _for.cond_range.x-2; // 'if' , '(' case CMD_GOTO_COND_N: return _for.cond_range.x-2; // 'if' , '(' case CMD_LABEL : return raw_range.x; } return -1; } /******************************************************************************/ }} /******************************************************************************/