PUBLIC EjsAny *ejsDeserialize(Ejs *ejs, EjsString *str) { EjsObj *obj; JsonState js; if (!ejsIs(ejs, str, String)) { ejsThrowSyntaxError(ejs, "Object is not a string"); return 0; } if (str->length == 0) { return ESV(empty); } js.next = js.data = str->value; js.end = &js.data[str->length]; js.error = 0; if ((obj = parseLiteral(ejs, &js)) == 0) { if (js.error) { ejsThrowSyntaxError(ejs, "Cannot parse object literal. Error at position %d.\n" "===========================\n" "Offending text: %w\n" "===========================\n" "In literal %w" "\n===========================\n", (int) (js.error - js.data), js.error, js.data); } else { ejsThrowSyntaxError(ejs, "Cannot parse object literal. Undefined error"); } return 0; } return obj; }
void MacroEnsamZ::compilaExpresionOLiteral(Metodo::CuerpoMetodo &instrucc) { lex->pasaEsp(); // Quéviene ahora? Zero::AnalizadorLexico::TipoToken tk = lex->getTipoSiguienteToken(); // Coger la expresié if (tk == Zero::AnalizadorLexico::IDENTIFICADOR) { lex->getToken(); compilaExpresion(lex->getTokenActual(), mnemosMetActual, instrucc); } else if (tk != Zero::AnalizadorLexico::NADA) { Zero::Mnemotecnico * lit = parseLiteral(); if (lit != NULL) { instrucc.push_back(lit); } else throw Zero::ESintaxis("se esperaba literal"); } else throw Zero::ESintaxis("se esperaba expresión"); }
PARSENODE_PTR SQLParser::parseExpression() { PARSENODE_PTR columnNode = parseIdentifier(); PARSENODE_PTR opNode = parseOperator(); PARSENODE_PTR valueNode = parseLiteral(); opNode->children.push_back(columnNode); opNode->children.push_back(valueNode); return opNode; }
ast::Expr *parsePrimary(TokenIt &it, const TokenIt &end) { Token *current = currentToken(it, end); EXPECT_ANY_TOKEN(current, errorE, "Expected a primary expression"); switch(current->type) { case Token::IDENTIFIER: return parseIdentifier(it, end); case Token::NUMBER: return parseLiteral(it, end); case Token::LPAREN: return parseParenExpr(it, end); default: return errorE("Unexpected token when expecting an expression"); } }
/** * Parses part of a regular expression string and builds a regular expression * tree with the given left subtree. The root node of the new tree is returned. * @param left The left subtree. * @param string The regular expression string. * @param pos The position of the parser in the regular expression. * @param len The length of the whole regular expression string. * @return The new root node of the expression tree. * @author Daniel Dreibrodt, Konstantin Steinmiller */ RETreeNode *REReaderWriter::parseNode(RETreeNode *left, const char string[], int *pos, int len) { if(*pos>=len) { //end of string reached, return last known tree root return left; } switch(string[*pos]) { case '(' : { throw "Read '(' but that is not allowed here!"; break; } case ')' : { (*pos)++; return left; break; } case '|' : { RETreeNode *opNode = new RETreeNode("|"); (*pos)++; opNode->setLeft(left); opNode->setRight(parseNode(string, pos, len)); return opNode; break; } case '.' : { RETreeNode *opNode = new RETreeNode("."); (*pos)++; opNode->setLeft(left); opNode->setRight(parseNode(string, pos, len)); return opNode; break; } case '*' : { RETreeNode *opNode = new RETreeNode("*"); (*pos)++; opNode->setLeft(left); return parseNode(opNode, string, pos, len); break; } case ' ' : { (*pos)++; return parseNode(left, string, pos, len); break; } default : { RETreeNode *lit = parseLiteral(string,pos,len); return parseNode(lit, string, pos, len); break; } } }
PARSENODE_PTR SQLParser::parseInsert() { if (!startsInsert(nowReading)) { syntaxError(nowReading, "expect insert token!"); return nullptr; } //LOG_TRACE(logger, "parse insert statement."); PARSENODE_PTR insertNode = PARSENODE_PTR(new ParseNode(INSERT)); readToken(); expect(INTO); insertNode->children.push_back(parseIdentifier()); expect(VALUES); expect(LEFT_BRACE); insertNode->children.push_back(parseLiteral()); while (nowReading == SLICE) { readToken(); insertNode->children.push_back(parseLiteral()); } expect(RIGHT_BRACE); expect(TERMINATOR); return insertNode; }
/** * Parses a regular expression string and builds a regular expression * tree. The root node of that tree is returned. * @param string The regular expression string. * @param pos The position of the parser in the regular expression. * @param len The length of the whole regular expression string. * @return The root node of the expression tree. * @author Daniel Dreibrodt, Konstantin Steinmiller */ RETreeNode *REReaderWriter::parseNode(const char string[], int *pos, int len) { if(*pos>=len) { //end of string reached return NULL; } switch(string[*pos]) { case '(' : { (*pos)++; RETreeNode *groupNode = parseNode(string, pos, len); return parseNode(groupNode, string, pos, len); break; } case ')' : { throw "Read ')' but that is not allowed here!"; break; } case '|' : { throw "Read '|' but that is not allowed here!"; break; } case '.' : { throw "Read '.' but that is not allowed here!"; break; } case '*' : { throw "Read '*' but that is not allowed here!"; break; } case ' ' : { (*pos)++; return parseNode(string, pos, len); break; } default : { RETreeNode *lit = parseLiteral(string,pos,len); return parseNode(lit, string, pos, len); break; } } }
/* Parse an object literal string pointed to by js->next into the given buffer. Update js->next to point to the next input token in the object literal. Supports nested object literals. */ static EjsObj *parseLiteralInner(Ejs *ejs, MprBuf *buf, JsonState *js) { EjsAny *obj, *vp; MprBuf *valueBuf; wchar *token, *key, *value; int tid, isArray; isArray = 0; tid = getNextJsonToken(buf, &token, js); if (tid == TOK_ERR || tid == TOK_EOF) { return 0; } if (tid == TOK_LBRACKET) { isArray = 1; obj = (EjsObj*) ejsCreateArray(ejs, 0); } else if (tid == TOK_LBRACE) { obj = ejsCreateEmptyPot(ejs); } else { return ejsParse(ejs, token, S_String); } if (obj == 0) { ejsThrowMemoryError(ejs); return 0; } while (1) { vp = 0; tid = peekNextJsonToken(js); if (tid == TOK_ERR) { return 0; } else if (tid == TOK_EOF) { break; } else if (tid == TOK_RBRACE || tid == TOK_RBRACKET) { getNextJsonToken(buf, &key, js); break; } if (tid == TOK_LBRACKET) { /* For array values */ vp = parseLiteral(ejs, js); assert(vp); } else if (tid == TOK_LBRACE) { /* For object values */ vp = parseLiteral(ejs, js); assert(vp); } else if (isArray) { tid = getNextJsonToken(buf, &value, js); vp = ejsParse(ejs, value, (tid == TOK_QID) ? S_String: -1); assert(vp); } else { getNextJsonToken(buf, &key, js); tid = peekNextJsonToken(js); if (tid == TOK_ERR) { return 0; } else if (tid == TOK_EOF) { break; } else if (tid == TOK_LBRACE || tid == TOK_LBRACKET) { vp = parseLiteral(ejs, js); } else if (tid == TOK_ID || tid == TOK_QID) { valueBuf = mprCreateBuf(0, 0); getNextJsonToken(valueBuf, &value, js); if (tid == TOK_QID) { vp = ejsCreateString(ejs, value, strlen(value)); } else { if (mcmp(value, "null") == 0) { vp = ESV(null); } else if (mcmp(value, "undefined") == 0) { vp = ESV(undefined); } else { vp = ejsParse(ejs, value, -1); } } assert(vp); } else { getNextJsonToken(buf, &value, js); js->error = js->next; return 0; } } if (vp == 0) { js->error = js->next; return 0; } if (isArray) { if (ejsSetProperty(ejs, obj, -1, vp) < 0) { ejsThrowMemoryError(ejs); return 0; } } else { if (ejsSetPropertyByName(ejs, obj, WEN(key), vp) < 0) { ejsThrowMemoryError(ejs); return 0; } } } return obj; }
QList< Token > Engine::tokenize(QString ex) { //presets Token::Type ctype=Token::Invalid; QString ctok; QList<Token> ret; int cline=1,ccol=0; int sline=cline,scol=ccol; int litend=-1; //go through expression for(int i=0;i<ex.size();i++){ if(ex[i]=='\n'){cline++;ccol=0;} ccol++; //skip everything till end of a literal if(litend>i)continue; //get type of current character Token::Type ntype=d->cclass.charType(ex[i],ctype); //check for invalid stuff if(ntype==Token::Invalid) return QList<Token>()<<Token(Position(cline,ccol)); //check whether we are still inside the same token if(ntype==ctype) ctok+=ex[i]; else{ //store old token if(ctype!=Token::Invalid && ctype!=Token::Whitespace && ctok!="") ret<<Token(ctok,ctype,Position(sline,scol)); //reset state ctok.clear(); sline=cline; scol=ccol; //handle current char switch(ntype){ case Token::ParOpen: case Token::ParClose: case Token::Comma: //special chars ret<<Token(QString(ex[i]),ntype,Position(cline,ccol)); ctype=Token::Invalid; break; case Token::Whitespace: case Token::Operator: case Token::Name: //start new token ctype=ntype; ctok+=ex[i]; break; case Token::Literal:{ //parse it QPair<QString,QVariant>lt=parseLiteral(ex,i); //check for failure if(lt.first=="") return QList<Token>()<<Token(Position(cline,ccol)); //store token ret<<Token(lt.first,lt.second,Position(cline,ccol)); //make the loop skip the rest litend=i+lt.first.size(); ctype=Token::Invalid; break;} default://nothing qDebug()<<"oops. unexpected token type at line"<<cline<<"col"<<ccol; ctype=Token::Invalid; break; } } } //add remaining stuff if(ctype!=Token::Invalid && ctype!=Token::Whitespace && ctok!="") ret<<Token(ctok,ctype,Position(sline,scol)); return ret; }
// -------------------------------------------- MacroEnsamZ::compilaExpresion() void MacroEnsamZ::compilaExpresion(const std::string &tok, Metodo *& met, Metodo::CuerpoMetodo &instrucc, bool primerNivel) /* compilar una expresion de este estilo: expr ::= [<ref>]+.<metodo>(<expr>) System.console.write(x.concat("Mundo!")) A: STR "Mundo!" ASG __gp1 MSG x concat __gp1 MSG System.console write __acc */ { Zero::Mnemotecnico *mnemo; GestorNombresLoc nl; lex->pasaEsp(); if ( Zero::NombreIdentificador::compruebaId( tok ) || ( Zero::NombreReferencia::compruebaRef( tok ) && lex->getCaracterActual() != '(' ) ) { if ( !primerNivel ) { // Es un identificador, se asigna al acc y punto mnemo = new(std::nothrow) Zero::NMSet( Zero::NombreRegistro::__ACC, tok ); if ( mnemo != NULL ) instrucc.push_back( mnemo ); else throw Zero::ENoHayMemoria( "creando mnemo SET" ); } else throw Zero::ESintxIdNoValido( "se esperaba asignacié o mensaje" ); } else { if (Zero::NombreReferencia::compruebaRef( tok ) ) { // Es un mensaje a un objeto std::string refObjeto = tok; size_t posUltimoPunto = refObjeto.rfind( '.' ); std::string nombreMetodo = refObjeto.substr( posUltimoPunto + 1 ); // borra '*.met' refObjeto.erase(posUltimoPunto, refObjeto.size()); lex->pasaEsp(); if( refObjeto.empty() ) { refObjeto = "."; } // Pasar el paréntesis, si existe if ( lex->getCaracterActual() == '(' ) { lex->avanza(); } else throw Zero::ESintxIdNoValido("se esperaba apertura de parétesis '('"); Zero::AnalizadorLexico::TipoToken tk = lex->getTipoSiguienteToken(); do { // Compilar la sub-expresión if (tk == Zero::AnalizadorLexico::LITNUMERICO) { Zero::Mnemotecnico * lit = parseLiteral(); if ( lit == NULL ) { throw Zero::ESintxIdNoValido( "se esperaba literal" "numérico" ); } instrucc.insert( instrucc.begin(), new Zero::NMAsg( nl.crearNuevo(), Zero::NombreRegistro::__ACC ) ); instrucc.insert( instrucc.begin(), lit ); } else if (tk == Zero::AnalizadorLexico::LITCADENA) { Zero::Mnemotecnico * lit = parseLiteral(); if (lit == NULL) throw Zero::ESintxIdNoValido("se esperaba literal cadena"); // Guardar el mensaje instrucc.insert(instrucc.begin(), new Zero::NMAsg( nl.crearNuevo(), Zero::NombreRegistro::__ACC ) ); instrucc.insert( instrucc.begin(), lit ); } else if (tk == Zero::AnalizadorLexico::IDENTIFICADOR) { // Tomar el identificador lex->getToken(); // Si es un identificador, adelante if ( Zero::NombreIdentificador::compruebaId( lex->getTokenActual() ) ) { if ( buscaVble( objetoActual, metodoActual, lex->getTokenActual() ) ) { nl.insertarNuevo( lex->getTokenActual() ); } else { compilaExpresion( lex->getTokenActual(), met, instrucc ); instrucc.push_back( new Zero::NMAsg( nl.crearNuevo(), Zero::NombreRegistro::__ACC) ); } } else { if ( Zero::NombreReferencia::compruebaRef( lex->getTokenActual() ) ) { // Es una referencia, // llamada recursiva compilaExpresion( lex->getTokenActual(), met, instrucc ) ; // Pasar el ')' if ( lex->getCaracterActual() == ')' ) { lex->avanza(); } instrucc.push_back( new Zero::NMAsg( nl.crearNuevo(), Zero::NombreRegistro::__ACC) ); } else throw Zero::ESintxIdNoValido("se esperaba un identificador" " o referencia"); } } lex->pasaEsp(); tk = lex->getTipoSiguienteToken(); } while(( lex->getCaracterActual() != ')') && ( !lex->esEol() ) ); // Crear el mensaje Zero::NMMsg *msg = new Zero::NMMsg( refObjeto, nombreMetodo ); // Argumentos while(!(nl.esVacio())) { msg->masArgumentos( nl.getSigNombre() ); } instrucc.push_back( msg ); } else throw Zero::ESintxIdNoValido("expresión debe empezar " "por referencia o identificador") ; } }