CAstStatement* CParser::statSequence(CAstScope *s) { // // statSequence ::= [ statement { ";" statement } ]. // FIRST(statement) = {tIF, tWhile, tReturn, tIdent}. // FOLLOW(statSequence) = {tEnd, tElse}. // CAstStatement *head = NULL; CAstStatement *tail = NULL; EToken tt = _scanner->Peek().GetType(); switch(tt) { case tIf: case tWhile: case tReturn: case tIdent: head = tail = statement(s); assert(head != NULL); // for multiple statements. while(1) { if(_scanner->Peek().GetType() == tEnd || _scanner->Peek().GetType() == tElse) { break; } else { Consume(tSemicolon); CAstStatement *st = NULL; st = statement(s); assert(st != NULL); tail->SetNext(st); tail = st; } } break; default: break; } return head; }
CAstStatement* CParser::statSequence(CAstScope *s) { // // stateSequence ::= [ statement { ";" statement } ]. // statement ::= assignment | subroutineCall // | ifStatement | whileStatement | returnStatement. // CAstStatement *head = NULL; CAstStatement *tail = NULL; CToken tt = _scanner->Peek(); while (!_abort && tt.GetType() != kEnd && tt.GetType() != kElse) { CAstStatement *st = NULL; // stateSequence -> ... statement ... tt = _scanner->Peek(); switch (tt.GetType()) { // statement -> assignment | subroutineCall case tIdent: { const CSymbol *sym = s->GetSymbolTable()->FindSymbol(tt.GetValue(), sLocal); if (!sym) sym = s->GetSymbolTable()->FindSymbol(tt.GetValue(), sGlobal); if (!sym) SetError(tt, "undeclared variable \"" + tt.GetValue() + "\""); ESymbolType stype = sym->GetSymbolType(); if (stype == stProcedure) st = subroutineCall(s); else st = assignment(s); } break; // statement -> ifStatement case kIf: st = ifStatement(s); break; // statement -> whileStatement case kWhile: st = whileStatement(s); break; // statement -> returnStatement case kReturn: st = returnStatement(s); break; default: SetError(_scanner->Peek(), "statement expected."); break; } assert(st); if (!head) head = st; else tail->SetNext(st); tail = st; tt = _scanner->Peek(); if (tt.GetType() == kEnd || tt.GetType() == kElse) break; // stateSequence -> ... ";" ... Consume(tSemicolon); } return head; }