CVPParser Class Reference

#include <vertex_program_parse.h>


Detailed Description

A vertex program parser.
Author:
Nicolas Vizerie

Nevrax France

Date:
2002

Definition at line 191 of file vertex_program_parse.h.

Public Types

typedef std::vector< CVPInstructionTProgram

Public Member Functions

bool parse (const char *src, TProgram &result, std::string &errorOutput)

Static Public Member Functions

void dump (const TProgram &prg, std::string &dest)
bool isInputUsed (const TProgram &prg, CVPOperand::EInputRegister input)

Private Member Functions

bool parseAddressRegister (CVPOperand &operand, std::string &errorOutput)
bool parseConstantRegister (CVPOperand &operand, std::string &errorOutput)
bool parseInputRegister (CVPOperand &operand, std::string &errorOutput)
bool parseInstruction (CVPInstruction &instr, std::string &errorOutput, bool &endEncountered)
bool parseOp2 (CVPInstruction &instr, std::string &errorOutput)
bool parseOp3 (CVPInstruction &instr, std::string &errorOutput)
bool parseOp4 (CVPInstruction &instr, std::string &errorOutput)
bool parseOperand (CVPOperand &operand, bool outputOperand, std::string &errorOutput)
bool parseOutputRegister (CVPOperand &operand, std::string &errorOutput)
bool parseSwizzle (CVPSwizzle &swizzle, std::string &errorOutput)
bool parseVariableRegister (CVPOperand &operand, std::string &errorOutput)
bool parseWriteMask (uint &mask, std::string &errorOutput)
void skipSpacesAndComments ()

Private Attributes

const char * _CurrChar
uint _LineIndex
const char * _LineStart
uint _RegisterMask [96]


Member Typedef Documentation

typedef std::vector<CVPInstruction> CVPParser::TProgram
 

Definition at line 194 of file vertex_program_parse.h.

Referenced by NL3D::CDriverGL::activeEXTVertexShader(), NL3D::CDriverGL::activeNVVertexProgram(), dump(), NL3D::CMeshVPPerPixelLight::initInstance(), isInputUsed(), parse(), and NL3D::CDriverGL::setupEXTVertexShader().


Member Function Documentation

void CVPParser::dump const TProgram prg,
std::string &  dest
[static]
 

Debugging purpose : This output a parsed vertex program in a string, with the standard format. This can serve as a base for other format code generation

Definition at line 1110 of file vertex_program_parse.cpp.

References dumpInstr(), TProgram, and uint.

01111 {       
01112         dest = "!!VP1.0 \n";
01113         for(uint k = 0; k < prg.size(); ++k)
01114         {
01115                 std::string instr;
01116                 dumpInstr(prg[k], instr);
01117                 dest += instr;
01118         }
01119         dest +="END";
01120 }

bool CVPParser::isInputUsed const TProgram prg,
CVPOperand::EInputRegister  input
[static]
 

Definition at line 893 of file vertex_program_parse.cpp.

References src, TProgram, and uint.

Referenced by NL3D::CDriverGL::setupEXTVertexShader().

00894 {
00895         for(uint k = 0; k < prg.size(); ++k)
00896         {
00897                 uint numSrc = prg[k].getNumUsedSrc();
00898                 for(uint l = 0; l < numSrc; ++l)
00899                 {
00900                         const CVPOperand &src =  prg[k].getSrc(l);
00901                         if (src.Type == CVPOperand::InputRegister && src.Value.InputRegisterValue == input) return true;
00902                 }
00903         }
00904         return false;
00905 }

bool CVPParser::parse const char *  src,
TProgram result,
std::string &  errorOutput
 

Parse a vertex program, and convert to proprietary format. It is intended to be use by a driver implementation.

Warning:
: Only syntax is checked. It doesn't check that a register has been initialised before use.
Parameters:
src The input text of a vertex program, in OpenGL format.
result The result program.
errorOuput If parsing failed, contains the reason
Returns:
true if the parsing succeeded

Definition at line 921 of file vertex_program_parse.cpp.

References _CurrChar, _LineIndex, _LineStart, _RegisterMask, getStringUntilCR(), parseInstruction(), src, NLMISC::toString(), and TProgram.

Referenced by NL3D::CDriverGL::activeEXTVertexShader(), NL3D::CDriverGL::activeNVVertexProgram(), and NL3D::CMeshVPPerPixelLight::initInstance().

00922 {
00923         if (!src) return false; 
00924         //
00925         std::fill(_RegisterMask, _RegisterMask + 96, 0);
00926 
00927         //
00928         _CurrChar = src;
00929         _LineStart = src;
00930         _LineIndex = 1;
00931         //
00932         //skipSpacesAndComments(); // in fact space are not allowed at the start of the vertex program
00933 
00934         // parse version
00935         if (   _CurrChar[0] != '!' 
00936                 || _CurrChar[1] != '!'
00937                 || _CurrChar[2] != 'V'
00938                 || _CurrChar[3] != 'P'
00939                 || _CurrChar[4] != '1'
00940                 || _CurrChar[5] != '.'
00941                 || (_CurrChar[6] != '0' && _CurrChar[6] != '1'))
00942         {
00943                 errorOutput = "Can't parse version.";
00944                 return false;
00945         }
00946         _CurrChar += 7;
00947 
00948         errorOutput.clear();
00949         // parse instructions
00950         bool endEncoutered = false;
00951         
00952         std::string errorMess;
00953         for(;;)
00954         {
00955                 CVPInstruction instr;           
00956                 if (!parseInstruction(instr, errorMess, endEncoutered))
00957                 {
00958                         errorOutput = std::string("CVPParser::parse : Error encountered at line ") + NLMISC::toString(_LineIndex) + std::string(" : ") + errorMess + std::string(" Text : ") + getStringUntilCR(_LineStart);
00959                         return false;
00960                 }
00961                 if (endEncoutered) break;               
00962                 result.push_back(instr);
00963         }       
00964         return true;    
00965 }

bool CVPParser::parseAddressRegister CVPOperand operand,
std::string &  errorOutput
[private]
 

Definition at line 533 of file vertex_program_parse.cpp.

References _CurrChar, and CVPOperand::Type.

Referenced by parseOperand().

00534 {
00535         ++_CurrChar;
00536         operand.Type = CVPOperand::AddressRegister;
00537         if (_CurrChar[0] != '0' || _CurrChar[1] != '.' || _CurrChar[2] != 'x')
00538         {
00539                 errorOutput = "Can't parse address register.";
00540                 return false;
00541         }
00542         _CurrChar += 3;
00543         return true;    
00544 }

bool CVPParser::parseConstantRegister CVPOperand operand,
std::string &  errorOutput
[private]
 

Definition at line 442 of file vertex_program_parse.cpp.

References _CurrChar, index, CVPOperand::Indexed, parseUInt(), skipSpacesAndComments(), CVPOperand::Type, uint, and CVPOperand::Value.

Referenced by parseOperand().

00443 {
00444         ++_CurrChar;
00445         operand.Type = CVPOperand::Constant;    
00446         if (*_CurrChar != '[')
00447         {
00448                 errorOutput = "'[' expected when parsing a constant register.";
00449                 return false;
00450         }
00451         ++_CurrChar;
00452         skipSpacesAndComments();
00453         uint &index = operand.Value.ConstantValue;
00454         if (isdigit(*_CurrChar))
00455         {               
00456                 // immediat case : c[0] to c[95]
00457                 _CurrChar = parseUInt(_CurrChar, index);
00458                 if (index > 95)
00459                 {
00460                         errorOutput = "Constant register index must range from 0 to 95.";
00461                         return false;
00462                 }
00463                 operand.Indexed = false;
00464         }
00465         else if (*_CurrChar == 'A')
00466         {
00467                 // indexed case : c[A0.x + 0] to c[A0.x + 95]
00468                 operand.Indexed = true;
00469                 index = 0;
00470                 if (_CurrChar[1] == '0'
00471                         && _CurrChar[2] == '.'
00472                         && _CurrChar[3] == 'x')
00473                 {
00474                         _CurrChar += 4;
00475                         skipSpacesAndComments();
00476                         if (*_CurrChar == '+')
00477                         {
00478                                 ++ _CurrChar;
00479                                 skipSpacesAndComments();
00480                                 if (isdigit(*_CurrChar))
00481                                 {
00482                                         _CurrChar = parseUInt(_CurrChar, index);
00483                                         if (index > 95)
00484                                         {
00485                                                 errorOutput = "Constant register index must range from 0 to 95.";
00486                                                 return false;
00487                                         }
00488                                 }
00489                                 else
00490                                 {
00491                                         errorOutput = "Can't parse offset for constant register.";
00492                                         return false;
00493                                 }
00494                         }
00495                 }
00496                 else
00497                 {
00498                         errorOutput = "Can't parse constant register index.";
00499                         return false;
00500                 }
00501         }
00502         skipSpacesAndComments();
00503         if (*_CurrChar != ']')
00504         {
00505                 errorOutput = "']' expected when parsing an input register.";
00506                 return false;
00507         }
00508         ++_CurrChar;
00509         return true;
00510 }

bool CVPParser::parseInputRegister CVPOperand operand,
std::string &  errorOutput
[private]
 

Definition at line 224 of file vertex_program_parse.cpp.

References _CurrChar, index, skipSpacesAndComments(), CVPOperand::Type, uint, uint32, and CVPOperand::Value.

Referenced by parseOperand().

00225 {
00226         ++_CurrChar;
00227         operand.Type = CVPOperand::InputRegister;       
00228         if (*_CurrChar != '[')
00229         {
00230                 errorOutput = "'[' expected when parsing an input register.";
00231                 return false;
00232         }
00233         ++_CurrChar;
00234         skipSpacesAndComments();
00235         if (isdigit(*_CurrChar))
00236         {
00237                 // The input register is expressed as an index
00238                 uint index = *_CurrChar - '0';
00239                 ++_CurrChar;
00240                 if (isdigit(*_CurrChar))
00241                 {
00242                         index =  10 * index + (*_CurrChar - '0');
00243                         ++_CurrChar;
00244                 }
00245                 if (index > 15)
00246                 {               
00247                         errorOutput = "Invalid index for input register, must be in [0, 15].";
00248                         return false;
00249                 }
00250                 operand.Value.InputRegisterValue = (CVPOperand::EInputRegister) index;
00251         }
00252         else
00253         {
00254                 // The input register is expressed as a string
00255                 uint32 strValue = 0;
00256                 // read the 4 letters
00257                 for(uint k = 0; k < 4; ++k)
00258                 {
00259                         if (!isalnum(*_CurrChar))
00260                         {
00261                                 errorOutput = "Can't parse index for input register.";
00262                                 return false;
00263                         }
00264                         strValue |= ((uint32) *_CurrChar) << (8 * (3 - k));
00265                         ++_CurrChar;
00266                 }
00267                 switch (strValue)
00268                 {
00269                         case 'OPOS': operand.Value.InputRegisterValue = CVPOperand::IPosition; break;
00270                         case 'WGHT': operand.Value.InputRegisterValue = CVPOperand::IWeight; break;
00271                         case 'NRML': operand.Value.InputRegisterValue = CVPOperand::INormal; break;
00272                         case 'COL0': operand.Value.InputRegisterValue = CVPOperand::IPrimaryColor; break;
00273                         case 'COL1': operand.Value.InputRegisterValue = CVPOperand::ISecondaryColor; break;                     
00274                         case 'FOGC': operand.Value.InputRegisterValue = CVPOperand::IFogCoord; break;
00275                         // texture argument
00276                         case 'TEX0':
00277                         case 'TEX1':
00278                         case 'TEX2':
00279                         case 'TEX3':
00280                         case 'TEX4':
00281                         case 'TEX5':
00282                         case 'TEX6':
00283                         case 'TEX7':
00284                                 operand.Value.InputRegisterValue = (CVPOperand::EInputRegister) (CVPOperand::ITex0 + strValue & 0xff - '0'); 
00285                         break;
00286                         default:
00287                                 errorOutput = "Can't parse index for input register.";
00288                                 return false;
00289                 }               
00290         }
00291         skipSpacesAndComments();
00292         if (*_CurrChar != ']')
00293         {
00294                 errorOutput = "']' expected when parsing an input register.";
00295                 return false;
00296         }
00297         ++ _CurrChar;
00298         return true;
00299 }

bool CVPParser::parseInstruction CVPInstruction instr,
std::string &  errorOutput,
bool &  endEncountered
[private]
 

Definition at line 714 of file vertex_program_parse.cpp.

References _CurrChar, _RegisterMask, CVPInstruction::Dest, END, CVPSwizzle::isScalar(), CVPInstruction::LOG, LOG, CVPInstruction::Opcode, parseOp2(), parseOp3(), parseOp4(), skipSpacesAndComments(), CVPInstruction::Src1, CVPOperand::Swizzle, CVPOperand::Type, uint, uint32, CVPOperand::Value, and CVPOperand::WriteMask.

Referenced by parse().

00715 {
00716         skipSpacesAndComments();
00717         endEncountered = false;
00718         uint32 instrStr = 0;
00719         uint k;
00720         for(k = 0; k < 4; ++k)
00721         {
00722                 if (!isalnum(*_CurrChar))
00723                 {
00724                         if (k < 3) // at least 3 letter in an instruction
00725                         {
00726                                 errorOutput = "Syntax error : can't read opcode.";
00727                                 return false;
00728                         }
00729                         else break;                     
00730                 }
00731                 instrStr |= ((uint) *_CurrChar) << (8 * (3 - k));
00732                 ++ _CurrChar;
00733         }
00734         if (k != 4)
00735         {
00736                 instrStr |= (uint32) ' ';
00737         }
00738         switch (instrStr)
00739         {
00740                 case 'ARL ':
00741                         instr.Opcode = CVPInstruction::ARL;
00742                         if (!parseOp2(instr, errorOutput)) return false;
00743                         if (!instr.Src1.Swizzle.isScalar())
00744                         {
00745                                 errorOutput = "ARL need a scalar src value.";
00746                                 return false;
00747                         }
00748                 break;          
00749                 case 'RSQ ':
00750                         instr.Opcode = CVPInstruction::RSQ;
00751                         if (!parseOp2(instr, errorOutput)) return false;
00752                         if (!instr.Src1.Swizzle.isScalar())
00753                         {
00754                                 errorOutput = "RSQ need a scalar src value.";
00755                                 return false;
00756                         }
00757                 break;
00758                 case 'EXP ':
00759                 case 'EXPP':
00760                         instr.Opcode = CVPInstruction::EXPP;
00761                         if (!parseOp2(instr, errorOutput)) return false;
00762                         if (!instr.Src1.Swizzle.isScalar())
00763                         {
00764                                 errorOutput = "EXP need a scalar src value.";
00765                                 return false;
00766                         }
00767                         /*
00768                         if (instr.Src1.Swizzle.Comp[0] != CVPSwizzle.W)
00769                         {
00770                                 errorOutput = "EXPP input scalar must be w";
00771                                 return false;
00772                         }*/
00773                 break;
00774                 case 'LOG ':
00775                         instr.Opcode = CVPInstruction::LOG;
00776                         if (!parseOp2(instr, errorOutput)) return false;
00777                         if (!instr.Src1.Swizzle.isScalar())
00778                         {
00779                                 errorOutput = "LOG need a scalar src value.";
00780                                 return false;
00781                         }
00782                         /*
00783                         if (instr.Src1.Swizzle.Comp[0] != CVPSwizzle.W)
00784                         {
00785                                 errorOutput = "LOG input scalar must be w";
00786                                 return false;
00787                         }
00788                         */
00789                 break;
00790                 case 'RCP ':
00791                         instr.Opcode = CVPInstruction::RCP;
00792                         if (!parseOp2(instr, errorOutput)) return false;
00793                         if (!instr.Src1.Swizzle.isScalar())
00794                         {
00795                                 errorOutput = "RCP need a scalar src value.";
00796                                 return false;
00797                         }
00798                 break;
00800                 case 'MOV ':
00801                         instr.Opcode = CVPInstruction::MOV;
00802                         if (!parseOp2(instr, errorOutput)) return false;
00803                         
00804                 break;
00805                 case 'LIT ':
00806                         instr.Opcode = CVPInstruction::LIT;
00807                         if (!parseOp2(instr, errorOutput)) return false;
00808                 break;          
00810                 case 'MAD ':
00811                         instr.Opcode = CVPInstruction::MAD;
00812                         if (!parseOp4(instr, errorOutput)) return false;
00813                 break;
00815                 case 'ADD ':
00816                         instr.Opcode = CVPInstruction::ADD;
00817                         if (!parseOp3(instr, errorOutput)) return false;
00818                 break;
00820                 case 'MUL ':
00821                         instr.Opcode = CVPInstruction::MUL;
00822                         if (!parseOp3(instr, errorOutput)) return false;
00823                 break;                          
00824                 case 'DP3 ':
00825                         instr.Opcode = CVPInstruction::DP3;
00826                         if (!parseOp3(instr, errorOutput)) return false;
00827                 break;
00828                 case 'DP4 ':
00829                         instr.Opcode = CVPInstruction::DP4;
00830                         if (!parseOp3(instr, errorOutput)) return false;
00831                 break;
00832                 case 'DST ':
00833                         instr.Opcode = CVPInstruction::DST;
00834                         if (!parseOp3(instr, errorOutput)) return false;
00835                 break;          
00836                 case 'MIN ':
00837                         instr.Opcode = CVPInstruction::MIN;
00838                         if (!parseOp3(instr, errorOutput)) return false;
00839                 break;
00840                 case 'MAX ':
00841                         instr.Opcode = CVPInstruction::MAX;
00842                         if (!parseOp3(instr, errorOutput)) return false;
00843                 break;
00844                 case 'SLT ':
00845                         instr.Opcode = CVPInstruction::SLT;
00846                         if (!parseOp3(instr, errorOutput)) return false;
00847                 break;
00848                 case 'SGE ':
00849                         instr.Opcode = CVPInstruction::SGE;
00850                         if (!parseOp3(instr, errorOutput)) return false;
00851                 break;
00853                 case 'END ':
00854                         endEncountered = true;
00855                         return true;
00856                 break;
00857                 default:
00858                         errorOutput = "Syntax error : unknow opcode.";
00859                         return false;
00860                 break;
00861         }
00862 
00863 
00864         if (instr.Dest.Type == CVPOperand::Variable)
00865         {
00866                 _RegisterMask[instr.Dest.Value.VariableValue] |= instr.Dest.WriteMask;
00867         }
00868 
00869         // it is not allowed to write to an adress register except for ARL
00870         if (instrStr != 'ARL ')
00871         {
00872                 if (instr.Dest.Type == CVPOperand::AddressRegister)
00873                 {
00874                         errorOutput = "Can't write to address register.";
00875                         return false;
00876                 }
00877         }
00878 
00879         // parse semi-colon
00880         skipSpacesAndComments();
00881         //
00882         if (*_CurrChar != ';')
00883         {
00884                 errorOutput = "';' expected.";
00885                 return false;
00886         }
00887         ++_CurrChar;
00888         return true;
00889 }

bool CVPParser::parseOp2 CVPInstruction instr,
std::string &  errorOutput
[private]
 

Definition at line 547 of file vertex_program_parse.cpp.

References _CurrChar, CVPInstruction::Dest, parseOperand(), skipSpacesAndComments(), CVPInstruction::Src1, and CVPOperand::Type.

Referenced by parseInstruction(), and parseOp3().

00548 {
00549         skipSpacesAndComments();
00550         // parse ouput
00551         if (!parseOperand(instr.Dest, true, errorOutput)) return false;
00552         // Can't write in input or consant register
00553         if (instr.Dest.Type == CVPOperand::Constant || instr.Dest.Type == CVPOperand::InputRegister)
00554         {
00555                 errorOutput = "Can't write to a constant or input register";
00556                 return false;
00557         }
00558         //
00559         skipSpacesAndComments();
00560         if (*_CurrChar != ',')
00561         {
00562                 errorOutput = "',' expected.";
00563                 return false;
00564         }
00565         ++_CurrChar;
00566         skipSpacesAndComments();
00567         // parse src1
00568         if (!parseOperand(instr.Src1, false, errorOutput)) return false;
00569         if (instr.Src1.Type == CVPOperand::AddressRegister 
00570                 || instr.Src1.Type == CVPOperand::OutputRegister)
00571         {
00572                 errorOutput = "Src1 must be constant, variable, or input register.";
00573                 return false;
00574         }
00575         return true;
00576 }

bool CVPParser::parseOp3 CVPInstruction instr,
std::string &  errorOutput
[private]
 

Definition at line 579 of file vertex_program_parse.cpp.

References _CurrChar, CVPOperand::Indexed, parseOp2(), parseOperand(), skipSpacesAndComments(), CVPInstruction::Src1, CVPInstruction::Src2, CVPOperand::Type, and CVPOperand::Value.

Referenced by parseInstruction(), and parseOp4().

00580 {       
00581         if (!parseOp2(instr, errorOutput)) return false;
00582         skipSpacesAndComments();
00583         if (*_CurrChar != ',')
00584         {
00585                 errorOutput = "',' expected.";
00586                 return false;
00587         }
00588         ++_CurrChar;
00589         skipSpacesAndComments();
00590         // parse src2
00591         if (!parseOperand(instr.Src2, false, errorOutput)) return false;
00592         if (instr.Src2.Type == CVPOperand::AddressRegister 
00593                 || instr.Src2.Type == CVPOperand::OutputRegister)
00594         {
00595                 errorOutput = "Src2 must be constant, variable, or input register.";
00596                 return false;
00597         }
00598         // make sure we do not have 2 =/= contant register as src (or in put register)
00599 
00600         // 2 constant registers ?
00601         if (instr.Src1.Type == CVPOperand::Constant
00602                 && instr.Src2.Type == CVPOperand::Constant)
00603         {
00604                 // the index must be the same
00605                 if (!
00606                         (
00607                                 instr.Src1.Indexed == instr.Src2.Indexed
00608                          && instr.Src1.Value.ConstantValue == instr.Src2.Value.ConstantValue
00609                         )
00610                    )
00611                 {
00612                         errorOutput = "Can't read 2 different constant registers in a single instruction.";
00613                         return false;
00614                 }                       
00615         }
00616 
00617         // 2 input registers ?
00618         if (instr.Src1.Type == CVPOperand::InputRegister
00619                 && instr.Src2.Type == CVPOperand::InputRegister)
00620         {
00621                 // the index must be the same
00622                 if (instr.Src1.Value.InputRegisterValue != instr.Src2.Value.InputRegisterValue)
00623                 {
00624                         errorOutput = "Can't read 2 different input registers in a single instruction.";
00625                         return false;
00626                 }                       
00627         }
00628         return true;
00629 }

bool CVPParser::parseOp4 CVPInstruction instr,
std::string &  errorOutput
[private]
 

Definition at line 632 of file vertex_program_parse.cpp.

References _CurrChar, CVPOperand::Indexed, parseOp3(), parseOperand(), skipSpacesAndComments(), CVPInstruction::Src1, CVPInstruction::Src2, CVPInstruction::Src3, CVPOperand::Type, and CVPOperand::Value.

Referenced by parseInstruction().

00633 {
00634         if (!parseOp3(instr, errorOutput)) return false;
00635         // parse src 3
00636         skipSpacesAndComments();
00637         if (*_CurrChar != ',')
00638         {
00639                 errorOutput = "',' expected.";
00640                 return false;
00641         }
00642         ++_CurrChar;
00643         skipSpacesAndComments();
00644         // parse src4
00645         if (!parseOperand(instr.Src3, false, errorOutput)) return false;
00646         if (instr.Src3.Type == CVPOperand::AddressRegister 
00647                 || instr.Src3.Type == CVPOperand::OutputRegister)
00648         {
00649                 errorOutput = "Src3 must be constant, variable, or input register.";
00650                 return false;
00651         }
00652         
00654         // check for different contant / input registers //
00656 
00657         // Duplicated constant register
00658         if (instr.Src3.Type == CVPOperand::Constant)
00659         {
00660                 if (instr.Src1.Type == CVPOperand::Constant)
00661                 {
00662                         if (!
00663                             (
00664                                     instr.Src1.Indexed == instr.Src3.Indexed
00665                              && instr.Src1.Value.ConstantValue == instr.Src3.Value.ConstantValue
00666                             )
00667                        )
00668                         {
00669                                 errorOutput = "Can't read 2 different constant registers in a single instruction.";
00670                                 return false;
00671                         }
00672                 }
00673                 if (instr.Src2.Type == CVPOperand::Constant)
00674                 {
00675                         if (!
00676                             (
00677                                     instr.Src2.Indexed == instr.Src3.Indexed
00678                              && instr.Src2.Value.ConstantValue == instr.Src3.Value.ConstantValue
00679                             )
00680                        )
00681                         {
00682                                 errorOutput = "Can't read 2 different constant registers in a single instruction.";
00683                                 return false;
00684                         }
00685                 }
00686         }
00687 
00688         // Duplicated input register
00689         if (instr.Src3.Type == CVPOperand::InputRegister)
00690         {
00691                 if (instr.Src1.Type == CVPOperand::InputRegister)
00692                 {                       
00693                         if (instr.Src1.Value.InputRegisterValue != instr.Src3.Value.InputRegisterValue)
00694                         {
00695                                 errorOutput = "Can't read 2 different input registers in a single instruction.";
00696                                 return false;
00697                         }
00698                 }
00699                 if (instr.Src2.Type == CVPOperand::InputRegister)
00700                 {
00701                         if (instr.Src2.Value.InputRegisterValue != instr.Src3.Value.InputRegisterValue)
00702                         {
00703                                 errorOutput = "Can't read 2 different input registers in a single instruction.";
00704                                 return false;
00705                         }
00706                 }
00707         }
00708 
00709 
00710         return true;
00711 }

bool CVPParser::parseOperand CVPOperand operand,
bool  outputOperand,
std::string &  errorOutput
[private]
 

Definition at line 142 of file vertex_program_parse.cpp.

References _CurrChar, _RegisterMask, CVPSwizzle::Comp, CVPOperand::Negate, parseAddressRegister(), parseConstantRegister(), parseInputRegister(), parseOutputRegister(), parseSwizzle(), parseVariableRegister(), parseWriteMask(), skipSpacesAndComments(), CVPOperand::Swizzle, CVPOperand::Type, uint, CVPOperand::Value, and CVPOperand::WriteMask.

Referenced by parseOp2(), parseOp3(), and parseOp4().

00143 {
00144         skipSpacesAndComments();
00145         bool result;
00146         if (outputOperand)
00147         {
00148                 operand.Negate = false;
00149                 switch(*_CurrChar)
00150                 {                       
00151                         case 'o': result = parseOutputRegister(operand, errorOutput); break;
00152                         case 'R': 
00153                                 result = parseVariableRegister(operand, errorOutput);                                                   
00154                         break;
00155                         case 'A': result = parseAddressRegister(operand, errorOutput); break;
00156                         case '-':
00157                                 errorOutput = "Negation not allowed on ouput register.";
00158                                 return false;
00159                         default:
00160                                 errorOutput = "Output, Address, or Temporary register expected as an output operand.";
00161                                 return false;                   
00162                 }
00163                 if (!result) return false;
00164 
00165                 // parse the write mask
00166                 return parseWriteMask(operand.WriteMask, errorOutput);                          
00167         }
00168         else
00169         {
00170                 operand.Negate = false;
00171                 switch(*_CurrChar)
00172                 {
00173                         case 'v': result = parseInputRegister(operand, errorOutput); break;
00174                         case 'R': result = parseVariableRegister(operand, errorOutput); break;
00175                         case 'c': result = parseConstantRegister(operand, errorOutput); break;
00176                         case 'a': result = parseAddressRegister(operand, errorOutput); break;
00177                         case '-':
00178                         {
00179                                 operand.Negate = true;
00180                                 // negation
00181                                 ++ _CurrChar;
00182                                 skipSpacesAndComments();
00183                                 switch(*_CurrChar)
00184                                 {
00185                                         case 'v': result = parseInputRegister(operand, errorOutput); break;
00186                                         case 'R': result = parseVariableRegister(operand, errorOutput); break;
00187                                         case 'c': result = parseConstantRegister(operand, errorOutput); break;
00188                                         default:
00189                                                 errorOutput = "Negation must be followed by an input register, a variable register, or a constant.";
00190                                                 return false;
00191                                         break;
00192                                 }
00193                         }
00194                         break;
00195                         default:
00196                                 errorOutput = "Syntax error.";
00197                                 return false;
00198                         break;
00199                 }
00200                 if (!result) return false;              
00201                 if (operand.Type != CVPOperand::AddressRegister)
00202                 {
00203                         if (!parseSwizzle(operand.Swizzle, errorOutput)) return false;          
00204                         if (operand.Type == CVPOperand::Variable)
00205                         {
00206                                 for(uint k = 0; k < 4; ++k)
00207                                 {
00208                                         if (!(_RegisterMask[operand.Value.VariableValue] & (1 << operand.Swizzle.Comp[k])))
00209                                         {
00210                                                 errorOutput = "Can't read a register component before writing to it.";
00211                                                 return false;
00212                                         }
00213                                 }
00214                         }
00215                 }
00216                 return true;
00217         }
00218 
00219         
00220 }

bool CVPParser::parseOutputRegister CVPOperand operand,
std::string &  errorOutput
[private]
 

Definition at line 370 of file vertex_program_parse.cpp.

References _CurrChar, skipSpacesAndComments(), CVPOperand::Type, uint, uint32, and CVPOperand::Value.

Referenced by parseOperand().

00371 {       
00372         ++_CurrChar;
00373         operand.Type = CVPOperand::OutputRegister;      
00374         if (*_CurrChar != '[')
00375         {
00376                 errorOutput = "'[' expected when parsing an ouput register.";
00377                 return false;
00378         }
00379         ++_CurrChar;
00380         skipSpacesAndComments();
00381         // The input register is expressed as a string
00382         uint32 strValue = 0;
00383         // read the 4 letters
00384         for(uint k = 0; k < 4; ++k)
00385         {
00386                 if (!isalnum(*_CurrChar))
00387                 {
00388                         errorOutput = "Can't parse index for output register.";
00389                         return false;
00390                 }
00391                 strValue |= ((uint32) *_CurrChar) << (8 * (3 - k));
00392                 ++_CurrChar;
00393         }
00394         // convert to enum
00395         switch(strValue)
00396         {
00397                 case 'HPOS': operand.Value.OutputRegisterValue = CVPOperand::OHPosition; break;
00398                 case 'COL0': operand.Value.OutputRegisterValue = CVPOperand::OPrimaryColor; break;
00399                 case 'COL1': operand.Value.OutputRegisterValue = CVPOperand::OSecondaryColor; break;
00400                 case 'BFC0': operand.Value.OutputRegisterValue = CVPOperand::OBackFacePrimaryColor; break;
00401                 case 'BFC1': operand.Value.OutputRegisterValue = CVPOperand::OBackFaceSecondaryColor; break;
00402                 case 'FOGC': operand.Value.OutputRegisterValue = CVPOperand::OFogCoord; break;
00403                 case 'PSIZ': operand.Value.OutputRegisterValue = CVPOperand::OPointSize; break;
00404                 case 'TEX0': operand.Value.OutputRegisterValue = CVPOperand::OTex0; break;
00405                 case 'TEX1': operand.Value.OutputRegisterValue = CVPOperand::OTex1; break;
00406                 case 'TEX2': operand.Value.OutputRegisterValue = CVPOperand::OTex2; break;
00407                 case 'TEX3': operand.Value.OutputRegisterValue = CVPOperand::OTex3; break;
00408                 case 'TEX4': operand.Value.OutputRegisterValue = CVPOperand::OTex4; break;
00409                 case 'TEX5': operand.Value.OutputRegisterValue = CVPOperand::OTex5; break;
00410                 case 'TEX6': operand.Value.OutputRegisterValue = CVPOperand::OTex6; break;
00411                 case 'TEX7': operand.Value.OutputRegisterValue = CVPOperand::OTex7; break;
00412                 default:
00413                         errorOutput = "Can't read index for output register.";
00414                         return false;
00415                 break;
00416         }
00417         skipSpacesAndComments();
00418         if (*_CurrChar != ']')
00419         {
00420                 errorOutput = "']' expected when parsing an output register.";
00421                 return false;
00422         }
00423         ++_CurrChar;
00424         return true;
00425 }

bool CVPParser::parseSwizzle CVPSwizzle swizzle,
std::string &  errorOutput
[private]
 

Definition at line 315 of file vertex_program_parse.cpp.

References _CurrChar, CVPSwizzle::Comp, letterToSwizzleComp(), and uint.

Referenced by parseOperand().

00316 {
00317         if (*_CurrChar != '.')
00318         {
00319                 // no swizzle
00320                 swizzle.Comp[0] = CVPSwizzle::X;        
00321                 swizzle.Comp[1] = CVPSwizzle::Y;
00322                 swizzle.Comp[2] = CVPSwizzle::Z;
00323                 swizzle.Comp[3] = CVPSwizzle::W;
00324                 return true;
00325         }       
00326         ++_CurrChar;
00327         // 4 letters case
00328         for(uint k = 0; k < 4; ++k)
00329         {
00330                 if (!isalpha(*_CurrChar))
00331                 {
00332                         if (k == 1) // 1 letter case
00333                         {
00334                                 switch(*_CurrChar)
00335                                 {
00336                                         case ',':
00337                                         case ';':
00338                                         case ' ':
00339                                         case '\t':
00340                                         case '\r':
00341                                         case '\n':
00342                                         case '#':
00343                                                 swizzle.Comp[1] = swizzle.Comp[2] = swizzle.Comp[3] = swizzle.Comp[0];
00344                                                 return true;
00345                                         break;
00346                                         default:
00347                                                 errorOutput = "Can't parse swizzle.";
00348 
00349                                 }
00350                         }
00351                         else
00352                         {
00353                                 errorOutput = "Invalid swizzle value.";
00354                                 return false;
00355                         }                       
00356                 }
00357                 
00358                 if (!letterToSwizzleComp(*_CurrChar, swizzle.Comp[k]))
00359                 {       
00360                         errorOutput = "Invalid swizzle value.";
00361                         return false;
00362                 }
00363                 ++ _CurrChar;
00364         }
00365         
00366         return true;
00367 }

bool CVPParser::parseVariableRegister CVPOperand operand,
std::string &  errorOutput
[private]
 

Definition at line 513 of file vertex_program_parse.cpp.

References _CurrChar, index, parseUInt(), CVPOperand::Type, uint, and CVPOperand::Value.

Referenced by parseOperand().

00514 {
00515         ++_CurrChar;
00516         operand.Type = CVPOperand::Variable;    
00517         if (!isdigit(*_CurrChar))
00518         {
00519                 errorOutput = "Can't parse variable register.";
00520                 return false;
00521         }
00522         uint &index = operand.Value.VariableValue;
00523         _CurrChar = parseUInt(_CurrChar, index);
00524         if (index > 11)
00525         {
00526                 errorOutput = "Variable register index must range from 0 to 11.";
00527                 return false;
00528         }
00529         return true;
00530 }

bool CVPParser::parseWriteMask uint mask,
std::string &  errorOutput
[private]
 

Definition at line 31 of file vertex_program_parse.cpp.

References _CurrChar, and uint.

Referenced by parseOperand().

00032 {       
00033         // parse output mask
00034         if (*_CurrChar != '.')
00035         {
00036                 // no output masks
00037                 mask = 0xf; //output 4 coordinates
00038                 return true;
00039         }
00040         else
00041         {
00042                 ++ _CurrChar;
00043                 mask = 0;
00044                 for(uint k = 0; k < 4; ++k)
00045                 {
00046                         uint maskIndex;
00047                         switch(*_CurrChar)
00048                         {
00049                                 case 'x': maskIndex = 0; break;
00050                                 case 'y': maskIndex = 1; break;
00051                                 case 'z': maskIndex = 2; break;
00052                                 case 'w': maskIndex = 3; break;
00053                                 default:
00054                                         if (k >= 1) return true;
00055                                         else
00056                                         {                                       
00057                                                 errorOutput = "Can't parse output mask.";
00058                                                 return false;
00059                                         }
00060                                 break;
00061                         }
00062                         ++_CurrChar;
00063                         if (mask & (1 << maskIndex))
00064                         {
00065                                 errorOutput = "Duplicated output mask component.";
00066                                 return false;
00067                         }
00068                         mask |= 1 << maskIndex;
00069                 }
00070                 return true;
00071         }
00072 }

void CVPParser::skipSpacesAndComments  )  [private]
 

Skip tabulation and space in a source code

Definition at line 77 of file vertex_program_parse.cpp.

References _CurrChar, _LineIndex, and _LineStart.

Referenced by parseConstantRegister(), parseInputRegister(), parseInstruction(), parseOp2(), parseOp3(), parseOp4(), parseOperand(), and parseOutputRegister().

00078 {
00079         bool stop = false;
00080         do
00081         {       
00082                 switch(*_CurrChar)
00083                 {
00084                         case '\t':
00085                         case '\r':
00086                         case ' ' : 
00087                                 ++_CurrChar; 
00088                         break;
00089                         //
00090                         case '\n': 
00091                                 ++_CurrChar; 
00092                                 ++_LineIndex; 
00093                                 _LineStart = _CurrChar;
00094                         break;
00095                         case '#': // comment go till end of line
00096                                 while (*_CurrChar != '\n' && *_CurrChar != '\0') ++_CurrChar;
00097                                 skipSpacesAndComments();
00098                         break;
00099                         default:
00100                                 stop = true;
00101                         break;                  
00102                 }
00103         }
00104         while (!stop);
00105 }


Field Documentation

const char* CVPParser::_CurrChar [private]
 

Definition at line 216 of file vertex_program_parse.h.

Referenced by parse(), parseAddressRegister(), parseConstantRegister(), parseInputRegister(), parseInstruction(), parseOp2(), parseOp3(), parseOp4(), parseOperand(), parseOutputRegister(), parseSwizzle(), parseVariableRegister(), parseWriteMask(), and skipSpacesAndComments().

uint CVPParser::_LineIndex [private]
 

Definition at line 218 of file vertex_program_parse.h.

Referenced by parse(), and skipSpacesAndComments().

const char* CVPParser::_LineStart [private]
 

Definition at line 217 of file vertex_program_parse.h.

Referenced by parse(), and skipSpacesAndComments().

uint CVPParser::_RegisterMask[96] [private]
 

Definition at line 219 of file vertex_program_parse.h.

Referenced by parse(), parseInstruction(), and parseOperand().


The documentation for this class was generated from the following files:
Generated on Tue Mar 16 06:43:56 2004 for NeL by doxygen 1.3.6