/* ================ Lexer::ReadFloat ================ */ float Lexer::ReadFloat( void ) { if ( !ReadToken() ) throw LexerError( LexerError::END_OF_FILE ); if ( !String::IsNumeric( token.GetString() ) ) throw LexerError( LexerError::BAD_TOKEN, token.line, "float", token.GetString() ); return String::ToFloat( token.GetString() ); }
openddl::Tree openddl::Tree::parse(const std::string & i) { Tree::Impl * impl = new Tree::Impl(); std::vector<detail::Token> tokens; std::vector<detail::Error> errors; if (!detail::lex(i, tokens, errors)) { throw LexerError(errors); } else if (!detail::parse(tokens, impl->commands, errors)) { throw ParseError(errors); } else if (!detail::semantic_check(impl->commands, errors, impl->global_names, impl->local_names)) { throw SemanticError(errors); } //Build the child table to avoid walking the table whenever running visitors across the data for (unsigned int i = 0; i < impl->commands.size(); i++) { auto it = impl->child_table.find(impl->commands[i].parent); if (it == impl->child_table.end()) it = impl->child_table.emplace(impl->commands[i].parent,std::vector<unsigned int>()).first; it->second.push_back(i); } Tree t; t.implementation.reset(impl); return std::move(t); }
/* ================ Lexer::FindToken ================ */ void Lexer::FindToken( const char *str ) { while ( ReadToken() ) { if ( String::Icmp( token.GetString(), str ) == 0 ) return; } throw LexerError( LexerError::MISSING_TOKEN, token.line, str, "[EOF]" ); }
/* ================ Lexer::CheckToken ================ */ bool Lexer::CheckToken( const char *string ) { if ( !ReadToken() ) throw LexerError( LexerError::END_OF_FILE ); if ( String::Icmp( token.GetString(), string ) != 0 ) { UnreadToken(); return false; } return true; }
/* ================ Lexer::ParseQuoted ================ */ void Lexer::ParseQuoted( void ) { char c = buffer[bufPos]; if ( flags & LEXER_FULL_LINES ) AddToToken( buffer[bufPos] ); bufPos++; while ( bufPos < bufSize ) { // Check for newlines if ( buffer[bufPos] == '\n' || buffer[bufPos] == '\r' ) throw LexerError( LexerError::BAD_TOKEN, token.line, Format( "quote end: '\\$*'" ) << c, "[EOL]" ); // Check for escape characters if ( useEscapeChars && buffer[bufPos] == '\\' ) { if ( buffer[bufPos+1] == 'n' ) { AddToToken( '\n' ); bufPos += 2; continue; } else if ( buffer[bufPos+1] == 't' ) { AddToToken( '\t' ); bufPos += 2; continue; } else if ( buffer[bufPos+1] == '\"' || buffer[bufPos+1] == '\'' ) { AddToToken( buffer[bufPos+1] ); bufPos += 2; continue; } } // Check if this is the quote end we are looking for. else if ( buffer[bufPos] == c ) { if ( flags & LEXER_FULL_LINES ) AddToToken( buffer[bufPos] ); else FinishToken( true ); bufPos++; return; } AddToToken( buffer[bufPos] ); bufPos++; } throw LexerError( LexerError::BAD_TOKEN, token.line, Format("quote end: '\\$*'" ) << c, "[EOF]" ); }
/* ================ DeclParser::Parse ================ */ void DeclParser::Parse( Lexer &lexer ) { Dict *resultDict = OG_NULL; bool getKeyValue = false; int index; const Token *token; String key, value; const char *p; while ( (token = lexer.ReadToken()) != OG_NULL ) { p = token->GetString(); if ( p ) { if ( *p == '\0' ) lexer.Error("Unexpected Empty Token"); if ( !getKeyValue ) { index = declTypes.Find(p); if ( index != -1 ) { value = lexer.ReadString(); if ( value.IsEmpty() ) lexer.Error("Empty name!"); DictEx<Dict> &result = declTypes[index]->declList; index = result.Find(p); if ( index == -1 ) resultDict = &result[p]; else { resultDict = &result[index]; resultDict->Clear(); } } else { resultDict = OG_NULL; lexer.Warning( Format("Unknown decl Type '$*'") << p ); } lexer.ExpectToken("{"); getKeyValue = true; } else { if ( *p == '}' ) getKeyValue = false; else if ( resultDict ) { key = p; (*resultDict).Set( key.c_str(), lexer.ReadString() ); } } } } if ( getKeyValue ) throw LexerError( LexerError::END_OF_FILE ); }
/* ================ ImportMD5AnimBaseFrame ================ */ bool ImportMD5AnimBaseFrame( const char *filename, Model *model ) { Lexer lexer(LEXER_NO_BOM_WARNING); if ( !lexer.LoadFile( filename ) ) { delete model; return false; } try { // MD5Version must be the first keyword lexer.ExpectToken( "MD5Version" ); int fileVersion = lexer.ReadInt(); if ( fileVersion != MD5_VERSION_DOOM3 && fileVersion != MD5_VERSION_QUAKEWARS ) lexer.Error( Format("MD5Version is $*, should be $* or $*") << fileVersion << MD5_VERSION_DOOM3 << MD5_VERSION_QUAKEWARS ); const Token *token; String key; const char *p; bool inHierarchyGroup = false; bool inBoundsGroup = false; bool inBaseFrameGroup = false; bool inFrameGroup = false; int numJoints = -1; int frameRate, numFrames, currentFrame; bool noAnimate = false; bool readVertexColor = false; Color vertexColor; ListEx<MD5Vertex> vertexList; ListEx<MD5Weight> weightList; Vec3 vTemp; int boneIndex = 0; while ( (token = lexer.ReadToken()) != NULL ) { p = token->GetString(); if ( !p || !*p ) continue; if ( inHierarchyGroup ) { if ( *p == '}' ) { inHierarchyGroup = false; continue; } Bone &bone = model->bones.Alloc(); bone.name = p; bone.idParent = lexer.ReadInt(); bone.flags = lexer.ReadInt(); lexer.ReadInt(); // start index ? } else if ( inBaseFrameGroup ) { if ( *p == '}' ) { inBaseFrameGroup = false; break; //! @todo should be continue when loading all frames. } lexer.UnreadToken(); Bone &bone = model->bones[boneIndex++]; ParseVector( lexer, &bone.origin.x, 3 ); ParseVector( lexer, &bone.quat.x, 3 ); bone.origin *= MD5_MODEL_SCALE; // Compute w bone.quat.w = 1.0f - (bone.quat.x * bone.quat.x) - (bone.quat.y * bone.quat.y) - (bone.quat.z * bone.quat.z); bone.quat.w = ( bone.quat.w <= 0.0f ) ? 0.0f : -Math::Sqrt( bone.quat.w ); } else if ( inBoundsGroup ) { if ( *p == '}' ) { inBoundsGroup = false; continue; } lexer.UnreadToken(); ParseVector( lexer, &vTemp.x, 3 ); ParseVector( lexer, &vTemp.x, 3 ); } else if ( inFrameGroup ) { if ( *p == '}' ) { inFrameGroup = false; continue; } //! @todo why was here a fixme ? } else { if ( String::Icmp( p, "commandline" ) == 0 ) { // Skip value, we don't need it lexer.ReadToken(); } else if ( String::Icmp( p, "frameRate" ) == 0 ) { frameRate = lexer.ReadInt(); } else if ( String::Icmp( p, "numAnimatedComponents" ) == 0 ) { // Skip value, we don't need it lexer.ReadToken(); } else if ( String::Icmp( p, "numJoints" ) == 0 ) { numJoints = lexer.ReadInt(); if ( numJoints > 0 ) { model->bones.SetGranularity( numJoints ); model->bones.CheckSize( numJoints ); } } else if ( String::Icmp( p, "numFrames" ) == 0 ) { numFrames = lexer.ReadInt(); if ( numFrames <= 0 ) lexer.Error("Zero frames on model"); //! @todo why was here a fixme ? } else if ( String::Icmp( p, "hierarchy" ) == 0 ) { if ( numJoints == -1 ) lexer.Error("numJoins not set!"); lexer.ExpectToken( "{" ); inHierarchyGroup = true; } else if ( String::Icmp( p, "bounds" ) == 0 ) { lexer.ExpectToken( "{" ); inBoundsGroup = true; } else if ( String::Icmp( p, "baseframe" ) == 0 ) { lexer.ExpectToken( "{" ); inBaseFrameGroup = true; } else if ( String::Icmp( p, "frame" ) == 0 ) { currentFrame = lexer.ReadInt(); lexer.ExpectToken( "{" ); inFrameGroup = true; } else { lexer.Error( Format("Unexpected '$*'") << p ); } } } if ( inHierarchyGroup || inBoundsGroup || inFrameGroup || numJoints == -1 ) throw LexerError( LexerError::END_OF_FILE ); return true; } catch( LexerError err ) { delete model; String errStr; err.ToString( errStr ); User::Error( ERR_LEXER_FAILURE, errStr.c_str(), filename ); return false; } }
/* ================ Model::ImportMD5 ================ */ Model *Model::ImportMD5( const char *filename, const char *filenameAnim ) { Lexer lexer(LEXER_NO_BOM_WARNING); if ( !lexer.LoadFile( filename ) ) return NULL; Model *model = new Model(true); int numJoints = -1; try { // MD5Version must be the first keyword lexer.ExpectToken( "MD5Version" ); int fileVersion = lexer.ReadInt(); if ( fileVersion != MD5_VERSION_DOOM3 && fileVersion != MD5_VERSION_QUAKEWARS ) lexer.Error( Format( "MD5Version is $*, should be $* or $*") << fileVersion << MD5_VERSION_DOOM3 << MD5_VERSION_QUAKEWARS ); const Token *token; String key; const char *p; bool inJointGroup = false; bool inMeshGroup = false; bool readMeshVerts = false; bool readMeshTris = false; int numMeshes = -1; int numVerts, vertIndex; int triCounter, indexCounter; int numWeights; MeshAnimated *mesh = NULL; int i, j, num; Vec3 vTemp; bool noAnimate = false; bool readVertexColor = false; Color vertexColor; ListEx<MD5Vertex> vertexList; ListEx<MD5Weight> weightList; while ( (token = lexer.ReadToken()) != NULL ) { p = token->GetString(); if ( !p || !*p ) continue; if ( inJointGroup ) { if ( *p == '}' ) { inJointGroup = false; continue; } lexer.ReadInt(); // unused ParseVector( lexer, &vTemp.x, 3 ); ParseVector( lexer, &vTemp.x, 3 ); } else if ( inMeshGroup ) { lexer.UnreadToken(); if ( readMeshVerts ) { if ( lexer.CheckToken( "numtris" ) ) { if ( numVerts != vertexList.Num() ) lexer.Error( Format("numVerts don't match: $*") << vertexList.Num() ); InitIndices( mesh, lexer.ReadInt() * 3 ); // numtris * 3 triCounter = 0; indexCounter = 0; readMeshVerts = false; readMeshTris = true; continue; } lexer.ExpectToken( "vert" ); vertIndex = lexer.ReadInt(); if ( vertIndex != vertexList.Num() ) lexer.Error( Format("Bad Vert Index, should be $*") << vertexList.Num() ); MD5Vertex &vertex = vertexList.Alloc(); ParseVector( lexer, &vertex.texCoord.x, 2 ); vertex.firstWeight = lexer.ReadInt(); vertex.lastWeight = lexer.ReadInt() + vertex.firstWeight - 1; if ( readVertexColor ) { // Currently we don't have use for vertex color.. // I haven't seen md5meshes with other values than ( 1 1 1 1 ) for vertexColor anyway.. ParseVector( lexer, &vertexColor.r, 4 ); } } else if ( readMeshTris ) { if ( lexer.CheckToken( "numweights" ) ) { numWeights = lexer.ReadInt(); weightList.CheckSize( numWeights ); readMeshTris = false; continue; } lexer.ExpectToken( "tri" ); if ( lexer.ReadInt() != triCounter ) lexer.Error( Format("Bad Tri Index, should be $*") << triCounter ); mesh->indices[indexCounter++] = lexer.ReadInt(); mesh->indices[indexCounter++] = lexer.ReadInt(); mesh->indices[indexCounter++] = lexer.ReadInt(); triCounter++; } else { if ( lexer.CheckToken( "}" ) ) { if ( numWeights != weightList.Num() ) lexer.Error( Format("numWeights doesn't match $*") << weightList.Num() ); // Convert vertices: num = vertexList.Num(); for( i=0; i<num; i++ ) { if ( i >= vertexList.Num() ) lexer.Error( "Vertex index out of range" ); const MD5Vertex &md5Vert = vertexList[i]; mesh->texCoords[i] = md5Vert.texCoord; Vertex &vInfo = mesh->vertices[i]; InitVertex( &vInfo, 1 + md5Vert.lastWeight - md5Vert.firstWeight ); vInfo.numWeights = 0; for ( j=md5Vert.firstWeight; j<=md5Vert.lastWeight; j++ ) { if ( j >= weightList.Num() ) lexer.Error( "Weight index out of range" ); const MD5Weight &md5Weight = weightList[j]; if ( md5Weight.jointIndex >= numJoints ) lexer.Error( "Weight joint index out of range" ); if ( md5Weight.bias == 0.0f ) continue; VertexWeight &weight = vInfo.weights[vInfo.numWeights++]; weight.boneId = md5Weight.jointIndex; weight.origin = md5Weight.origin; //weight.normal = md5Weight.normal; //! @todo calculate normal weight.influence = md5Weight.bias; } } inMeshGroup = false; continue; } lexer.ExpectToken( "weight" ); if ( lexer.ReadInt() != weightList.Num() ) lexer.Error( Format("Bad VertexWeight Index, should be $*") << weightList.Num() ); MD5Weight &weight = weightList.Alloc(); weight.jointIndex = lexer.ReadInt(); weight.bias = lexer.ReadFloat(); ParseVector( lexer, &weight.origin.x, 3 ); weight.origin *= MD5_MODEL_SCALE; } } else { if ( String::Icmp( p, "commandline" ) == 0 ) { // Skip value, we don't need it lexer.ReadToken(); } else if ( String::Icmp( p, "numJoints" ) == 0 ) { numJoints = lexer.ReadInt(); if ( numJoints > 0 ) { model->bones.SetGranularity( numJoints ); model->bones.CheckSize( numJoints ); } } else if ( String::Icmp( p, "numMeshes" ) == 0 ) { numMeshes = lexer.ReadInt(); if ( numMeshes <= 0 ) lexer.Error("Zero meshes"); model->meshes.SetGranularity( numMeshes ); model->meshes.CheckSize( numMeshes ); } else if ( String::Icmp( p, "joints" ) == 0 ) { if ( numJoints == -1 ) lexer.Error( "numJoins not set!" ); lexer.ExpectToken( "{" ); inJointGroup = true; } else if ( String::Icmp( p, "mesh" ) == 0 ) { if ( numMeshes == -1 ) lexer.Error( "numMeshes not set!" ); lexer.ExpectToken( "{" ); mesh = new MeshAnimated; model->meshes.Append(mesh); if ( fileVersion != MD5_VERSION_QUAKEWARS ) mesh->name = Format("mesh $*") << model->meshes.Num(); else { lexer.ExpectToken( "name" ); mesh->name = lexer.ReadString(); } lexer.ExpectToken( "shader" ); mesh->material = lexer.ReadString(); noAnimate = false; readVertexColor = false; if ( fileVersion == MD5_VERSION_QUAKEWARS ) { lexer.ExpectToken( "flags" ); lexer.ExpectToken( "{" ); while( !lexer.CheckToken("}") ) { if ( lexer.CheckToken("noAnimate") ) noAnimate = true; else if ( lexer.CheckToken("vertexColor") ) readVertexColor = true; else lexer.Error( Format("Unknown flag: '$*'") << lexer.ReadString() ); } } lexer.ExpectToken( "numverts" ); numVerts = lexer.ReadInt(); vertexList.Clear(); vertexList.CheckSize( numVerts ); weightList.Clear(); InitVertices( mesh, numVerts ); inMeshGroup = true; readMeshVerts = true; } else { lexer.Error( Format("Unexpected '$*'") << p ); } } } if ( inJointGroup || inMeshGroup || numJoints == -1 || numMeshes == -1 ) throw LexerError( LexerError::END_OF_FILE ); } catch( LexerError err ) { delete model; String errStr; err.ToString( errStr ); User::Error( ERR_LEXER_FAILURE, errStr.c_str(), filename ); return NULL; } if ( !ImportMD5AnimBaseFrame( filenameAnim, model ) ) return NULL; if ( numJoints != model->bones.Num() ) { delete model; User::Error( ERR_FILE_CORRUPT, "Number of Joints do not match", filename ); return NULL; } return model; }
int yyFlexLexer::yylex() { LexerError( "yyFlexLexer::yylex invoked but %option yyclass used" ); return 0; }
/* ================ Lexer::ReadString ================ */ const char *Lexer::ReadString( void ) { if ( !ReadToken() ) throw LexerError( LexerError::END_OF_FILE ); return token.GetString(); }
/* ================ Lexer::ExpectToken ================ */ void Lexer::ExpectToken( const char *string ) { if ( !ReadToken() ) throw LexerError( LexerError::END_OF_FILE ); if ( String::Icmp( token.GetString(), string ) != 0 ) throw LexerError( LexerError::MISSING_TOKEN, token.line, string, token.GetString() ); }
/* ================ Lexer::Error ================ */ void Lexer::Error( const char *message ) { throw LexerError( LexerError::CUSTOM, token.line, message ); }
void yyerror(const char * msg) { LexerError(msg); }
/* ================ XDeclParser::Parse ================ */ void XDeclParser::Parse( Lexer &lexer ) { const Token *token; String name, value; XDeclNode *currentNode = &rootNode; XDeclNode *newNode; bool getKeyValue = false; bool addNode; Stack<XDeclNode *> nodeStack; const char *p; while ( (token = lexer.ReadToken()) != NULL ) { p = token->GetString(); if ( p ) { if ( *p == '\0' ) lexer.Error("Unexpected Empty Token"); if ( !getKeyValue ) { if ( String::Cmp( p, "}" ) == 0 ) { currentNode = nodeStack.Top(); nodeStack.Pop(); } else { name = p; addNode = false; if ( lexer.CheckToken("=") ) { currentNode->dict.Set( name.c_str(), lexer.ReadString() ); lexer.ExpectToken(";"); } else if ( lexer.CheckToken("(") ) { addNode = true; getKeyValue = true; } else if ( lexer.CheckToken("{") ) { addNode = true; } else { lexer.Error("Syntax Error, was expecting '(', '=' or '{'"); } if ( addNode ) { newNode = allocator.Alloc(); newNode->name = name; currentNode->numChildren++; if ( currentNode->firstChild == NULL ) currentNode->firstChild = newNode; else currentNode->lastChild->next = newNode; currentNode->lastChild= newNode; nodeStack.Push( currentNode ); currentNode = newNode; } } } else { name = p; lexer.ExpectToken("="); currentNode->dict.Set( name.c_str(), lexer.ReadString() ); if ( !lexer.CheckToken(",") ) { lexer.ExpectToken(")"); if ( lexer.CheckToken(";") ) { currentNode = nodeStack.Top(); nodeStack.Pop(); getKeyValue = false; } else if ( lexer.CheckToken("{") ) { getKeyValue = false; } else { lexer.Error("Syntax Error, was expecting ';' or '{'"); } } } } } if ( getKeyValue || nodeStack.Num() ) throw LexerError( LexerError::END_OF_FILE ); }