%{ //OpenSCADA system module DAQ.JavaLikeCalc file: func_analise.ypp /*************************************************************************** * Copyright (C) 2005-2020 by Roman Savochenko, * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; version 2 of the License. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include "freefunc.h" #include "freelib.h" #include "virtual.h" #define YYERROR_VERBOSE true namespace JavaLikeCalc { struct YYLTYPE; int yylex( ); void yyerror( const char *s ); void sfErr( const string &mess, YYLTYPE *ps ); %} /************************* GRAMMAR ****************************/ %union { int id; //Function id Reg *reg; //Variable and Constant registers list index and function list index int fp_cnt; //Function parameters counter int prg_cd; //Program code char op[256]; //Object's properties, internal function } %token ERR VAR_DIR IF ELSE WHILE FOR IN BREAK CONTINUE ADDEQ SUBEQ MULEQ DIVEQ BITSHLEFT BITSHRIGHT RETURN NEW DELETE OBJECT ARRAY REGEXP %token FUNC INT_FUNC B_FUNC B_FUNC1 B_FUNC2 %token VAR CONST FUNC_R %token O_PRP_F FUNCTION %type var expr %type if if_expr OR_expr AND_expr end cycl fnc_in %type prmlst varlst %right '=' ADDEQ SUBEQ MULEQ DIVEQ %right '?' ':' %left OR AND %left '|' '&' '^' %left '>' '<' GE LE EQ NE %left BITSHLEFT BITSHRIGHT %left '+' '-' %left '*' '/' '%' %right UN_MINUS '!' '~' %right INCREM DECREM %% root: solver end | error { sfErr("",&yylloc); YYABORT; } solver: /*empty*/ | solver solve solve: assign ';' | var ';' { $1->free(); } | IF '(' expr ')' if solve end { try{ pF->cdCond($3,$5,$7,$7); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | IF '(' expr ')' if solve end ELSE solve end { try{ pF->cdCond($3,$5,$7,$10); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | WHILE cycl '(' expr end ')' solve end { try{ pF->cdCycle($2,$4,$5,$8,0); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | FOR '(' assign ';' cycl expr end ';' assign end ')' solve end { try{ pF->cdCycle($5,$6,$10,$13,$7); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | FOR '(' var IN cycl expr end ')' solve end { try{ pF->cdCycleObj($5,$6,$7,$10,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | FUNCTION '(' varlst ')' fnc_in solve end { if($5 > 65535) { sfErr(TSYS::strMess(_("Internal function inaccessible by offset %d > %d"),$5,65535), &@1); YYABORT; } uint16_t fSz = $7 - $5; pF->prg.replace($5+1, sizeof(fSz), (char*)&fSz, sizeof(fSz)); pF->inFuncDef($1, -1); } | BREAK ';' { pF->prg = pF->prg+(char)Reg::Break; } | CONTINUE ';' { pF->prg = pF->prg+(char)Reg::Continue; } | RETURN ';' { pF->prg += (char)Reg::EndFull; } | RETURN expr ';' { if(pF->mInFnc.size()) { struct SCode { uint8_t cod; uint16_t sz; uint8_t n; uint16_t rez; } __attribute__((packed)); const struct SCode *ptr = (const struct SCode *)(pF->prg.data()+pF->inFuncGet(pF->mInFnc)); pF->cdMove(pF->regAt(ptr->rez), $2); } else for(int i_io = 0; i_io < pF->ioSize(); i_io++) if(pF->io(i_io)->flg()&IO::Return) { Reg *rez = pF->regAt(pF->regGet(pF->io(i_io)->id())); if(!rez) { rez = pF->regAt(pF->regNew(true)); rez->setName(pF->io(i_io)->id()); rez->setVar(i_io); rez->setLock(true); } pF->cdAssign(rez, $2); break; } pF->prg += (char)Reg::EndFull; } | DELETE var ';' { pF->prg += (uint8_t)Reg::Delete; uint16_t addr = $2->pos(); pF->prg.append((char*)&addr, sizeof(uint16_t)); } | FUNC '(' prmlst ')' ';' { try{ pF->cdExtFnc($1,$3,true); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | FUNC_R '(' prmlst ')' ';' { try{ pF->cdExtFnc(-1,$3,true,$1); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | INT_FUNC '(' prmlst ')' ';' { try{ pF->cdIntFnc($1,$3,true); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | '{' solver '}' var: VAR { $$ = $1; } | VAR_DIR VAR { $2->setType(Reg::Real/*String*/); $$ = $2; } | VAR VAR { if($1->name() == "var") { $2->setType(Reg::Real/*String*/); $$ = $2; } else { sfErr(TSYS::strMess(_("Variable '%s' just after variable '%s'"),$2->name().c_str(),$1->name().c_str()),&@1); YYABORT; } } | var O_PRP_F { $$ = pF->cdProp($1,$2); } | var '[' expr ']' { $$ = pF->cdProp($1,"",$3); } | var O_PRP_F '(' prmlst ')' { try{ $$ = pF->cdObjFnc($1,$2,$4); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } assign: assign ',' assign | var '=' expr { try { if($1->type() == Reg::Free) $1->setType($3->vType(pF)); pF->cdAssign($1, $3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | var ADDEQ expr { try { if($1->type() == Reg::Free) throw TError(pF->nodePath().c_str(), _("Variable '%s' is used but undefined"), $1->name().c_str()); pF->cdBinaryOp(Reg::AddAss, $1, $3, $1); //pF->cdAssign($1, pF->cdBinaryOp(Reg::Add,$1,$3)); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | var SUBEQ expr { try { if($1->type() == Reg::Free) throw TError(pF->nodePath().c_str(), _("Variable '%s' is used but undefined"), $1->name().c_str()); pF->cdBinaryOp(Reg::SubAss, $1, $3, $1); //pF->cdAssign($1, pF->cdBinaryOp(Reg::Sub,$1,$3)); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | var MULEQ expr { try { if($1->type() == Reg::Free) throw TError(pF->nodePath().c_str(), _("Variable '%s' is used but undefined"), $1->name().c_str()); pF->cdBinaryOp(Reg::MulAss, $1, $3, $1); //pF->cdAssign($1, pF->cdBinaryOp(Reg::Mul,$1,$3)); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | var DIVEQ expr { try { if($1->type() == Reg::Free) throw TError(pF->nodePath().c_str(), _("Variable '%s' is used but undefined"), $1->name().c_str()); pF->cdBinaryOp(Reg::DivAss, $1, $3, $1); //pF->cdAssign($1, pF->cdBinaryOp(Reg::Div,$1,$3)); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | var INCREM { try { if($1->type() == Reg::Free) throw TError(pF->nodePath().c_str(), _("Variable '%s' is used but undefined"), $1->name().c_str()); Reg *reg = pF->regTmpNew(); *reg = 1; pF->cdBinaryOp(Reg::AddAss, $1, reg, $1); //pF->cdAssign($1, pF->cdBinaryOp(Reg::Add,$1,reg)); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | var DECREM { try { if($1->type() == Reg::Free) throw TError(pF->nodePath().c_str(), _("Variable '%s' is used but undefined"), $1->name().c_str()); Reg *reg = pF->regTmpNew(); *reg = 1; pF->cdBinaryOp(Reg::SubAss, $1, reg, $1); //pF->cdAssign($1, pF->cdBinaryOp(Reg::Sub,$1,reg)); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | /*empty*/ expr: CONST { $$ = $1; } | expr CONST { try { if($1->type() != Reg::String || $2->type() != Reg::String) throw TError(pF->nodePath().c_str(),_("Error constant after constant")); $1->val().s->append(*($2->val().s)); $2->free(); $$ = $1; } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | var { try { if($1->type() == Reg::Free) throw TError(pF->nodePath().c_str(), _("Variable '%s' is used but undefined"), $1->name().c_str()); $$ = $1; } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | var '=' expr { try { if($1->type() == Reg::Free) $1->setType($3->vType(pF)); pF->cdAssign($1, $3); $$ = $1; } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | var INCREM { try { if($1->type() == Reg::Free) throw TError(pF->nodePath().c_str(), _("Variable '%s' is used but undefined"), $1->name().c_str()); $$ = pF->cdMove(NULL, $1); Reg *reg = pF->regTmpNew(); *reg = 1; pF->cdBinaryOp(Reg::AddAss, $1, reg, $1); //pF->cdAssign($1, pF->cdBinaryOp(Reg::Add,$1,reg)); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | var DECREM { try { if($1->type() == Reg::Free) throw TError(pF->nodePath().c_str(), _("Variable '%s' is used but undefined"), $1->name().c_str()); $$ = pF->cdMove(NULL, $1); Reg *reg = pF->regTmpNew(); *reg = 1; pF->cdBinaryOp(Reg::SubAss, $1, reg, $1); //pF->cdAssign($1, pF->cdBinaryOp(Reg::Sub,$1,reg)); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | INCREM var { try { if($2->type() == Reg::Free) throw TError(pF->nodePath().c_str(), _("Variable '%s' is used but undefined"), $2->name().c_str()); Reg *reg = pF->regTmpNew(); *reg = 1; pF->cdBinaryOp(Reg::AddAss, $2, reg, $2); //pF->cdAssign($2, pF->cdBinaryOp(Reg::Add,$2,reg)); $$ = $2; } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | DECREM var { try { if($2->type() == Reg::Free) throw TError(pF->nodePath().c_str(), _("Variable '%s' is used but undefined"), $2->name().c_str()); Reg *reg = pF->regTmpNew(); *reg = 1; pF->cdBinaryOp(Reg::SubAss, $2, reg, $2); //pF->cdAssign($2, pF->cdBinaryOp(Reg::Sub,$2,reg)); $$ = $2; } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | B_FUNC '(' ')' { try{ $$ = pF->cdBldFnc($1); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | B_FUNC1 '(' expr ')' { try{ $$ = pF->cdBldFnc($1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | B_FUNC2 '(' expr ',' expr ')' { try{ $$ = pF->cdBldFnc($1,$3,$5); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | FUNC '(' prmlst ')' { try{ $$ = pF->cdExtFnc($1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | FUNC_R '(' prmlst ')' { try{ $$ = pF->cdExtFnc(-1,$3,false,$1); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | INT_FUNC '(' prmlst ')' { try{ $$ = pF->cdIntFnc($1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | NEW OBJECT '(' ')' { try{ $$ = pF->cdMviObject(); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | NEW ARRAY '(' prmlst ')' { try{ $$ = pF->cdMviArray($4); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | NEW REGEXP '(' prmlst ')' { try{ $$ = pF->cdMviRegExp($4); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | expr '+' expr { try{ $$ = pF->cdBinaryOp(Reg::Add,$1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | expr '-' expr { try{ $$ = pF->cdBinaryOp(Reg::Sub,$1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | expr '*' expr { try{ $$ = pF->cdBinaryOp(Reg::Mul,$1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | expr '/' expr { try{ $$ = pF->cdBinaryOp(Reg::Div,$1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | expr '%' expr { try{ $$ = pF->cdBinaryOp(Reg::RstI,$1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | expr '|' expr { try{ $$ = pF->cdBinaryOp(Reg::BitOr,$1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | expr '&' expr { try{ $$ = pF->cdBinaryOp(Reg::BitAnd,$1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | expr '^' expr { try{ $$ = pF->cdBinaryOp(Reg::BitXor,$1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | '(' expr ')' { $$ = $2; } // | expr OR expr { try{ $$ = pF->cdBinaryOp(Reg::LOr,$1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | expr OR_expr expr end { try{ $$ = pF->cdCondBinaryOp($2,$1,$3,$4); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } // | expr AND expr { try{ $$ = pF->cdBinaryOp(Reg::LAnd,$1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | expr AND_expr expr end { try{ $$ = pF->cdCondBinaryOp($2,$1,$3,$4); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | expr BITSHLEFT expr { try{ $$ = pF->cdBinaryOp(Reg::BitShLeft,$1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | expr BITSHRIGHT expr { try{ $$ = pF->cdBinaryOp(Reg::BitShRight,$1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | expr '<' expr { try{ $$ = pF->cdBinaryOp(Reg::LT,$1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | expr '>' expr { try{ $$ = pF->cdBinaryOp(Reg::GT,$1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | expr GE expr { try{ $$ = pF->cdBinaryOp(Reg::GEQ,$1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | expr LE expr { try{ $$ = pF->cdBinaryOp(Reg::LEQ,$1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | expr EQ expr { try{ $$ = pF->cdBinaryOp(Reg::EQU,$1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | expr NE expr { try{ $$ = pF->cdBinaryOp(Reg::NEQ,$1,$3); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | '!' expr { try{ $$ = pF->cdUnaryOp(Reg::Not,$2); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | '~' expr { try{ $$ = pF->cdUnaryOp(Reg::BitNot,$2); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | '-' expr %prec UN_MINUS { try{ $$ = pF->cdUnaryOp(Reg::Neg,$2); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | expr if_expr expr end ':' expr end { try{ $$ = pF->cdCond($1,$2,$4,$7,$3,$6); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } | expr O_PRP_F { $$ = pF->cdProp($1,$2); } | expr '[' expr ']' { $$ = pF->cdProp($1,"",$3); } | expr O_PRP_F '(' prmlst ')' { try{ $$ = pF->cdObjFnc($1,$2,$4); } catch(TError &err){ sfErr(err.mess,&@1); YYABORT; } } prmlst: /*empty*/ { $$ = 0; } | expr { $$ = 1; pF->fPrmst.push_front($1); } | prmlst ',' prmlst { $$ = $1 + $3; } if: /*empty*/ { $$ = pF->prg.size(); pF->prg = pF->prg+(char)Reg::If+"RR00nn"; } if_expr: '?' { $$ = pF->prg.size(); pF->prg = pF->prg+(char)Reg::If+"RR00nn"; } OR_expr: OR { $$ = pF->prg.size(); pF->prg = pF->prg+(char)Reg::LCOr+"RRrrRRnn"; } AND_expr: AND { $$ = pF->prg.size(); pF->prg = pF->prg+(char)Reg::LCAnd+"RRrrRRnn"; } cycl: /*empty*/ { $$ = pF->prg.size(); pF->prg = pF->prg+(char)Reg::Cycle+"RRbbaann"; } varlst: /*empty*/ { $$ = 0; } | VAR { $$ = 1; pF->fPrmst.push_front($1); } | varlst ',' varlst { $$ = $1 + $3; } fnc_in: /*empty*/ { $$ = pF->prg.size(); pF->prg = pF->prg + (char)Reg::IFuncDef + "NN"; pF->prg += (uint8_t)pF->fPrmst.size(); uint16_t addr; int ckAddr; //Place the return if((ckAddr=pF->regGet("<>")) < 0) { addr = pF->regNew(false, -1, false); pF->regAt(addr)->setName("<>"); pF->regAt(addr)->setLock(true); //pF->regAt(addr)->setInFnc(false); } else addr = ckAddr; pF->prg.append((char*)&addr,sizeof(addr)); //Place the arguments while(pF->fPrmst.size()) { pF->fPrmst.back()->setType(Reg::Real); addr = pF->fPrmst.back()->pos(); pF->prg.append((char*)&addr,sizeof(addr)); pF->fPrmst.pop_back(); } } end: /*empty*/ { pF->prg+=(char)Reg::End; $$ = pF->prg.size(); } /************************* END OF GRAMMAR ****************************/ %% void sfErr( const string &mess, YYLTYPE *ps ) { char m_buf[prmStrBuf_SZ]; snprintf(m_buf, sizeof(m_buf), _("%s, pos: (%d,%d)-(%d,%d)."), mess.c_str(), ps->first_line, ps->first_column, ps->last_line, ps->last_column); yyerror(m_buf); } void yyerror( const char *s ) { pF->pErr += s; } int yylex( ) { unsigned c = 0, st_pos; unsigned &pos = pF->laPos; string &prog = pF->sprg; if(pos == 0) { yylloc.last_line = yylloc.last_column = 1; } retry: //Empty space while(pos < prog.size() && ((c = prog[pos]) == ' ' || c == '\n' || c == '\t' || c == '\f' || c == '\r' || c == '\v')) { if(c == '\n') { yylloc.last_column = 1; yylloc.last_line++; } else yylloc.last_column++; pos++; } //End string if(pos >= prog.size()) return 0; //Comentars // and /* ... */ if(prog.substr(pos,2) == "//") { pos += 2; while(pos < prog.size() && prog[pos] != '\n') pos++; goto retry; } if(prog.substr(pos,2) == "/*") { pos += 3; while(pos < prog.size() && prog.substr(pos-1,2) != "*/") { if(prog[pos] == '\n') { yylloc.last_column = 1; yylloc.last_line++; } else yylloc.last_column++; pos++; } pos++; goto retry; } yylloc.first_line = yylloc.last_line; yylloc.first_column = yylloc.last_column; //Number if(isdigit(c) || (c == '.' && (pos+1) < prog.size() && isdigit(prog[pos+1]))) { st_pos = pos; int tp = 0; //Type constant (0-detect;1-dec;2-oct;3-hex;4-real) if(c == '.') tp = 4; else { while(pos < prog.size() && isdigit(c=prog[pos])) { pos++; yylloc.last_column++; } if(pos >= prog.size()) tp = (prog[st_pos]=='0')?2:1; else if(c == 'x' || c == 'X') tp = 3; else if(c == '.' || c == 'e' || c == 'E') tp = 4; else tp = (prog[st_pos]=='0') ? 2 : 1; } if(tp == 1) { yylval.reg = pF->regTmpNew(); *yylval.reg = (int64_t)strtoll(prog.substr(st_pos,pos-st_pos).c_str(),NULL,10); return CONST; } else if(tp == 2) { yylloc.last_column -= pos-st_pos; pos = st_pos; while(pos < prog.size() && (c=prog[pos]) >= '0' && c <= '7') { pos++; yylloc.last_column++; } yylval.reg = pF->regTmpNew(); *yylval.reg = (int64_t)strtoll(prog.substr(st_pos,pos-st_pos).c_str(),NULL,8); return CONST; } else if(tp == 3) { pos++; yylloc.last_column++; while(pos < prog.size() && (isdigit(c=prog[pos]) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) { pos++; yylloc.last_column++; } yylval.reg = pF->regTmpNew(); *yylval.reg = (int64_t)strtoll(prog.substr(st_pos,pos-st_pos).c_str(),NULL,16); return CONST; } else if(tp == 4) { bool e_ok = (c=='e'||c=='E') ? true : false; pos++; yylloc.last_column++; while(pos < prog.size() && (isdigit(c=prog[pos]) || c == 'E' || c == 'e' || ((c == '+' || c == '-') && ((prog[pos-1]) == 'e' || (prog[pos-1]) == 'E')))) { if(c == 'E' || c == 'e') { if(e_ok) break; else e_ok = true; } pos++; yylloc.last_column++; } yylval.reg = pF->regTmpNew(); *yylval.reg = s2r(prog.substr(st_pos,pos-st_pos)); return CONST; } else return 0; } //String if(c == '"' && (pos+1) < prog.size()) { st_pos = ++pos; string rez_str; yylloc.last_column++; while(pos < prog.size() && prog[pos] != '"' && prog[pos] != '\n') { int elSzPass = 1; if(prog[pos] == '\\' && (pos+1) < prog.size()) { switch(prog[pos+1]) { case 'n': rez_str += '\n'; break; case 't': rez_str += '\t'; break; case 'b': rez_str += '\b'; break; case 'f': rez_str += '\f'; break; case 'r': rez_str += '\r'; break; case 'x': case 'X': if((pos+3) < prog.size() && isxdigit(prog[pos+2]) && isxdigit(prog[pos+3])) { rez_str += (char)strtol(prog.substr(pos+2,2).c_str(),NULL,16); elSzPass += 2; } break; default: if((pos+3) < prog.size() && prog[pos+1] >= '0' && prog[pos+1] <= '7' && prog[pos+2] >= '0' && prog[pos+2] <= '7' && prog[pos+3] >= '0' && prog[pos+3] <= '7') { rez_str += (char)strtol(prog.substr(pos+1,3).c_str(),NULL,8); elSzPass += 2; } else rez_str += prog[pos+1]; } elSzPass++; } else rez_str += prog[pos]; pos += elSzPass; yylloc.last_column += elSzPass; } if(pos >= prog.size()) { yyerror(_("Unexpected end program, expect end string symbol '\"', ")); return ERR; } else if(prog[pos] == '\n') { yyerror(_("The next line symbol failed into string, ")); return ERR; } yylloc.last_column++; yylval.reg = pF->regTmpNew(); *yylval.reg = rez_str; //*yylval.reg = prog.substr(st_pos,pos-st_pos); pos++; return CONST; } //Symbols if(c == '_' || isalpha(c) || c > 0x7F) { bool is_dot = false; st_pos = pos; while(pos < prog.size() && ((c = prog[pos]) == '_' || c == '.' || isalnum(c) || c > 0x7F)) { if(c == '.') is_dot = true; pos++; yylloc.last_column++; } string smb_nm = prog.substr(st_pos,pos-st_pos); //Keywords if(smb_nm == "if") return IF; if(smb_nm == "else") return ELSE; if(smb_nm == "while") return WHILE; if(smb_nm == "for") return FOR; if(smb_nm == "break") return BREAK; if(smb_nm == "continue")return CONTINUE; if(smb_nm == "return") return RETURN; if(smb_nm == "new") return NEW; if(smb_nm == "delete") return DELETE; if(smb_nm == "Object") return OBJECT; if(smb_nm == "Array") return ARRAY; if(smb_nm == "RegExp") return REGEXP; if(smb_nm == "using") { char buf[255]; buf[0] = 0; while(pos < prog.size() && prog[pos] != ';') pos++; if(pos < prog.size()) sscanf(prog.substr(st_pos,pos-st_pos).c_str(),"using %254s",buf); if(pos >= prog.size() || buf[0] == 0) { yyerror(_("Using namespace is error or empty, ")); return ERR; } string fVal; for(int off = 0; !(fVal=TSYS::strSepParse(pF->mUsings,0,';',&off)).empty(); ) if(fVal == buf) break; if(fVal.empty()) pF->mUsings = pF->mUsings+buf+";"; pos++; goto retry; } if(smb_nm == "function") { yylval.op[0] = 0; while(pos < prog.size() && !(prog[pos] == '(' || prog[pos] == '=')) pos++; if(pos < prog.size()) sscanf(prog.substr(st_pos,pos-st_pos).c_str(),"function %254s",yylval.op); if(pos >= prog.size() || yylval.op[0] == 0) { yyerror(_("Internal function declaration error, ")); return ERR; } // Static function assign if(prog[pos] == '=') { smb_nm = yylval.op; if(!(yylval.reg=pF->regAt(pF->regGet(EXT_F_AS_PREF+smb_nm)))) { yylval.reg = pF->regAt(pF->regNew(true)); yylval.reg->setName(EXT_F_AS_PREF+smb_nm); yylval.reg->setType(Reg::Function); yylval.reg->setLock(true); } return VAR; } // Internal function define if(pF->inFuncGet(yylval.op) >= 0) { yyerror(TSYS::strMess(_("Internal function '%s' defined early, "),yylval.op).c_str()); return ERR; } if(pF->mInFnc.size()) { yyerror(_("Do not include declaration of one internal function to other, ")); return ERR; } pF->inFuncDef(yylval.op, pF->prg.size()); //Early mark of the function context return FUNCTION; } //Boolean if(smb_nm == "true" || smb_nm == "false") { yylval.reg = pF->regTmpNew(); *yylval.reg = (smb_nm == "true") ? true : false; return CONST; } //Check IO if(c != '(' && (yylval.reg=pF->regAt(pF->ioGet(smb_nm)))) return VAR; //Constants NConst *cnst_v; if((cnst_v = mod->constGet(smb_nm.c_str())) != NULL) { yylval.reg = pF->regTmpNew(); switch(cnst_v->tp) { case TFld::Real: *yylval.reg = TSYS::getUnalignDbl(cnst_v->val.data()); break; case TFld::Integer: *yylval.reg = (int64_t)TSYS::getUnalign64(cnst_v->val.data()); break; case TFld::Boolean: *yylval.reg = (char)cnst_v->val[0]; break; case TFld::String: *yylval.reg = cnst_v->val; break; default: break; } return CONST; } //Constant objects string sel = TSYS::strSepParse(smb_nm,0,'.'); if(sel == "SYS" || sel == "arguments") { yylval.reg = pF->regTmpNew(); yylval.reg->setType(Reg::Obj); yylval.reg->setName(sel); pos -= (smb_nm.size()-sel.size()); yylloc.last_column -= (smb_nm.size()-sel.size()); return VAR; } //Find buildin function BFunc *bf = NULL; if(c == '(' && (bf=mod->bFuncGet(smb_nm.c_str()))) { yylval.id = bf->code; switch(bf->prm) { case 0: return B_FUNC; case 1: return B_FUNC1; case 2: return B_FUNC2; default: yyerror(_("Build in function has too much parameters, ")); return ERR; } } //Find internal, external or object's functions execution if(c == '(') { // Internal functions if((yylval.id=pF->inFuncGet(smb_nm)) >= 0) return INT_FUNC; // Static linked external functions if((yylval.reg=pF->regAt(pF->regGet(EXT_F_AS_PREF+smb_nm)))) return FUNC_R; // External/static functions if((yylval.id=pF->funcGet(smb_nm)) >= 0) return FUNC; // Check for object's functions and system object's function //string sel = TSYS::strSepParse(smb_nm,0,'.'); if((yylval.reg=pF->regAt(pF->regGet(sel,true))) || (yylval.reg=pF->regAt(pF->ioGet(sel)))) { pos -= (smb_nm.size()-sel.size()); yylloc.last_column -= (smb_nm.size()-sel.size()); return VAR; } yyerror(_("Function error, ")); return ERR; } //Check allowed registers if((yylval.reg=pF->regAt(pF->regGet(smb_nm,true)))) return VAR; //Check for register as dynamic linked external function, mostly for allow it check for connection if((yylval.reg=pF->regAt(pF->regGet(EXT_F_AS_PREF+smb_nm)))) return VAR; //Global attributes and object's parameters. if(is_dot) { // Check to parameter attribute (TValue) try { AutoHD vl = SYS->daq().at().at(TSYS::strSepParse(smb_nm,0,'.')).at(). at(TSYS::strSepParse(smb_nm,1,'.')).at(). at(TSYS::strSepParse(smb_nm,2,'.')).at(). vlAt(TSYS::strSepParse(smb_nm,3,'.')); yylval.reg = pF->regAt(pF->regNew(true)); yylval.reg->setName(smb_nm); yylval.reg->setPAttr(vl); yylval.reg->setLock(true); return VAR; } catch(...) { } // Check for object's parameters //string sel = TSYS::strSepParse(smb_nm,0,'.'); if((yylval.reg=pF->regAt(pF->regGet(sel,true))) || (yylval.reg=pF->regAt(pF->ioGet(sel)))) { pos -= (smb_nm.size()-sel.size()); yylloc.last_column -= (smb_nm.size()-sel.size()); return VAR; } yyerror(_("Symbol error, ")); return ERR; } //Check IO //if((yylval.reg=pF->regAt(pF->ioGet(smb_nm)))) return VAR; //Keywords if(smb_nm == "in") return IN; if(smb_nm == "var") return VAR_DIR; //Get new register yylval.reg = pF->regAt(pF->regNew(true)); yylval.reg->setName(smb_nm); #ifdef IN_F_SHARE_REGS if(pF->mInFnc.size()) yylval.reg->setName(yylval.reg->name()); #else if(pF->mInFnc.size()) yylval.reg->setName(pF->mInFnc+":"+yylval.reg->name()); #endif yylval.reg->setLock(true); return VAR; } //Object's properties or functions else if(c == '.' && (pos+1) < prog.size()) { st_pos = ++pos; yylloc.last_column++; while(pos < prog.size() && ((c = prog[pos]) == '_' || isalpha(c) || (pos > st_pos && isdigit(c)) || c > 0x7F)) { pos++; yylloc.last_column++; } if((pos-st_pos) > 255) { yyerror(_("Object's properties too long, ")); return ERR; } strncpy(yylval.op,prog.substr(st_pos,pos-st_pos).data(),255); // pF->o_prpf.push_back(prog.substr(st_pos,pos-st_pos)); return O_PRP_F; } //Multi symbol operations else if(prog.substr(pos,2) == "++") { pos += 2; yylloc.last_column += 2; return INCREM; } else if(prog.substr(pos,2) == "--") { pos += 2; yylloc.last_column += 2; return DECREM; } else if(prog.substr(pos,2) == "||") { pos += 2; yylloc.last_column += 2; return OR; } else if(prog.substr(pos,2) == "&&") { pos += 2; yylloc.last_column += 2; return AND; } else if(prog.substr(pos,2) == ">=") { pos += 2; yylloc.last_column += 2; return GE; } else if(prog.substr(pos,2) == "<=") { pos += 2; yylloc.last_column += 2; return LE; } else if(prog.substr(pos,2) == "==") { pos += 2; yylloc.last_column += 2; return EQ; } else if(prog.substr(pos,2) == "!=") { pos += 2; yylloc.last_column += 2; return NE; } else if(prog.substr(pos,2) == "<<") { pos += 2; yylloc.last_column += 2; return BITSHLEFT; } else if(prog.substr(pos,2) == ">>") { pos += 2; yylloc.last_column += 2; return BITSHRIGHT; } else if(prog.substr(pos,2) == "+=") { pos += 2; yylloc.last_column += 2; return ADDEQ; } else if(prog.substr(pos,2) == "-=") { pos += 2; yylloc.last_column += 2; return SUBEQ; } else if(prog.substr(pos,2) == "*=") { pos += 2; yylloc.last_column += 2; return MULEQ; } else if(prog.substr(pos,2) == "/=") { pos += 2; yylloc.last_column += 2; return DIVEQ; } else { pos++; yylloc.last_column++; } return c; } }