Implementation note : Token_'s generated by the Lexer_ are disposed of by the SyntacticSink (or the Grammar_). However, objects of the derived class terminalToken's are static and need not be disposed of (so allocation/deallocation is reduced). So deallocation is done by a virtual member function toGarbage(), overriden as required. It can deallocate child objects, then destroy the object by the instruction 'delete this; return' (!). Because of such a allocation/deallocation scheme, Token_ should not be allocated as variables local to a function; use static or dynamic allocation instead.
1. This one shows SyntacticTree construction for 'var;;' :
Grammar_ |TokenSource lane |lane parseFromTo() root_->parse_() EITHER()->parse_() variable_->parse_() SyntacticTree s1() MAYBE()->parse_() int_->parse_() |currentSource.expect_( int_) returns false returns errorToken s1.push_back( noToken); identifier_->parse_() |currentSource.expect_( identifier_) returns true s1.push_back( currentSource.fetch_() returns VariableToken( "identifier", "var")) semicolon_->parse_() |currentSource.expect_( semicolon_) returns true s1.push_back( currentSource.fetch_() returns semicolon_) HANDLE_() syntacticSink->handle( s1) output occurs here return noToken returns noToken EITHER()->parse_() variable_->parse_() SyntacticTree s1() MAYBE()->parse_() int_->parse_() |currentSource.expect_( int_) returns false s1.push_back( noToken); identifier_->parse_() |currentSource.expect_( identifier_) returns false return errorToken return errorToken function_->parse_() SyntacticTree s1() identifier_->parse_() |currentSource.expect_( identifier_) returns false return errorToken return errorToken returns errorToken returns noToken currentSource->printWarning()
2. This sequence diagram shows for 'foo3(){;}' :
Grammar_ |TokenSource lane |lane parseFromTo() |expecteds() root_->parse_() EITHER->parse_() variable_->parse_() SyntacticTree s1() MAYBE()->parse_() |currentSource.expect_( int_) | expecteds.insert( int_) | return false; identifier_->parse_() |currentSource.expect_( identifier_) return false |currentSource.fetch_() | expecteds.clear() semicolon_->parse_() |currentSource.expect_( semicolon_) | expecteds.insert( semicolon_) | return false //s1==SyntacticTree( noToken, VariableToken( "identifier", "foo3"), 0) |currentSource.storeBack( s1) returns errorToken function_->parse_() SyntacticTree s1() |currentSource.expect_( identifier_) |currentSource.fetch_() .. from data stored back |currentSource.expect_( braces_) |currentSource.fetch_() | expecteds.clear() Since we found braces, we no longer care that semicolon was not found ANY()->parse_() variable_->parse_() SyntacticTree s2() MAYBE()->parse_() |currentSource.expect_( int_) | expecteds.insert( int_) | return false identifier_.parse_() |currentSource.expect_( identifier_) | expecteds.insert( identifier_) | return false //s2= SyntacticTree( noToken, 0) |currentSource.storeBack( s2) return errorToken return noToken endBraces->parse_() |currentSource.expect_( endBraces) | expecteds.insert( endBraces) | return false; //s1=SyntacticTree( VariableToken( "identifier", "foo3"), braces, 0) |currentSource.storeBack( s1) returns errorToken returns errorToken returns errorToken |//expecteds= set( int_, identifier, endBraces) cuurentSource->printWarning()