void ParserThread::HandleClass(EClassType ct) { // class xxx { or class { // the keyworkd "class" is already comsumed //assert(CurrentToken()->type_id()==TKN_CLASS); ConsumeToken(); Token * current = ConsumeToken(); // class name Token * next = PeekToken(); TRACE("HandleClass() : Found class '%s'", current->get_text().c_str() ); // Check current firstly if (current->type_id() == TKN_L_BRACE) // unnamed class/struct/union { // cc_string unnamedTmp; // unnamedTmp.Printf(_T("%s%s%d"), // ParserConsts::unnamed.wx_str(), // ct == ctClass ? _T("Class") : // ct == ctUnion ? _T("Union") : // _T("Struct"), ++m_pTokensTree->m_StructUnionUnnamedCount); // // Token* newToken = DoAddToken(tkClass, unnamedTmp, lineNr); // // PushContext(); // m_Context.Clear(); // m_Context.parentToken = newToken; // m_Context.accessScope = ct == ctClass ? tsPrivate : tsPublic; // struct has default public scope // // newToken->m_ImplLine = lineNr; // newToken->m_ImplLineStart = m_Tokenizer.GetLineNumber(); // // DoParse(); // // PopContext(); } else if (current->type_id() == TKN_IDENTIFIER) //OK, we need to check the next { //parser base clause if ( next->type_id() == TKN_COLON ) { //ReadType //ConsumeToken(); //remove :id ConsumeToken(); //remove : ConsumeToken(); //remove protect/public/private //ConsumeToken(); //need to read the id ParseFullIdentifer(); } next = PeekToken(); if ( next->type_id() == TKN_L_BRACE) // class AAA {, we find the "{" here { //ParserThreadContext savedContext = m_Context; //m_Context.EndStatement(); //m_Context.parentToken = newToken; ConsumeToken();// consume { Symbol * sym = DoAddToken(tkClass, *current); PushContext(); m_Context.parentToken = sym; DoParse(); // when meet a }, we should return from DoParse() PopContext(); current = ConsumeToken(); if(current->type_id()==TKN_SEMICOLON) // class A {.....}; return; else SkipStatementBlock(); //struct A {....} a b; } } else { // something wrong, should be skip to a semicolon SkipStatementBlock(); } }
/// ParseDeclarationTypeSpec - Parse a declaration type spec construct. /// /// [R502]: /// declaration-type-spec := /// intrinsic-type-spec /// or TYPE ( derived-type-spec ) /// or CLASS ( derived-type-spec ) /// or CLASS ( * ) bool Parser::ParseDeclarationTypeSpec(DeclSpec &DS, bool AllowSelectors, bool AllowOptionalCommaAfterCharLength) { // [R403]: // intrinsic-type-spec := // INTEGER [ kind-selector ] // or REAL [ kind-selector ] // or DOUBLE PRECISION // or COMPLEX [ kind-selector ] // or DOUBLE COMPLEX // or CHARACTER [ char-selector ] // or BYTE // or LOGICAL [ kind-selector ] switch (Tok.getKind()) { default: DS.SetTypeSpecType(DeclSpec::TST_unspecified); break; case tok::kw_INTEGER: DS.SetTypeSpecType(DeclSpec::TST_integer); break; case tok::kw_REAL: DS.SetTypeSpecType(DeclSpec::TST_real); break; case tok::kw_COMPLEX: DS.SetTypeSpecType(DeclSpec::TST_complex); break; case tok::kw_CHARACTER: DS.SetTypeSpecType(DeclSpec::TST_character); break; case tok::kw_BYTE: DS.SetTypeSpecType(DeclSpec::TST_logical); DS.setByte(); // equivalent to Kind = 1 break; case tok::kw_LOGICAL: DS.SetTypeSpecType(DeclSpec::TST_logical); break; case tok::kw_DOUBLEPRECISION: DS.SetTypeSpecType(DeclSpec::TST_real); DS.setDoublePrecision(); // equivalent to Kind = 8 break; case tok::kw_DOUBLECOMPLEX: DS.SetTypeSpecType(DeclSpec::TST_complex); DS.setDoublePrecision(); // equivalent to Kind = 8 break; } if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) if (ParseTypeOrClassDeclTypeSpec(DS)) return true; ExprResult Kind; ExprResult Len; // FIXME: no Kind for double complex, double precision and byte switch (DS.getTypeSpecType()) { case DeclSpec::TST_struct: break; default: ConsumeToken(); if (ConsumeIfPresent(tok::star)) { // FIXME: proper obsolete COMPLEX*16 support ConsumeAnyToken(); DS.setDoublePrecision(); } if (!AllowSelectors) break; if (ConsumeIfPresent(tok::l_paren)) { Kind = ParseSelector(true); if (Kind.isInvalid()) return true; if(!ExpectAndConsume(tok::r_paren, 0, "", tok::r_paren)) return true; } break; case DeclSpec::TST_character: // [R424]: // char-selector := // length-selector // or ( LEN = type-param-value , KIND = scalar-int-initialization-expr ) // or ( type-param-value , # // # [ KIND = ] scalar-int-initialization-expr ) // or ( KIND = scalar-int-initialization-expr [, LEN = type-param-value]) // // [R425]: // length-selector := // ( [ LEN = ] type-param-value ) // or * char-length [,] // // [R426]: // char-length := // ( type-param-value ) // or scalar-int-literal-constant // // [R402]: // type-param-value := // scalar-int-expr // or * // or : ConsumeToken(); if(ConsumeIfPresent(tok::star)) { ParseCharacterStarLengthSpec(DS); if(AllowOptionalCommaAfterCharLength) ConsumeIfPresent(tok::comma); } else { if (!AllowSelectors) break; if(ConsumeIfPresent(tok::l_paren)) { if(IsPresent(tok::kw_LEN)) { Len = ParseSelector(false); if (Len.isInvalid()) return true; } else if(IsPresent(tok::kw_KIND)) { Kind = ParseSelector(true); if (Kind.isInvalid()) return true; } else { Len = ParseExpectedFollowupExpression("("); if(Len.isInvalid()) return true; } if(ConsumeIfPresent(tok::comma)) { // FIXME: if (Tok.is(tok::kw_LEN)) { if (Len.isInvalid()) return Diag.ReportError(Tok.getLocation(), "multiple LEN selectors for this type"); Len = ParseSelector(false); if (Len.isInvalid()) return true; } else if (Tok.is(tok::kw_KIND)) { if (Kind.isInvalid()) return Diag.ReportError(Tok.getLocation(), "multiple KIND selectors for this type"); Kind = ParseSelector(true); if (Kind.isInvalid()) return true; } else { if (Kind.isInvalid()) return Diag.ReportError(Tok.getLocation(), "multiple KIND selectors for this type"); ExprResult KindExpr = ParseExpression(); Kind = KindExpr; } } if(!ExpectAndConsume(tok::r_paren)) return true; } } break; } // Set the selectors for declspec. if(Kind.isUsable()) DS.setKindSelector(Kind.get()); if(Len.isUsable()) DS.setLengthSelector(Len.get()); return false; }
void ParserThread::DoParse() { while (true) { Token* tk = PeekToken(); switch (tk->type_id()) { case TKN_L_BRACE: //{ { SkipBrace(); break; } case TKN_R_BRACE: //} { // the only time we get to find a } is when recursively called by e.g. HandleClass // we have to return now... TRACE("DoParse(): return from%s%d:%d",tk->get_string().c_str(),tk->line_number(),tk->column_number()); ConsumeToken(); return; } case TKN_R_PAREN: //) { TRACE("DoParse(): return from%s%d:%d",tk->get_string().c_str(),tk->line_number(),tk->column_number()); ConsumeToken(); if(m_Context.parseType==FunctionParameter && m_Context.typeQueue.size()>0 && m_Context.nameQueue.size()>0) { DoAddToken(tkParameter, m_Context.nameQueue.back().name); } return; } case TKN_L_PAREN : // ( { SkipParentheses(); break; } case TKN_FOR: case TKN_WHILE: case TKN_IF: case TKN_SWITCH: { TRACE("handling for or while block"); HandleForWhile(); break; } case TKN_ELSE: { ConsumeToken(); if(PeekToken()->type_id()==TKN_IF) { ConsumeToken(); HandleForWhile(); } else SkipStatementBlock(); break; } case TKN_CLASS: case TKN_STRUCT: { m_Context.EndStatement(); if (m_Options.handleClasses) HandleClass(ctClass); else SkipStatementBlock(); break; } case TKN_EXPLICIT: case TKN_CONST: case TKN_FRIEND: case TKN_VIRTUAL: case TKN_VOLATILE: case TKN_STATIC: case TKN_INLINE: case TKN_AUTO: case TKN_REGISTER: case TKN_MUTABLE: { ConsumeToken(); //m_Context.typeQualifier = tk->type_id(); break; } case TKN_IDENTIFIER: { ParseFullIdentifer(); // we are interested in the following token. Token * peek = PeekToken(); int peekID = peek-> type_id(); switch (peekID) { case TKN_L_PAREN: // This is a function definition or declration, because it has AAA BBB ( if(m_Context.nameQueue.empty()) // AAA( { //HandleMacro(); if( m_Context.parentToken!= NULL && m_Context.parentToken->m_SymbolKind == tkClass && m_Context.parentToken->m_Name.get_text() == tk->get_text()) HandleFunction(); else { SkipParentheses(); } } else // AAA BBB( { HandleFunction(); } break; case TKN_SEMICOLON: // A B; if(m_Context.nameQueue.empty()) // AAA; { SkipStatementBlock(); } else // AAA BBB; { // the last element of the m_Context.name is the actual variable name cc_string variableName = m_Context.nameQueue.back().name.get_text(); // the last element of the m_Context.type is the actual type name cc_string variableType = m_Context.typeQueue.back().name.get_text(); TRACE("Variable Find name(%s) type(%s)",variableName.c_str(),variableType.c_str()); //Add variable to tokenstree if (m_Options.handleVars) DoAddToken(tkVariable, m_Context.nameQueue.back().name); ConsumeToken(); //consume the semicolon m_Context.EndStatement(); } break; case TKN_BITAND://& m_Context.typeQualifier.isReference = true; ConsumeToken(); break; case TKN_MULT: //* m_Context.typeQualifier.isPointer = true; ConsumeToken(); break; case TKN_L_SQUARE: case TKN_PLUS: case TKN_PLUS_ASSIGN: case TKN_DOUBLE_PLUS: case TKN_MINUS: case TKN_DOUBLE_MINUS: case TKN_MINUS_ASSIGN: case TKN_MULT_ASSIGN: case TKN_DIV: case TKN_DIV_ASSIGN: case TKN_MODULO: case TKN_MODULO_ASSIGN: case TKN_L_SHIFT: case TKN_L_SHIFT_ASSIGN: case TKN_R_SHIFT: case TKN_R_SHIFT_ASSIGN: case TKN_DOT: case TKN_ARROW: ConsumeToken(); SkipStatementBlock(); break; case TKN_COMMA: case TKN_ASSIGN: // A B = ....; // A B,C,D=2; if(m_Context.nameQueue.empty()) // A, { TRACE("Something wrong in mode A, "); SkipStatementBlock(); } else // A B, { cc_string variableName = m_Context.nameQueue.back().name.get_text(); cc_string variableType = m_Context.typeQueue.back().name.get_text(); TRACE("Variable Find name(%s) type(%s)",variableName.c_str(),variableType.c_str()); //Add variable to tokenstree if (m_Options.handleVars) { if(m_Context.parseType == FunctionParameter) DoAddToken(tkParameter, m_Context.nameQueue.back().name); else DoAddToken(tkVariable, m_Context.nameQueue.back().name); } ConsumeToken(); //consume , or = // tk is updated if(peek->type_id() == TKN_ASSIGN) { SkipStatementBlock(); } else m_Context.nameQueue.clear(); // clear name information, because we need to read another name } break; } break; }// End of handling of case TKN_IDENTIFIER case TKN_SEMICOLON: { ConsumeToken(); m_Context.EndStatement(); break; } case TKN_PUBLIC: { ConsumeToken(); Token * peek = PeekToken(); if(peek->type_id() == TKN_COLON) { m_Context.accessScope = tsPublic; m_Context.EndStatement(); ConsumeToken(); } break; } case TKN_PRIVATE: { ConsumeToken(); Token * peek = PeekToken(); if(peek->type_id() == TKN_COLON) { m_Context.accessScope = tsPrivate; m_Context.EndStatement(); ConsumeToken(); } break; } case TKN_PROTECT: { ConsumeToken(); Token * peek = PeekToken(); if(peek->type_id() == TKN_COLON) { m_Context.accessScope = tsProtected; m_Context.EndStatement(); ConsumeToken(); } break; } case TKN_USING: { ParseUsing(); break; } case TKN_DELETE: case TKN_NEW: case TKN_RETURN: case TKN_EXTERN: case TKN_GOTO: { SkipStatementBlock(); break; } case TKN_TEMPLATE: { bool readArgsOK = GetTemplateArgs(); // should following a <> pair, if(!readArgsOK) //should return true, otherwise, we should SkipStatementBlock(); break; } case TKN_ENUM: { if (m_Options.handleEnums) HandleEnum(); else SkipStatementBlock(); break; } case TKN_TYPEDEF: { if (m_Options.handleTypedefs) HandleTypedef(); else SkipStatementBlock(); m_Context.EndStatement(); break; } case TKN_NAMESPACE: { HandleNamespace(); break; } case TKN_OPERATOR: { ConsumeToken(); //eat the operator keyword Token *op = ConsumeToken(); // eat the operator pair if(op->type_id()==TKN_L_PAREN || op->type_id()==TKN_L_SQUARE) ConsumeToken(); ScopeBlock Operator; Operator.name = *op; m_Context.nameQueue.push_back(Operator); Token *peek = PeekToken(); if(peek->type_id()==TKN_L_PAREN) { HandleFunction(); } break; } default: { //cout<<"Skip unhandled"<<*tk<<endl; // As the tk is only a pointer to the Token buffer, so it may changed by // some function calling on ConsumeToken or PeekToken ConsumeToken(); break; } } } }
BriefParser::BriefParser(Lexer &L) : L(L) { // Get lookahead token. ConsumeToken(); }