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()