nsresult nsSVGPathDataParser::MatchSubPathElements() { ENSURE_MATCHED(MatchSubPathElement()); while (1) { const char* pos = mTokenPos; while (IsTokenWspStarter()) { ENSURE_MATCHED(MatchWsp()); } if (IsTokenSubPathElementStarter()) { ENSURE_MATCHED(MatchSubPathElement()); } else { if (pos != mTokenPos) RewindTo(pos); return NS_OK; } } return NS_OK; }
asCScriptNode *asCParser::ParseTypeMod(bool isParam) { asCScriptNode *node = new asCScriptNode(snDataType); sToken t; // Parse possibly byref token GetToken(&t); RewindTo(&t); if( t.type == ttAmp ) { node->AddChildLast(ParseToken(ttAmp)); if( isSyntaxError ) return node; if( isParam ) { int tokens[3] = {ttIn, ttOut, ttInOut}; node->AddChildLast(ParseOneOf(tokens, 3)); } } return node; }
asCScriptNode *asCParser::ParseReturn() { asCScriptNode *node = new asCScriptNode(snReturn); sToken t; GetToken(&t); if( t.type != ttReturn ) { Error(ExpectedToken("return").AddressOf(), &t); return node; } node->UpdateSourcePos(t.pos, t.length); GetToken(&t); if( t.type == ttEndStatement ) { node->UpdateSourcePos(t.pos, t.length); return node; } RewindTo(&t); node->AddChildLast(ParseAssignment()); if( isSyntaxError ) return node; GetToken(&t); if( t.type != ttEndStatement ) { Error(ExpectedToken(";").AddressOf(), &t); return node; } node->UpdateSourcePos(t.pos, t.length); return node; }
asCScriptNode *asCParser::ParseExpression() { asCScriptNode *node = new asCScriptNode(snExpression); node->AddChildLast(ParseExprTerm()); if( isSyntaxError ) return node; for(;;) { sToken t; GetToken(&t); RewindTo(&t); if( !IsOperator(t.type) ) return node; node->AddChildLast(ParseExprOperator()); if( isSyntaxError ) return node; node->AddChildLast(ParseExprTerm()); if( isSyntaxError ) return node; } return 0; }
nsresult nsSVGPathDataParser::MatchMovetoArgSeq(PRBool absCoords) { float x, y; ENSURE_MATCHED(MatchCoordPair(&x, &y)); nsresult rv = StoreMoveTo(absCoords, x, y); NS_ENSURE_SUCCESS(rv, rv); const char* pos = mTokenPos; if (IsTokenCommaWspStarter()) { ENSURE_MATCHED(MatchCommaWsp()); } if (IsTokenLinetoArgSeqStarter()) { ENSURE_MATCHED(MatchLinetoArgSeq(absCoords)); } else { if (pos != mTokenPos) RewindTo(pos); } return NS_OK; }
asCScriptNode *asCParser::ParseExprValue() { asCScriptNode *node = new asCScriptNode(snExprValue); sToken t1; GetToken(&t1); RewindTo(&t1); if( t1.type == ttIdentifier || IsRealType(t1.type) ) { if( IsFunctionCall() ) node->AddChildLast(ParseFunctionCall()); else node->AddChildLast(ParseIdentifier()); } else if( IsConstant(t1.type) ) node->AddChildLast(ParseConstant()); else if( t1.type == ttOpenParanthesis ) { GetToken(&t1); node->UpdateSourcePos(t1.pos, t1.length); node->AddChildLast(ParseAssignment()); if( isSyntaxError ) return node; GetToken(&t1); if( t1.type != ttCloseParanthesis ) Error(ExpectedToken(")"), &t1); node->UpdateSourcePos(t1.pos, t1.length); } else Error(TXT_EXPECTED_EXPRESSION_VALUE, &t1); return node; }
asCScriptNode *asCParser::ParseParameterList() { asCScriptNode *node = new asCScriptNode(snParameterList); sToken t1; GetToken(&t1); if( t1.type != ttOpenParanthesis ) { Error(ExpectedToken("(").AddressOf(), &t1); return node; } node->UpdateSourcePos(t1.pos, t1.length); GetToken(&t1); if( t1.type == ttCloseParanthesis ) { node->UpdateSourcePos(t1.pos, t1.length); // Statement block is finished return node; } else { RewindTo(&t1); for(;;) { // Parse data type node->AddChildLast(ParseType(true)); if( isSyntaxError ) return node; node->AddChildLast(ParseTypeMod(true)); if( isSyntaxError ) return node; // Parse identifier GetToken(&t1); if( t1.type == ttIdentifier ) { RewindTo(&t1); node->AddChildLast(ParseIdentifier()); if( isSyntaxError ) return node; GetToken(&t1); } // Check if list continues if( t1.type == ttCloseParanthesis ) { node->UpdateSourcePos(t1.pos, t1.length); return node; } else if( t1.type == ttListSeparator ) continue; else { Error(ExpectedTokens(")", ",").AddressOf(), &t1); return node; } } } return 0; }
asCScriptNode *asCParser::ParseClass() { asCScriptNode *node = new asCScriptNode(snClass); sToken t; GetToken(&t); if( t.type != ttClass ) { Error(ExpectedToken("class").AddressOf(), &t); return node; } node->SetToken(&t); node->AddChildLast(ParseIdentifier()); GetToken(&t); // Optional list of interfaces that are being implemented and classes that are being inherited if( t.type == ttColon ) { node->AddChildLast(ParseIdentifier()); GetToken(&t); while( t.type == ttListSeparator ) { node->AddChildLast(ParseIdentifier()); GetToken(&t); } } if( t.type != ttStartStatementBlock ) { Error(ExpectedToken("{").AddressOf(), &t); return node; } // Parse properties GetToken(&t); RewindTo(&t); while( t.type != ttEndStatementBlock && t.type != ttEnd ) { // Is it a property or a method? if( IsFuncDecl(true) ) { // Parse the method node->AddChildLast(ParseFunction(true)); } else if( IsVarDecl() ) { // Parse a property declaration asCScriptNode *prop = new asCScriptNode(snDeclaration); node->AddChildLast(prop); prop->AddChildLast(ParseType(true)); if( isSyntaxError ) return node; prop->AddChildLast(ParseIdentifier()); if( isSyntaxError ) return node; GetToken(&t); if( t.type != ttEndStatement ) { Error(ExpectedToken(";").AddressOf(), &t); return node; } prop->UpdateSourcePos(t.pos, t.length); } else { Error(TXT_EXPECTED_METHOD_OR_PROPERTY, &t); return node; } GetToken(&t); RewindTo(&t); } GetToken(&t); if( t.type != ttEndStatementBlock ) { Error(ExpectedToken("}").AddressOf(), &t); return node; } node->UpdateSourcePos(t.pos, t.length); return node; }
bool asCParser::IsFuncDecl(bool isMethod) { // Set start point so that we can rewind sToken t; GetToken(&t); RewindTo(&t); // A class constructor can start with identifier followed by parenthesis if( isMethod ) { sToken t1, t2; GetToken(&t1); GetToken(&t2); RewindTo(&t); if( t1.type == ttIdentifier && t2.type == ttOpenParanthesis ) return true; } // A function decl can start with a const sToken t1; GetToken(&t1); if( t1.type == ttConst ) GetToken(&t1); if( !IsDataType(t1.type) ) { RewindTo(&t); return false; } // Object handles can be interleaved with the array brackets sToken t2; GetToken(&t2); while( t2.type == ttHandle || t2.type == ttOpenBracket ) { if( t2.type == ttOpenBracket ) { GetToken(&t2); if( t2.type != ttCloseBracket ) { RewindTo(&t); return false; } } GetToken(&t2); } if( t2.type != ttIdentifier ) { RewindTo(&t); return false; } GetToken(&t2); if( t2.type == ttOpenParanthesis ) { // If the closing paranthesis is not followed by a // statement block then it is not a function. while( t2.type != ttCloseParanthesis && t2.type != ttEnd ) GetToken(&t2); if( t2.type == ttEnd ) return false; else { GetToken(&t1); RewindTo(&t); if( t1.type == ttStartStatementBlock ) return true; } RewindTo(&t); return false; } RewindTo(&t); return false; }
bool asCParser::IsVarDecl() { // Set start point so that we can rewind sToken t; GetToken(&t); RewindTo(&t); // A variable decl can start with a const sToken t1; GetToken(&t1); if( t1.type == ttConst ) GetToken(&t1); if( !IsDataType(t1.type) ) { RewindTo(&t); return false; } // Object handles can be interleaved with the array brackets sToken t2; GetToken(&t2); while( t2.type == ttHandle || t2.type == ttOpenBracket ) { if( t2.type == ttOpenBracket ) { GetToken(&t2); if( t2.type != ttCloseBracket ) { RewindTo(&t); return false; } } GetToken(&t2); } if( t2.type != ttIdentifier ) { RewindTo(&t); return false; } GetToken(&t2); if( t2.type == ttEndStatement || t2.type == ttAssignment || t2.type == ttListSeparator ) { RewindTo(&t); return true; } if( t2.type == ttOpenParanthesis ) { // If the closing paranthesis is followed by a statement // block or end-of-file, then treat it as a function. while( t2.type != ttCloseParanthesis && t2.type != ttEnd ) GetToken(&t2); if( t2.type == ttEnd ) return false; else { GetToken(&t1); RewindTo(&t); if( t1.type == ttStartStatementBlock || t1.type == ttEnd ) return false; } RewindTo(&t); return true; } RewindTo(&t); return false; }
asCScriptNode *asCParser::ParseScript() { asCScriptNode *node = new asCScriptNode(snScript); // Determine type of node sToken t1; for(;;) { while( !isSyntaxError ) { GetToken(&t1); RewindTo(&t1); if( t1.type == ttImport ) node->AddChildLast(ParseImport()); else if( t1.type == ttClass ) node->AddChildLast(ParseClass()); else if( t1.type == ttInterface ) node->AddChildLast(ParseInterface()); else if( t1.type == ttConst ) node->AddChildLast(ParseGlobalVar()); else if( IsDataType(t1.type) ) { if( IsVarDecl() ) node->AddChildLast(ParseGlobalVar()); else node->AddChildLast(ParseFunction()); } else if( t1.type == ttEndStatement ) { // Ignore a semicolon by itself GetToken(&t1); } else if( t1.type == ttEnd ) return node; else { asCString str; const char *t = asGetTokenDefinition(t1.type); if( t == 0 ) t = "<unknown token>"; str.Format(TXT_UNEXPECTED_TOKEN_s, t); Error(str.AddressOf(), &t1); } } if( isSyntaxError ) { // Search for either ';' or '{' or end GetToken(&t1); while( t1.type != ttEndStatement && t1.type != ttEnd && t1.type != ttStartStatementBlock ) GetToken(&t1); if( t1.type == ttStartStatementBlock ) { // Find the end of the block and skip nested blocks int level = 1; while( level > 0 ) { GetToken(&t1); if( t1.type == ttStartStatementBlock ) level++; if( t1.type == ttEndStatementBlock ) level--; if( t1.type == ttEnd ) break; } } isSyntaxError = false; } } return 0; }
asCScriptNode *asCParser::ParseSwitch() { asCScriptNode *node = new asCScriptNode(snSwitch); sToken t; GetToken(&t); if( t.type != ttSwitch ) { Error(ExpectedToken("switch").AddressOf(), &t); return node; } node->UpdateSourcePos(t.pos, t.length); GetToken(&t); if( t.type != ttOpenParanthesis ) { Error(ExpectedToken("(").AddressOf(), &t); return node; } node->AddChildLast(ParseAssignment()); if( isSyntaxError ) return node; GetToken(&t); if( t.type != ttCloseParanthesis ) { Error(ExpectedToken(")").AddressOf(), &t); return node; } GetToken(&t); if( t.type != ttStartStatementBlock ) { Error(ExpectedToken("{").AddressOf(), &t); return node; } while( !isSyntaxError ) { GetToken(&t); if( t.type == ttEndStatementBlock || t.type == ttDefault) break; RewindTo(&t); if( t.type != ttCase ) { Error(ExpectedToken("case").AddressOf(), &t); return node; } node->AddChildLast(ParseCase()); if( isSyntaxError ) return node; } if( t.type == ttDefault) { RewindTo(&t); node->AddChildLast(ParseCase()); if( isSyntaxError ) return node; GetToken(&t); } if( t.type != ttEndStatementBlock ) { Error(ExpectedToken("}").AddressOf(), &t); return node; } return node; }
asCScriptNode *asCParser::ParseInitList() { asCScriptNode *node = new asCScriptNode(snInitList); sToken t1; GetToken(&t1); if( t1.type != ttStartStatementBlock ) { Error(ExpectedToken("{").AddressOf(), &t1); return node; } node->UpdateSourcePos(t1.pos, t1.length); GetToken(&t1); if( t1.type == ttEndStatementBlock ) { node->UpdateSourcePos(t1.pos, t1.length); // Statement block is finished return node; } else { RewindTo(&t1); for(;;) { GetToken(&t1); if( t1.type == ttListSeparator ) { // No expression node->AddChildLast(new asCScriptNode(snUndefined)); GetToken(&t1); if( t1.type == ttEndStatementBlock ) { // No expression node->AddChildLast(new asCScriptNode(snUndefined)); node->UpdateSourcePos(t1.pos, t1.length); return node; } RewindTo(&t1); } else if( t1.type == ttEndStatementBlock ) { // No expression node->AddChildLast(new asCScriptNode(snUndefined)); node->UpdateSourcePos(t1.pos, t1.length); // Statement block is finished return node; } else if( t1.type == ttStartStatementBlock ) { RewindTo(&t1); node->AddChildLast(ParseInitList()); if( isSyntaxError ) return node; GetToken(&t1); if( t1.type == ttListSeparator ) continue; else if( t1.type == ttEndStatementBlock ) { node->UpdateSourcePos(t1.pos, t1.length); // Statement block is finished return node; } else { Error(ExpectedTokens("}", ",").AddressOf(), &t1); return node; } } else { RewindTo(&t1); node->AddChildLast(ParseAssignment()); if( isSyntaxError ) return node; GetToken(&t1); if( t1.type == ttListSeparator ) continue; else if( t1.type == ttEndStatementBlock ) { node->UpdateSourcePos(t1.pos, t1.length); // Statement block is finished return node; } else { Error(ExpectedTokens("}", ",").AddressOf(), &t1); return node; } } } } return 0; }
asCScriptNode *asCParser::ParseStatementBlock() { asCScriptNode *node = new asCScriptNode(snStatementBlock); sToken t1; GetToken(&t1); if( t1.type != ttStartStatementBlock ) { Error(ExpectedToken("{").AddressOf(), &t1); return node; } node->UpdateSourcePos(t1.pos, t1.length); for(;;) { while( !isSyntaxError ) { GetToken(&t1); if( t1.type == ttEndStatementBlock ) { node->UpdateSourcePos(t1.pos, t1.length); // Statement block is finished return node; } else { RewindTo(&t1); if( IsVarDecl() ) node->AddChildLast(ParseDeclaration()); else node->AddChildLast(ParseStatement()); } } if( isSyntaxError ) { // Search for either ';', '{', '}', or end GetToken(&t1); while( t1.type != ttEndStatement && t1.type != ttEnd && t1.type != ttStartStatementBlock && t1.type != ttEndStatementBlock ) { GetToken(&t1); } // Skip this statement block if( t1.type == ttStartStatementBlock ) { // Find the end of the block and skip nested blocks int level = 1; while( level > 0 ) { GetToken(&t1); if( t1.type == ttStartStatementBlock ) level++; if( t1.type == ttEndStatementBlock ) level--; if( t1.type == ttEnd ) break; } } else if( t1.type == ttEndStatementBlock ) { RewindTo(&t1); } else if( t1.type == ttEnd ) { Error(TXT_UNEXPECTED_END_OF_FILE, &t1); return node; } isSyntaxError = false; } } return 0; }