Alien-SmokeQt
view release on metacpan or search on metacpan
generator/parser/parser.cpp view on Meta::CPAN
else \
advance(); \
} while (0)
#define CHECK(tk) \
do { \
if (session->token_stream->lookAhead() != tk) { \
return false; \
} \
advance(); \
} while (0)
#define UPDATE_POS(_node, start, end) \
do { \
(_node)->start_token = start; \
(_node)->end_token = end; \
} while (0)
void Parser::addComment( CommentAST* ast, const Comment& comment ) {
if( comment ) {
/* kDebug() << "Adding but leaving comment" << session->token_stream->token(comment.token()).symbol();*/
ast->comments = snoc(ast->comments, comment.token(), session->mempool);
}
}
void Parser::moveComments( CommentAST* ast ) {
while( m_commentStore.hasComment() ) {
size_t token = m_commentStore.takeFirstComment().token();
/* kDebug() << "Moving comment" << session->token_stream->token(token).symbol();*/
ast->comments = snoc(ast->comments, token, session->mempool);
}
}
Parser::Parser(Control *c)
: control(c), lexer(control), session(0), _M_last_valid_token(0), _M_last_parsed_comment(0), _M_hadMismatchingCompoundTokens(false), m_primaryExpressionWithTemplateParamsNeedsFunctionCall(true)
{
_M_max_problem_count = 5;
_M_hold_errors = false;
}
Parser::~Parser()
{
}
void Parser::rewind(size_t position) {
session->token_stream->rewind(position);
//Search the previous valid token
_M_last_valid_token = position > 0 ? position-1 : position;
while( _M_last_valid_token > 0 && session->token_stream->kind(_M_last_valid_token) == Token_comment )
--_M_last_valid_token;
}
void Parser::advance( bool skipComment ) {
size_t t = session->token_stream->lookAhead();
if( t != Token_comment )
_M_last_valid_token = session->token_stream->cursor();
session->token_stream->nextToken();
if( session->token_stream->lookAhead() == Token_comment ) {
if( skipComment ) {
processComment();
advance();
}
}
}
Comment Parser::comment() {
return m_commentStore.latestComment();
}
void Parser::preparseLineComments( int tokenNumber ) {
const Token& token( (*session->token_stream)[tokenNumber] );
SimpleCursor tokenPosition = SimpleCursor::invalid();
for( int a = 0; a < 40; a++ ) {
if( !session->token_stream->lookAhead(a) ) break;
if( session->token_stream->lookAhead(a) == Token_comment ) {
//Make sure the token's line is before the searched token's line
const Token& commentToken( (*session->token_stream)[session->token_stream->cursor() + a] );
if( !tokenPosition.isValid() ) //Get the token line. Only on-demand, because it's not cheap.
tokenPosition = session->positionAt(token.position);
SimpleCursor commentPosition = session->positionAt( commentToken.position );
if( commentPosition.line < tokenPosition.line ) {
continue;
} else if( commentPosition.line == tokenPosition.line ) {
processComment( a );
} else {
//Too far
break;
}
}
}
}
int Parser::lineFromTokenNumber( size_t tokenNumber ) const {
const Token& token( (*session->token_stream)[tokenNumber] );
return session->positionAt( token.position ).line;
}
void Parser::processComment( int offset, int line ) {
size_t tokenNumber = session->token_stream->cursor() + offset;
if(_M_last_parsed_comment >= tokenNumber)
return; //The comment was already parsed. May happen because of pre-parsing
_M_last_parsed_comment = tokenNumber;
const Token& commentToken( (*session->token_stream)[tokenNumber] );
Q_ASSERT(commentToken.kind == Token_comment);
if( line == -1 ) {
SimpleCursor position = session->positionAt( commentToken.position );
line = position.line;
}
/* kDebug() << "noticing comment" << commentToken.symbol();*/
m_commentStore.addComment( Comment( session->token_stream->cursor() + offset, line ) );
}
void Parser::clearComment( ) {
m_commentStore.clear();
}
TranslationUnitAST *Parser::parse(ParseSession* _session)
{
clear();
session = _session;
if (!session->token_stream)
session->token_stream = new TokenStream;
lexer.tokenize(session);
advance(); // skip the first token
TranslationUnitAST *ast = 0;
parseTranslationUnit(ast);
return ast;
}
StatementAST *Parser::parseStatement(ParseSession* _session)
{
clear();
session = _session;
if (!session->token_stream)
session->token_stream = new TokenStream;
lexer.tokenize(session);
advance(); // skip the first token
StatementAST *ast = 0;
parseCompoundStatement(ast);
return ast;
}
AST *Parser::parseTypeOrExpression(ParseSession* _session, bool forceExpression)
{
clear();
session = _session;
if (!session->token_stream)
session->token_stream = new TokenStream;
lexer.tokenize(session);
advance(); // skip the first token
TypeIdAST *ast = 0;
if (!forceExpression)
parseTypeId(ast);
if(!ast) {
m_primaryExpressionWithTemplateParamsNeedsFunctionCall = false;
ExpressionAST* ast = 0;
parseExpression(ast);
return ast;
}
return ast;
}
void Parser::clear()
{
_M_hold_errors = false;
m_tokenMarkers.clear();
}
void Parser::addTokenMarkers(size_t tokenNumber, Parser::TokenMarkers markers)
{
hash_map<size_t, TokenMarkers>::iterator it = m_tokenMarkers.find(tokenNumber);
if(it != m_tokenMarkers.end())
(*it).second = (TokenMarkers)((*it).second | markers);
else
m_tokenMarkers.insert(std::make_pair(tokenNumber, markers));
}
Parser::TokenMarkers Parser::tokenMarkers(size_t tokenNumber) const
{
hash_map<size_t, TokenMarkers>::const_iterator it = m_tokenMarkers.find(tokenNumber);
if(it != m_tokenMarkers.end())
return (*it).second;
else
return None;
}
IndexedString declSpecString("__declspec");
bool Parser::parseWinDeclSpec(WinDeclSpecAST *&node)
{
if (session->token_stream->lookAhead() != Token_identifier)
return false;
std::size_t start = session->token_stream->cursor();
IndexedString name = session->token_stream->token(session->token_stream->cursor()).symbol();
if (name != declSpecString)
return false;
std::size_t specifier = session->token_stream->cursor();
advance();
if (session->token_stream->lookAhead() != '(')
return false;
advance();
if (session->token_stream->lookAhead() != Token_identifier)
return false;
std::size_t modifier = session->token_stream->cursor();
advance();
if (session->token_stream->lookAhead() != ')')
return false;
advance();
node = CreateNode<WinDeclSpecAST>(session->mempool);
node->specifier = specifier;
node->modifier = modifier;
UPDATE_POS(node, start, _M_last_valid_token+1);
return true;
}
void Parser::tokenRequiredError(int token)
{
QString err;
err += "Expected token ";
err += '\'';
err += token_name(token);
err += "\' after \'";
err += token_name(session->token_stream->lookAhead(-1));
err += "\' found \'";
err += token_name(session->token_stream->lookAhead());
err += '\'';
if(token == '}' || token == '{')
_M_hadMismatchingCompoundTokens = true;
reportError(err);
}
void Parser::syntaxError()
{
std::size_t cursor = session->token_stream->cursor();
std::size_t kind = session->token_stream->lookAhead();
if (m_syntaxErrorTokens.contains(cursor))
return; // syntax error at this point has already been reported
m_syntaxErrorTokens.insert(cursor);
QString err;
if (kind == Token_EOF)
err += "Unexpected end of file";
else
{
err += "Unexpected token ";
err += '\'';
err += token_name(kind);
err += '\'';
}
reportError(err);
}
void Parser::reportPendingErrors()
{
bool hold = holdErrors(false);
std::size_t start = session->token_stream->cursor();
while (m_pendingErrors.count() > 0)
{
PendingError error = m_pendingErrors.dequeue();
session->token_stream->rewind(error.cursor);
reportError(error.message);
}
rewind(start);
holdErrors(hold);
}
void Parser::reportError(const QString& msg)
{
if (!_M_hold_errors && _M_problem_count < _M_max_problem_count)
{
++_M_problem_count;
QString fileName;
std::size_t tok = session->token_stream->cursor();
SimpleCursor position = session->positionAt(session->token_stream->position(tok));
Problem *p = new Problem;
p->file = session->url().str();
p->position = position;
p->description = msg + " : " + QString::fromUtf8(lineFromContents(session->size(), session->contents(), p->position.line));
p->source = Problem::Source_Parser;
control->reportProblem(p);
}
else if (_M_hold_errors)
{
PendingError pending;
pending.message = msg;
pending.cursor = session->token_stream->cursor();
m_pendingErrors.enqueue(pending);
}
}
bool Parser::skipUntil(int token)
{
clearComment();
while (session->token_stream->lookAhead())
{
if (session->token_stream->lookAhead() == token)
return true;
advance();
}
return false;
}
bool Parser::skipUntilDeclaration()
{
while (session->token_stream->lookAhead())
{
switch(session->token_stream->lookAhead())
{
case ';':
case '~':
case Token_scope:
case Token_identifier:
case Token_operator:
case Token_char:
case Token_size_t:
case Token_wchar_t:
case Token_bool:
case Token_short:
case Token_int:
case Token_long:
case Token_signed:
case Token_unsigned:
case Token_float:
case Token_double:
case Token_void:
case Token_extern:
case Token_namespace:
case Token_using:
case Token_typedef:
case Token_asm:
case Token_template:
case Token_export:
case Token_const: // cv
case Token_volatile: // cv
case Token_public:
case Token_protected:
case Token_private:
case Token_signals: // Qt
case Token_slots: // Qt
return true;
generator/parser/parser.cpp view on Meta::CPAN
case Token_continue:
case Token_return:
case Token_goto:
case Token_try:
case Token_catch:
case Token_throw:
case Token_char:
case Token_size_t:
case Token_wchar_t:
case Token_bool:
case Token_short:
case Token_int:
case Token_long:
case Token_signed:
case Token_unsigned:
case Token_float:
case Token_double:
case Token_void:
case Token_class:
case Token_struct:
case Token_union:
case Token_enum:
case Token_scope:
case Token_template:
case Token_using:
return true;
default:
advance();
}
}
return false;
}
bool Parser::skip(int l, int r)
{
int count = 0;
while (session->token_stream->lookAhead())
{
int tk = session->token_stream->lookAhead();
if (tk == l)
++count;
else if (tk == r)
--count;
else if (l != '{' && (tk == '{' || tk == '}' || tk == ';'))
return false;
if (count == 0)
return true;
advance();
}
return false;
}
bool Parser::parseName(NameAST*& node, ParseNameAcceptTemplate acceptTemplateId)
{
std::size_t start = session->token_stream->cursor();
WinDeclSpecAST *winDeclSpec = 0;
parseWinDeclSpec(winDeclSpec);
NameAST *ast = CreateNode<NameAST>(session->mempool);
if (session->token_stream->lookAhead() == Token_scope)
{
ast->global = true;
advance();
}
std::size_t idx = session->token_stream->cursor();
while (true)
{
UnqualifiedNameAST *n = 0;
if (!parseUnqualifiedName(n)) {
return false;
}
if (session->token_stream->lookAhead() == Token_scope)
{
advance();
ast->qualified_names
= snoc(ast->qualified_names, n, session->mempool);
if (session->token_stream->lookAhead() == Token_template)
{
/// skip optional template #### @todo CHECK
advance();
}
}
else
{
Q_ASSERT(n != 0);
if (acceptTemplateId == DontAcceptTemplate ||
//Eventually only accept template parameters as primary expression if the expression is followed by a function call
(acceptTemplateId == EventuallyAcceptTemplate && n->template_arguments && session->token_stream->lookAhead() != '(' && m_primaryExpressionWithTemplateParamsNeedsFunctionCall))
{
rewind(n->start_token);
parseUnqualifiedName(n, false);
}
ast->unqualified_name = n;
break;
}
}
if (idx == session->token_stream->cursor())
return false;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseTranslationUnit(TranslationUnitAST *&node)
{
_M_problem_count = 0;
_M_hadMismatchingCompoundTokens = false;
/* kDebug() << "tokens:";
for(size_t a = 0; a < session->token_stream->size(); ++a)
kDebug() << token_name(session->token_stream->token(a).kind) << session->token_stream->token(a).symbolString();*/
std::size_t start = session->token_stream->cursor();
TranslationUnitAST *ast = CreateNode<TranslationUnitAST>(session->mempool);
if( m_commentStore.hasComment() )
addComment(ast, m_commentStore.takeFirstComment());
while (session->token_stream->lookAhead())
{
std::size_t startDecl = session->token_stream->cursor();
DeclarationAST *declaration = 0;
if (parseDeclaration(declaration))
{
ast->declarations =
snoc(ast->declarations, declaration, session->mempool);
}
else
{
// error recovery
if (startDecl == session->token_stream->cursor())
{
// skip at least one token
advance();
}
skipUntilDeclaration();
}
}
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
ast->hadMissingCompoundTokens = _M_hadMismatchingCompoundTokens;
return true;
}
bool Parser::parseDeclaration(DeclarationAST *&node)
{
std::size_t start = session->token_stream->cursor();
switch(session->token_stream->lookAhead())
{
case ';':
advance();
return true;
case Token_extern:
return parseLinkageSpecification(node);
case Token_namespace:
return parseNamespace(node);
case Token_using:
return parseUsing(node);
case Token_typedef:
return parseTypedef(node);
case Token_asm:
return parseAsmDefinition(node);
case Token_template:
case Token_export:
return parseTemplateDeclaration(node);
default:
{
const ListNode<std::size_t> *cv = 0;
parseCvQualify(cv);
const ListNode<std::size_t> *storageSpec = 0;
parseStorageClassSpecifier(storageSpec);
parseCvQualify(cv);
Comment mcomment = comment();
clearComment();
TypeSpecifierAST *spec = 0;
if (parseEnumSpecifier(spec)
|| parseClassSpecifier(spec))
{
parseCvQualify(cv);
spec->cv = cv;
const ListNode<InitDeclaratorAST*> *declarators = 0;
parseInitDeclaratorList(declarators);
ADVANCE(';', ";");
SimpleDeclarationAST *ast =
CreateNode<SimpleDeclarationAST>(session->mempool);
ast->storage_specifiers = storageSpec;
ast->type_specifier = spec;
ast->init_declarators = declarators;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
if( mcomment )
addComment(ast, mcomment);
preparseLineComments(ast->end_token-1);
if( m_commentStore.hasComment() )
addComment( ast, m_commentStore.takeCommentInRange( lineFromTokenNumber( --ast->end_token ) ) );
return true;
} else {
rewind(start);
if( parseDeclarationInternal(node) ) {
//Add the comments to the declaration
if( mcomment )
addComment(node, mcomment);
preparseLineComments(node->end_token-1);
if( m_commentStore.hasComment() )
addComment( node, m_commentStore.takeCommentInRange( lineFromTokenNumber( --node->end_token ) ) );
return true;
}
}
}
} // end switch
return false;
}
bool Parser::parseLinkageSpecification(DeclarationAST *&node)
{
std::size_t start = session->token_stream->cursor();
CHECK(Token_extern);
LinkageSpecificationAST *ast = CreateNode<LinkageSpecificationAST>(session->mempool);
if (session->token_stream->lookAhead() == Token_string_literal)
{
ast->extern_type = session->token_stream->cursor();
advance();
}
if (session->token_stream->lookAhead() == '{')
{
parseLinkageBody(ast->linkage_body);
}
else if (!parseDeclaration(ast->declaration))
{
reportError(("Declaration syntax error"));
}
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseLinkageBody(LinkageBodyAST *&node)
{
std::size_t start = session->token_stream->cursor();
CHECK('{');
LinkageBodyAST *ast = CreateNode<LinkageBodyAST>(session->mempool);
while (session->token_stream->lookAhead())
{
int tk = session->token_stream->lookAhead();
if (tk == '}')
break;
std::size_t startDecl = session->token_stream->cursor();
DeclarationAST *declaration = 0;
if (parseDeclaration(declaration))
{
ast->declarations = snoc(ast->declarations, declaration, session->mempool);
}
else
{
// error recovery
if (startDecl == session->token_stream->cursor())
{
// skip at least one token
advance();
}
skipUntilDeclaration();
}
}
clearComment();
if (session->token_stream->lookAhead() != '}') {
reportError(("} expected"));
_M_hadMismatchingCompoundTokens = true;
} else
advance();
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseNamespace(DeclarationAST *&node)
{
std::size_t start = session->token_stream->cursor();
CHECK(Token_namespace);
std::size_t namespace_name = 0;
if (session->token_stream->lookAhead() == Token_identifier)
{
namespace_name = session->token_stream->cursor();
advance();
}
if (session->token_stream->lookAhead() == '=')
{
// namespace alias
advance();
NameAST *name = 0;
if (parseName(name))
{
ADVANCE(';', ";");
NamespaceAliasDefinitionAST *ast
= CreateNode<NamespaceAliasDefinitionAST>(session->mempool);
ast->namespace_name = namespace_name;
ast->alias_name = name;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
else
{
reportError(("Namespace expected"));
return false;
}
}
else if (session->token_stream->lookAhead() != '{')
{
reportError(("{ expected"));
_M_hadMismatchingCompoundTokens = true;
return false;
}
NamespaceAST *ast = CreateNode<NamespaceAST>(session->mempool);
ast->namespace_name = namespace_name;
parseLinkageBody(ast->linkage_body);
UPDATE_POS(ast, start, ast->linkage_body->end_token);
node = ast;
return true;
}
bool Parser::parseUsing(DeclarationAST *&node)
{
std::size_t start = session->token_stream->cursor();
CHECK(Token_using);
if (session->token_stream->lookAhead() == Token_namespace)
return parseUsingDirective(node);
UsingAST *ast = CreateNode<UsingAST>(session->mempool);
if (session->token_stream->lookAhead() == Token_typename)
{
ast->type_name = session->token_stream->cursor();
advance();
}
if (!parseName(ast->name))
return false;
ADVANCE(';', ";");
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseUsingDirective(DeclarationAST *&node)
{
std::size_t start = session->token_stream->cursor();
CHECK(Token_namespace);
NameAST *name = 0;
if (!parseName(name))
{
reportError(("Namespace name expected"));
return false;
}
ADVANCE(';', ";");
UsingDirectiveAST *ast = CreateNode<UsingDirectiveAST>(session->mempool);
ast->name = name;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseOperatorFunctionId(OperatorFunctionIdAST *&node)
{
std::size_t start = session->token_stream->cursor();
CHECK(Token_operator);
OperatorFunctionIdAST *ast = CreateNode<OperatorFunctionIdAST>(session->mempool);
if (!parseOperator(ast->op))
{
ast->op = 0;
// parse cast operator
const ListNode<std::size_t> *cv = 0;
parseCvQualify(cv);
if (!parseSimpleTypeSpecifier(ast->type_specifier))
{
syntaxError();
return false;
}
parseCvQualify(cv);
ast->type_specifier->cv = cv;
PtrOperatorAST *ptr_op = 0;
while (parsePtrOperator(ptr_op))
ast->ptr_ops = snoc(ast->ptr_ops, ptr_op, session->mempool);
}
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseTemplateArgumentList(const ListNode<TemplateArgumentAST*> *&node,
bool reportError)
{
TemplateArgumentAST *templArg = 0;
if (!parseTemplateArgument(templArg))
return false;
node = snoc(node, templArg, session->mempool);
while (session->token_stream->lookAhead() == ',')
{
advance();
if (!parseTemplateArgument(templArg))
{
if (reportError)
{
syntaxError();
break;
}
node = 0;
return false;
}
node = snoc(node, templArg, session->mempool);
}
return true;
}
bool Parser::parseTypedef(DeclarationAST *&node)
{
std::size_t start = session->token_stream->cursor();
Comment mcomment = comment();
CHECK(Token_typedef);
TypeSpecifierAST *spec = 0;
if (!parseTypeSpecifierOrClassSpec(spec))
{
reportError(("Need a type specifier to declare"));
return false;
}
const ListNode<InitDeclaratorAST*> *declarators = 0;
if (!parseInitDeclaratorList(declarators))
{
//reportError(("Need an identifier to declare"));
//return false;
}
clearComment();
TypedefAST *ast = CreateNode<TypedefAST>(session->mempool);
if( mcomment )
addComment( ast, mcomment );
ADVANCE(';', ";");
ast->type_specifier = spec;
ast->init_declarators = declarators;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
preparseLineComments( ast->end_token-1 );
if( m_commentStore.hasComment() )
addComment( ast, m_commentStore.takeCommentInRange( lineFromTokenNumber( --ast->end_token ) ) );
return true;
}
bool Parser::parseAsmDefinition(DeclarationAST *&node)
{
std::size_t start = session->token_stream->cursor();
ADVANCE(Token_asm, "asm");
const ListNode<std::size_t> *cv = 0;
parseCvQualify(cv);
#if defined(__GNUC__)
#warning "implement me"
#endif
skip('(', ')');
advance();
ADVANCE(';', ";");
AsmDefinitionAST *ast = CreateNode<AsmDefinitionAST>(session->mempool);
ast->cv = cv;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseTemplateDeclaration(DeclarationAST *&node)
{
std::size_t start = session->token_stream->cursor();
std::size_t exported = 0;
if (session->token_stream->lookAhead() == Token_export)
{
exported = session->token_stream->cursor();
advance();
}
CHECK(Token_template);
const ListNode<TemplateParameterAST*> *params = 0;
if (session->token_stream->lookAhead() == '<')
{
advance();
parseTemplateParameterList(params);
ADVANCE('>', ">");
}
DeclarationAST *declaration = 0;
if (!parseDeclaration(declaration))
{
reportError(("Expected a declaration"));
}
TemplateDeclarationAST *ast = CreateNode<TemplateDeclarationAST>(session->mempool);
ast->exported = exported;
ast->template_parameters = params;
ast->declaration = declaration;
UPDATE_POS(ast, start, declaration ? declaration->end_token : _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseOperator(OperatorAST *&node)
{
std::size_t start = session->token_stream->cursor();
OperatorAST *ast = CreateNode<OperatorAST>(session->mempool);
switch(session->token_stream->lookAhead())
{
case Token_new:
case Token_delete:
{
ast->op = session->token_stream->cursor();
advance();
if (session->token_stream->lookAhead() == '['
&& session->token_stream->lookAhead(1) == ']')
{
ast->open = session->token_stream->cursor();
advance();
ast->close = session->token_stream->cursor();
advance();
}
}
break;
case '+':
case '-':
case '*':
case '/':
case '%':
case '^':
case '&':
case '|':
case '~':
case '!':
case '=':
case '<':
case '>':
case ',':
case Token_assign:
case Token_shift:
case Token_eq:
case Token_not:
case Token_not_eq:
case Token_leq:
case Token_geq:
case Token_and:
case Token_or:
case Token_incr:
case Token_decr:
case Token_ptrmem:
case Token_arrow:
ast->op = session->token_stream->cursor();
advance();
break;
default:
if (session->token_stream->lookAhead() == '('
&& session->token_stream->lookAhead(1) == ')')
{
ast->op = ast->open = session->token_stream->cursor();
advance();
ast->close = session->token_stream->cursor();
advance();
}
else if (session->token_stream->lookAhead() == '['
&& session->token_stream->lookAhead(1) == ']')
{
ast->op = ast->open = session->token_stream->cursor();
advance();
ast->close = session->token_stream->cursor();
advance();
}
else
{
return false;
}
}
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseCvQualify(const ListNode<std::size_t> *&node)
{
std::size_t start = session->token_stream->cursor();
int tk;
while (0 != (tk = session->token_stream->lookAhead())
&& (tk == Token_const || tk == Token_volatile))
{
node = snoc(node, session->token_stream->cursor(), session->mempool);
advance();
}
return start != session->token_stream->cursor();
}
bool Parser::parseSimpleTypeSpecifier(TypeSpecifierAST *&node,
bool onlyIntegral)
{
std::size_t start = session->token_stream->cursor();
bool isIntegral = false;
bool done = false;
const ListNode<std::size_t> *integrals = 0;
while (!done)
{
switch(session->token_stream->lookAhead())
{
case Token_char:
case Token_size_t:
case Token_wchar_t:
case Token_bool:
case Token_short:
case Token_int:
case Token_long:
case Token_signed:
case Token_unsigned:
case Token_float:
case Token_double:
case Token_void:
integrals = snoc(integrals, session->token_stream->cursor(), session->mempool);
isIntegral = true;
advance();
break;
default:
done = true;
}
}
SimpleTypeSpecifierAST *ast = CreateNode<SimpleTypeSpecifierAST>(session->mempool);
if (isIntegral)
{
ast->integrals = integrals;
}
else if (session->token_stream->lookAhead() == Token___typeof)
{
ast->type_of = session->token_stream->cursor();
advance();
if (session->token_stream->lookAhead() == '(')
{
advance();
std::size_t saved = session->token_stream->cursor();
parseTypeId(ast->type_id);
if (session->token_stream->lookAhead() != ')')
{
ast->type_id = 0;
rewind(saved);
parseUnaryExpression(ast->expression);
}
ADVANCE(')', ")");
}
else
{
parseUnaryExpression(ast->expression);
}
}
else if (onlyIntegral)
{
rewind(start);
return false;
}
else
{
if (!parseName(ast->name, AcceptTemplate))
{
ast->name = 0;
rewind(start);
return false;
}
}
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parsePtrOperator(PtrOperatorAST *&node)
{
int tk = session->token_stream->lookAhead();
if (tk != '&' && tk != '*'
&& tk != Token_scope && tk != Token_identifier)
{
return false;
}
std::size_t start = session->token_stream->cursor();
PtrOperatorAST *ast = CreateNode<PtrOperatorAST>(session->mempool);
switch (session->token_stream->lookAhead())
{
case '&':
case '*':
ast->op = session->token_stream->cursor();
advance();
break;
case Token_scope:
case Token_identifier:
{
if (!parsePtrToMember(ast->mem_ptr))
{
rewind(start);
return false;
}
}
break;
default:
Q_ASSERT(0);
break;
}
parseCvQualify(ast->cv);
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseTemplateArgument(TemplateArgumentAST *&node)
{
std::size_t start = session->token_stream->cursor();
TypeIdAST *typeId = 0;
ExpressionAST *expr = 0;
if (!parseTypeId(typeId) || (session->token_stream->lookAhead() != ','
&& session->token_stream->lookAhead() != '>' && session->token_stream->lookAhead() != ')'))
{
rewind(start);
if (!parseLogicalOrExpression(expr, true))
return false;
}
TemplateArgumentAST *ast = CreateNode<TemplateArgumentAST>(session->mempool);
ast->type_id = typeId;
ast->expression = expr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseTypeSpecifier(TypeSpecifierAST *&node)
{
std::size_t start = session->token_stream->cursor();
const ListNode<std::size_t> *cv = 0;
parseCvQualify(cv);
TypeSpecifierAST *ast = 0;
if (!parseElaboratedTypeSpecifier(ast) && !parseSimpleTypeSpecifier(ast))
{
rewind(start);
return false;
}
parseCvQualify(cv);
ast->cv = cv;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseDeclarator(DeclaratorAST *&node)
{
std::size_t start = session->token_stream->cursor();
DeclaratorAST *ast = CreateNode<DeclaratorAST>(session->mempool);
DeclaratorAST *decl = 0;
NameAST *declId = 0;
PtrOperatorAST *ptrOp = 0;
while (parsePtrOperator(ptrOp))
{
ast->ptr_ops = snoc(ast->ptr_ops, ptrOp, session->mempool);
}
if (session->token_stream->lookAhead() == '(')
{
advance();
if (!parseDeclarator(decl))
return false;
ast->sub_declarator = decl;
CHECK(')');
}
else
{
if (session->token_stream->lookAhead() == ':')
{
// unnamed bitfield
}
else if (parseName(declId, AcceptTemplate))
{
ast->id = declId;
}
else
{
rewind(start);
return false;
}
if (session->token_stream->lookAhead() == ':')
{
advance();
if (!parseConstantExpression(ast->bit_expression))
{
reportError(("Constant expression expected"));
}
goto update_pos;
}
}
{
bool isVector = false;
while (session->token_stream->lookAhead() == '[')
{
advance();
ExpressionAST *expr = 0;
parseCommaExpression(expr);
ADVANCE(']', "]");
ast->array_dimensions = snoc(ast->array_dimensions, expr, session->mempool);
isVector = true;
}
bool skipParen = false;
if (session->token_stream->lookAhead() == Token_identifier
&& session->token_stream->lookAhead(1) == '('
&& session->token_stream->lookAhead(2) == '(')
{
advance();
advance();
skipParen = true;
}
int tok = session->token_stream->lookAhead();
if (ast->sub_declarator
&& !(isVector || tok == '(' || tok == ','
|| tok == ';' || tok == '='))
{
rewind(start);
return false;
}
std::size_t index = session->token_stream->cursor();
if (session->token_stream->lookAhead() == '(')
{
advance();
///@todo Sometimes something like (test()) is parsed as a parameter declaration clause, although it cannot be one.
ParameterDeclarationClauseAST *params = 0;
if (!parseParameterDeclarationClause(params))
{
rewind(index);
goto update_pos;
}
ast->parameter_declaration_clause = params;
if (session->token_stream->lookAhead() != ')')
{
rewind(index);
goto update_pos;
}
advance(); // skip ')'
parseCvQualify(ast->fun_cv);
parseExceptionSpecification(ast->exception_spec);
if (session->token_stream->lookAhead() == Token___attribute__)
{
advance();
ADVANCE('(', "(");
ExpressionAST *expr = 0;
parseExpression(expr);
if (session->token_stream->lookAhead() != ')')
{
reportError(("')' expected"));
}
else
{
advance();
}
}
}
if (skipParen)
{
if (session->token_stream->lookAhead() != ')')
{
reportError(("')' expected"));
}
else
advance();
}
}
update_pos:
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseAbstractDeclarator(DeclaratorAST *&node)
{
std::size_t start = session->token_stream->cursor();
DeclaratorAST *ast = CreateNode<DeclaratorAST>(session->mempool);
DeclaratorAST *decl = 0;
PtrOperatorAST *ptrOp = 0;
while (parsePtrOperator(ptrOp))
{
ast->ptr_ops = snoc(ast->ptr_ops, ptrOp, session->mempool);
}
int index = session->token_stream->cursor();
if (session->token_stream->lookAhead() == '(')
{
advance();
if (!parseAbstractDeclarator(decl))
{
rewind(index);
goto label1;
}
ast->sub_declarator = decl;
if (session->token_stream->lookAhead() != ')')
{
rewind(start);
return false;
}
advance();
}
else if (session->token_stream->lookAhead() == ':')
{
advance();
if (!parseConstantExpression(ast->bit_expression))
{
ast->bit_expression = 0;
reportError(("Constant expression expected"));
}
goto update_pos;
}
label1:
{
bool isVector = false;
while (session->token_stream->lookAhead() == '[')
{
advance();
ExpressionAST *expr = 0;
parseCommaExpression(expr);
ADVANCE(']', "]");
ast->array_dimensions = snoc(ast->array_dimensions, expr, session->mempool);
isVector = true;
}
int tok = session->token_stream->lookAhead();
if (ast->sub_declarator
&& !(isVector || tok == '(' || tok == ','
|| tok == ';' || tok == '='))
{
rewind(start);
return false;
}
int index = session->token_stream->cursor();
if (session->token_stream->lookAhead() == '(')
{
advance();
ParameterDeclarationClauseAST *params = 0;
if (!parseParameterDeclarationClause(params))
{
rewind(index);
goto update_pos;
}
ast->parameter_declaration_clause = params;
if (session->token_stream->lookAhead() != ')')
{
rewind(index);
goto update_pos;
}
advance(); // skip ')'
parseCvQualify(ast->fun_cv);
parseExceptionSpecification(ast->exception_spec);
}
}
update_pos:
if (session->token_stream->cursor() == start)
return false;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseEnumSpecifier(TypeSpecifierAST *&node)
{
std::size_t start = session->token_stream->cursor();
CHECK(Token_enum);
NameAST *name = 0;
parseName(name);
if (session->token_stream->lookAhead() != '{')
{
rewind(start);
return false;
}
advance();
EnumSpecifierAST *ast = CreateNode<EnumSpecifierAST>(session->mempool);
ast->name = name;
EnumeratorAST *enumerator = 0;
if (parseEnumerator(enumerator))
{
ast->enumerators = snoc(ast->enumerators, enumerator, session->mempool);
while (session->token_stream->lookAhead() == ',')
{
advance();
if (!parseEnumerator(enumerator))
{
//reportError(("Enumerator expected"));
break;
}
ast->enumerators = snoc(ast->enumerators, enumerator, session->mempool);
}
}
clearComment();
ADVANCE_NR('}', "}");
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseTemplateParameterList(const ListNode<TemplateParameterAST*> *&node)
{
TemplateParameterAST *param = 0;
if (!parseTemplateParameter(param))
return false;
node = snoc(node, param, session->mempool);
while (session->token_stream->lookAhead() == ',')
{
advance();
if (!parseTemplateParameter(param))
{
syntaxError();
break;
}
else
{
node = snoc(node, param, session->mempool);
}
}
return true;
}
bool Parser::parseTemplateParameter(TemplateParameterAST *&node)
{
std::size_t start = session->token_stream->cursor();
TemplateParameterAST *ast = CreateNode<TemplateParameterAST>(session->mempool);
int tk = session->token_stream->lookAhead();
if ((tk == Token_class || tk == Token_typename || tk == Token_template)
&& parseTypeParameter(ast->type_parameter))
{
// nothing to do
}
else if (!parseParameterDeclaration(ast->parameter_declaration))
return false;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseTypeParameter(TypeParameterAST *&node)
{
std::size_t start = session->token_stream->cursor();
TypeParameterAST *ast = CreateNode<TypeParameterAST>(session->mempool);
ast->type = start;
switch(session->token_stream->lookAhead())
{
case Token_class:
case Token_typename:
{
advance(); // skip class
// parse optional name
if(parseName(ast->name, AcceptTemplate))
{
if (session->token_stream->lookAhead() == '=')
{
advance();
if(!parseTypeId(ast->type_id))
{
//syntaxError();
rewind(start);
return false;
}
}
else if (session->token_stream->lookAhead() != ','
&& session->token_stream->lookAhead() != '>')
{
rewind(start);
return false;
}
}
}
break;
case Token_template:
{
advance(); // skip template
ADVANCE('<', "<");
if (!parseTemplateParameterList(ast->template_parameters))
return false;
ADVANCE('>', ">");
// TODO add to AST
if (session->token_stream->lookAhead() == Token_class)
advance();
// parse optional name
if (parseName(ast->name, AcceptTemplate))
{
if (session->token_stream->lookAhead() == '=')
{
advance();
if (!parseTypeId(ast->type_id))
{
syntaxError();
return false;
}
}
}
if (session->token_stream->lookAhead() == '=')
{
advance();
parseName(ast->template_name, AcceptTemplate);
}
}
break;
default:
return false;
} // end switch
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseStorageClassSpecifier(const ListNode<std::size_t> *&node)
{
std::size_t start = session->token_stream->cursor();
int tk;
while (0 != (tk = session->token_stream->lookAhead())
&& (tk == Token_friend || tk == Token_auto
|| tk == Token_register || tk == Token_static
|| tk == Token_extern || tk == Token_mutable))
{
node = snoc(node, session->token_stream->cursor(), session->mempool);
advance();
}
return start != session->token_stream->cursor();
}
bool Parser::parseFunctionSpecifier(const ListNode<std::size_t> *&node)
{
std::size_t start = session->token_stream->cursor();
int tk;
while (0 != (tk = session->token_stream->lookAhead())
&& (tk == Token_inline || tk == Token_virtual
|| tk == Token_explicit))
{
node = snoc(node, session->token_stream->cursor(), session->mempool);
advance();
}
return start != session->token_stream->cursor();
}
bool Parser::parseTypeId(TypeIdAST *&node)
{
/// @todo implement the AST for typeId
std::size_t start = session->token_stream->cursor();
TypeSpecifierAST *spec = 0;
if (!parseTypeSpecifier(spec))
{
rewind(start);
return false;
}
DeclaratorAST *decl = 0;
parseAbstractDeclarator(decl);
TypeIdAST *ast = CreateNode<TypeIdAST>(session->mempool);
ast->type_specifier = spec;
ast->declarator = decl;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseInitDeclaratorList(const ListNode<InitDeclaratorAST*> *&node)
{
InitDeclaratorAST *decl = 0;
if (!parseInitDeclarator(decl))
return false;
node = snoc(node, decl, session->mempool);
while (session->token_stream->lookAhead() == ',')
{
advance();
if (!parseInitDeclarator(decl))
{
syntaxError();
break;
}
node = snoc(node, decl, session->mempool);
}
return true;
}
bool Parser::parseParameterDeclarationClause(ParameterDeclarationClauseAST *&node)
{
std::size_t start = session->token_stream->cursor();
ParameterDeclarationClauseAST *ast
= CreateNode<ParameterDeclarationClauseAST>(session->mempool);
if (!parseParameterDeclarationList(ast->parameter_declarations))
{
if (session->token_stream->lookAhead() == ')')
goto good;
if (session->token_stream->lookAhead() == Token_ellipsis
&& session->token_stream->lookAhead(1) == ')')
{
ast->ellipsis = session->token_stream->cursor();
goto good;
}
return false;
}
good:
if (session->token_stream->lookAhead() == Token_ellipsis)
{
ast->ellipsis = session->token_stream->cursor();
advance();
}
/// @todo add ellipsis
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseParameterDeclarationList(const ListNode<ParameterDeclarationAST*> *&node)
{
std::size_t start = session->token_stream->cursor();
ParameterDeclarationAST *param = 0;
if (!parseParameterDeclaration(param))
{
rewind(start);
return false;
}
node = snoc(node, param, session->mempool);
while (session->token_stream->lookAhead() == ',')
{
advance();
if (session->token_stream->lookAhead() == Token_ellipsis)
break;
if (!parseParameterDeclaration(param))
{
rewind(start);
return false;
}
node = snoc(node, param, session->mempool);
}
return true;
}
bool Parser::parseParameterDeclaration(ParameterDeclarationAST *&node)
{
std::size_t start = session->token_stream->cursor();
const ListNode<std::size_t> *storage = 0;
parseStorageClassSpecifier(storage);
// parse decl spec
TypeSpecifierAST *spec = 0;
if (!parseTypeSpecifier(spec))
{
rewind(start);
return false;
}
int index = session->token_stream->cursor();
DeclaratorAST *decl = 0;
if (!parseDeclarator(decl))
{
rewind(index);
// try with abstract declarator
parseAbstractDeclarator(decl);
}
ExpressionAST *expr = 0;
if (session->token_stream->lookAhead() == '=')
{
advance();
if (!parseLogicalOrExpression(expr,true))
{
//reportError(("Expression expected"));
}
}
if( session->token_stream->lookAhead() != ',' && session->token_stream->lookAhead() != ')' && session->token_stream->lookAhead() != '>' )
{
//Not a valid parameter declaration
rewind(start);
return false;
}
ParameterDeclarationAST *ast = CreateNode<ParameterDeclarationAST>(session->mempool);
ast->type_specifier = spec;
ast->declarator = decl;
ast->expression = expr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseClassSpecifier(TypeSpecifierAST *&node)
{
std::size_t start = session->token_stream->cursor();
int kind = session->token_stream->lookAhead();
if (kind != Token_class && kind != Token_struct && kind != Token_union)
return false;
std::size_t class_key = session->token_stream->cursor();
advance();
WinDeclSpecAST *winDeclSpec = 0;
parseWinDeclSpec(winDeclSpec);
while (session->token_stream->lookAhead() == Token_identifier
&& session->token_stream->lookAhead(1) == Token_identifier)
{
advance();
}
NameAST *name = 0;
parseName(name, AcceptTemplate);
BaseClauseAST *bases = 0;
if (session->token_stream->lookAhead() == ':')
{
if (!parseBaseClause(bases))
{
skipUntil('{');
}
}
if (session->token_stream->lookAhead() != '{')
{
rewind(start);
return false;
}
ADVANCE('{', "{");
ClassSpecifierAST *ast = CreateNode<ClassSpecifierAST>(session->mempool);
ast->win_decl_specifiers = winDeclSpec;
ast->class_key = class_key;
ast->name = name;
ast->base_clause = bases;
while (session->token_stream->lookAhead())
{
if (session->token_stream->lookAhead() == '}')
break;
std::size_t startDecl = session->token_stream->cursor();
DeclarationAST *memSpec = 0;
if (!parseMemberSpecification(memSpec))
{
if (startDecl == session->token_stream->cursor())
advance(); // skip at least one token
skipUntilDeclaration();
}
else
ast->member_specs = snoc(ast->member_specs, memSpec, session->mempool);
}
clearComment();
ADVANCE_NR('}', "}");
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseAccessSpecifier(DeclarationAST *&node)
{
std::size_t start = session->token_stream->cursor();
const ListNode<std::size_t> *specs = 0;
bool done = false;
while (!done)
{
switch(session->token_stream->lookAhead())
{
case Token_signals:
case Token_slots:
case Token_k_dcop:
case Token_k_dcop_signals:
case Token_public:
case Token_protected:
case Token_private:
specs = snoc(specs, session->token_stream->cursor(), session->mempool);
advance();
break;
default:
done = true;
break;
}
}
if (!specs)
return false;
ADVANCE(':', ":");
AccessSpecifierAST *ast = CreateNode<AccessSpecifierAST>(session->mempool);
ast->specs = specs;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseMemberSpecification(DeclarationAST *&node)
{
std::size_t start = session->token_stream->cursor();
if (session->token_stream->lookAhead() == ';')
{
advance();
return true;
}
else if (session->token_stream->lookAhead() == Token_Q_OBJECT || session->token_stream->lookAhead() == Token_K_DCOP)
{
advance();
return true;
}
else if (parseTypedef(node))
{
return true;
}
else if (parseUsing(node))
{
return true;
}
else if (parseTemplateDeclaration(node))
{
return true;
}
else if (parseAccessSpecifier(node))
{
return true;
}
rewind(start);
const ListNode<std::size_t> *cv = 0;
parseCvQualify(cv);
const ListNode<std::size_t> *storageSpec = 0;
parseStorageClassSpecifier(storageSpec);
parseCvQualify(cv);
Comment mcomment = comment();
clearComment();
TypeSpecifierAST *spec = 0;
if (parseEnumSpecifier(spec) || parseClassSpecifier(spec))
{
parseCvQualify(cv);
spec->cv = cv;
const ListNode<InitDeclaratorAST*> *declarators = 0;
parseInitDeclaratorList(declarators);
ADVANCE(';', ";");
SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(session->mempool);
ast->storage_specifiers = storageSpec;
ast->type_specifier = spec;
ast->init_declarators = declarators;
UPDATE_POS(ast, start, _M_last_valid_token+1);
if( mcomment )
addComment(ast,mcomment);
preparseLineComments(ast->end_token-1);
if( m_commentStore.hasComment() )
addComment( ast, m_commentStore.takeCommentInRange( lineFromTokenNumber( --ast->end_token ) ) );
node = ast;
return true;
} else {
rewind(start);
if( parseDeclarationInternal(node) ) {
//Add the comments to the declaration
if( mcomment )
addComment(node, mcomment);
preparseLineComments(node->end_token-1);
if( m_commentStore.hasComment() )
addComment( node, m_commentStore.takeCommentInRange( lineFromTokenNumber( --node->end_token ) ) );
return true;
}
}
return false;
}
bool Parser::parseCtorInitializer(CtorInitializerAST *&node)
{
std::size_t start = session->token_stream->cursor();
CHECK(':');
CtorInitializerAST *ast = CreateNode<CtorInitializerAST>(session->mempool);
ast->colon = start;
if (!parseMemInitializerList(ast->member_initializers))
{
reportError(("Member initializers expected"));
}
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseElaboratedTypeSpecifier(TypeSpecifierAST *&node)
{
std::size_t start = session->token_stream->cursor();
int tk = session->token_stream->lookAhead();
if (tk == Token_class ||
tk == Token_struct ||
tk == Token_union ||
tk == Token_enum ||
tk == Token_typename)
{
std::size_t type = session->token_stream->cursor();
advance();
NameAST *name = 0;
if (parseName(name, AcceptTemplate))
{
ElaboratedTypeSpecifierAST *ast
= CreateNode<ElaboratedTypeSpecifierAST>(session->mempool);
ast->type = type;
ast->name = name;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
}
rewind(start);
return false;
}
bool Parser::parseExceptionSpecification(ExceptionSpecificationAST *&node)
{
std::size_t start = session->token_stream->cursor();
CHECK(Token_throw);
ADVANCE('(', "(");
ExceptionSpecificationAST *ast
= CreateNode<ExceptionSpecificationAST>(session->mempool);
if (session->token_stream->lookAhead() == Token_ellipsis)
{
ast->ellipsis = session->token_stream->cursor();
advance();
}
else
{
parseTypeIdList(ast->type_ids);
}
ADVANCE(')', ")");
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseEnumerator(EnumeratorAST *&node)
{
std::size_t start = session->token_stream->cursor();
CHECK(Token_identifier);
std::size_t id = start;
EnumeratorAST *ast = CreateNode<EnumeratorAST>(session->mempool);
ast->id = id;
if (session->token_stream->lookAhead() == '=')
{
advance();
if (!parseConstantExpression(ast->expression))
{
reportError(("Constant expression expected"));
}
}
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
moveComments(node);
preparseLineComments( ast->end_token-1 );
if( m_commentStore.hasComment() )
addComment( node, m_commentStore.takeCommentInRange( lineFromTokenNumber(--ast->end_token) ) );
return true;
}
bool Parser::parseInitDeclarator(InitDeclaratorAST *&node)
{
std::size_t start = session->token_stream->cursor();
DeclaratorAST *decl = 0;
if (!parseDeclarator(decl))
{
return false;
}
if (session->token_stream->lookAhead(0) == Token_asm)
{
advance();
skip('(', ')');
advance();
}
InitializerAST *init = 0;
parseInitializer(init);
InitDeclaratorAST *ast = CreateNode<InitDeclaratorAST>(session->mempool);
ast->declarator = decl;
ast->initializer = init;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseBaseClause(BaseClauseAST *&node)
{
std::size_t start = session->token_stream->cursor();
CHECK(':');
BaseSpecifierAST *baseSpec = 0;
if (!parseBaseSpecifier(baseSpec))
return false;
BaseClauseAST *ast = CreateNode<BaseClauseAST>(session->mempool);
ast->base_specifiers = snoc(ast->base_specifiers, baseSpec, session->mempool);
while (session->token_stream->lookAhead() == ',')
{
advance();
if (!parseBaseSpecifier(baseSpec))
{
reportError(("Base class specifier expected"));
break;
}
ast->base_specifiers = snoc(ast->base_specifiers, baseSpec, session->mempool);
}
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseInitializer(InitializerAST *&node)
{
std::size_t start = session->token_stream->cursor();
int tk = session->token_stream->lookAhead();
if (tk != '=' && tk != '(')
return false;
InitializerAST *ast = CreateNode<InitializerAST>(session->mempool);
if (tk == '=')
{
advance();
if (!parseInitializerClause(ast->initializer_clause))
{
reportError(("Initializer clause expected"));
}
}
else if (tk == '(')
{
advance();
parseCommaExpression(ast->expression);
CHECK(')');
}
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseMemInitializerList(const ListNode<MemInitializerAST*> *&node)
{
MemInitializerAST *init = 0;
if (!parseMemInitializer(init))
return false;
node = snoc(node, init, session->mempool);
while (session->token_stream->lookAhead() == ',')
{
advance();
if (!parseMemInitializer(init))
break;
node = snoc(node, init, session->mempool);
}
return true;
}
bool Parser::parseMemInitializer(MemInitializerAST *&node)
{
std::size_t start = session->token_stream->cursor();
NameAST *initId = 0;
if (!parseName(initId, AcceptTemplate))
{
reportError(("Identifier expected"));
return false;
}
ADVANCE('(', "(");
ExpressionAST *expr = 0;
parseCommaExpression(expr);
ADVANCE(')', ")");
MemInitializerAST *ast = CreateNode<MemInitializerAST>(session->mempool);
ast->initializer_id = initId;
ast->expression = expr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseTypeIdList(const ListNode<TypeIdAST*> *&node)
{
TypeIdAST *typeId = 0;
if (!parseTypeId(typeId))
return false;
node = snoc(node, typeId, session->mempool);
while (session->token_stream->lookAhead() == ',')
{
advance();
if (parseTypeId(typeId))
{
node = snoc(node, typeId, session->mempool);
}
else
{
reportError(("Type id expected"));
break;
}
}
return true;
}
bool Parser::parseBaseSpecifier(BaseSpecifierAST *&node)
{
std::size_t start = session->token_stream->cursor();
BaseSpecifierAST *ast = CreateNode<BaseSpecifierAST>(session->mempool);
if (session->token_stream->lookAhead() == Token_virtual)
{
ast->virt = session->token_stream->cursor();
advance();
int tk = session->token_stream->lookAhead();
if (tk == Token_public || tk == Token_protected
|| tk == Token_private)
{
ast->access_specifier = session->token_stream->cursor();
advance();
}
}
else
{
int tk = session->token_stream->lookAhead();
if (tk == Token_public || tk == Token_protected
|| tk == Token_private)
{
ast->access_specifier = session->token_stream->cursor();
advance();
}
if (session->token_stream->lookAhead() == Token_virtual)
{
ast->virt = session->token_stream->cursor();
advance();
}
}
if (!parseName(ast->name, AcceptTemplate))
reportError(("Class name expected"));
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseInitializerList(const ListNode<InitializerClauseAST*> *&node)
{
const ListNode<InitializerClauseAST*> *list = 0;
do
{
if (list)
advance(); // skip ',' separator between clauses
InitializerClauseAST *init_clause = 0;
if (!parseInitializerClause(init_clause))
{
return false;
}
list = snoc(list,init_clause,session->mempool);
} while (session->token_stream->lookAhead() == ',');
node = list;
return true;
}
bool Parser::parseInitializerClause(InitializerClauseAST *&node)
{
std::size_t start = session->token_stream->cursor();
InitializerClauseAST *ast = CreateNode<InitializerClauseAST>(session->mempool);
if (session->token_stream->lookAhead() == '{')
{
advance();
const ListNode<InitializerClauseAST*> *initializer_list = 0;
if (session->token_stream->lookAhead() != '}' &&
!parseInitializerList(initializer_list))
{
return false;
}
ADVANCE('}',"}");
ast->initializer_list = initializer_list;
}
else
{
if (!parseAssignmentExpression(ast->expression))
{
reportError("Expression expected");
return false;
}
}
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parsePtrToMember(PtrToMemberAST *&node)
{
#if defined(__GNUC__)
#warning "implemente me (AST)"
#endif
std::size_t start = session->token_stream->cursor();
std::size_t global_scope = 0;
if (session->token_stream->lookAhead() == Token_scope)
{
global_scope = session->token_stream->cursor();
advance();
}
UnqualifiedNameAST *name = 0;
while (session->token_stream->lookAhead() == Token_identifier)
{
if (!parseUnqualifiedName(name))
break;
if (session->token_stream->lookAhead() == Token_scope
&& session->token_stream->lookAhead(1) == '*')
{
advance();
advance();
PtrToMemberAST *ast = CreateNode<PtrToMemberAST>(session->mempool);
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
if (session->token_stream->lookAhead() == Token_scope)
advance();
}
rewind(start);
return false;
}
bool Parser::parseUnqualifiedName(UnqualifiedNameAST *&node,
bool parseTemplateId)
{
std::size_t start = session->token_stream->cursor();
std::size_t tilde = 0;
std::size_t id = 0;
OperatorFunctionIdAST *operator_id = 0;
if (session->token_stream->lookAhead() == Token_identifier)
{
id = session->token_stream->cursor();
advance();
}
else if (session->token_stream->lookAhead() == '~'
&& session->token_stream->lookAhead(1) == Token_identifier)
{
tilde = session->token_stream->cursor();
advance(); // skip ~
id = session->token_stream->cursor();
advance(); // skip classname
}
else if (session->token_stream->lookAhead() == Token_operator)
{
if (!parseOperatorFunctionId(operator_id))
return false;
}
else
{
return false;
}
UnqualifiedNameAST *ast = CreateNode<UnqualifiedNameAST>(session->mempool);
ast->tilde = tilde;
ast->id = id;
ast->operator_id = operator_id;
if (parseTemplateId && !tilde)
{
std::size_t index = session->token_stream->cursor();
if (session->token_stream->lookAhead() == '<' && !(tokenMarkers(index) & IsNoTemplateArgumentList))
{
advance();
// optional template arguments
parseTemplateArgumentList(ast->template_arguments);
if (session->token_stream->lookAhead() == '>')
{
advance();
}
else
{
addTokenMarkers(index, IsNoTemplateArgumentList);
ast->template_arguments = 0;
rewind(index);
}
}
}
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseStringLiteral(StringLiteralAST *&node)
{
std::size_t start = session->token_stream->cursor();
if (session->token_stream->lookAhead() != Token_string_literal)
return false;
StringLiteralAST *ast = CreateNode<StringLiteralAST>(session->mempool);
while (session->token_stream->lookAhead() == Token_string_literal)
{
ast->literals = snoc(ast->literals, session->token_stream->cursor(), session->mempool);
advance();
}
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseExpressionStatement(StatementAST *&node)
{
std::size_t start = session->token_stream->cursor();
ExpressionAST *expr = 0;
parseCommaExpression(expr);
ADVANCE(';', ";");
ExpressionStatementAST *ast = CreateNode<ExpressionStatementAST>(session->mempool);
ast->expression = expr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseJumpStatement(StatementAST *&node)
{
std::size_t op = session->token_stream->cursor();
std::size_t kind = session->token_stream->lookAhead();
std::size_t identifier = 0;
if (kind != Token_break && kind != Token_continue && kind != Token_goto)
return false;
advance();
if (kind == Token_goto)
{
ADVANCE(Token_identifier,"label");
identifier = op+1;
}
ADVANCE(';',";");
JumpStatementAST* ast = CreateNode<JumpStatementAST>(session->mempool);
ast->op = op;
ast->identifier = identifier;
UPDATE_POS(ast,ast->op,_M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseStatement(StatementAST *&node)
{
std::size_t start = session->token_stream->cursor();
switch(session->token_stream->lookAhead())
{
case Token_while:
return parseWhileStatement(node);
case Token_do:
return parseDoStatement(node);
case Token_for:
return parseForStatement(node);
case Token_if:
return parseIfStatement(node);
case Token_switch:
return parseSwitchStatement(node);
case Token_try:
return parseTryBlockStatement(node);
case Token_case:
case Token_default:
return parseLabeledStatement(node);
case Token_break:
case Token_continue:
case Token_goto:
return parseJumpStatement(node);
case Token_return:
{
advance();
ExpressionAST *expr = 0;
parseCommaExpression(expr);
ADVANCE(';', ";");
ReturnStatementAST *ast = CreateNode<ReturnStatementAST>(session->mempool);
ast->expression = expr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
case '{':
return parseCompoundStatement(node);
case Token_identifier:
if (parseLabeledStatement(node))
return true;
break;
}
return parseExpressionOrDeclarationStatement(node);
}
bool Parser::parseExpressionOrDeclarationStatement(StatementAST *&node)
{
// hold any errors while the expression/declaration ambiguity is resolved
// for this statement
bool hold = holdErrors(true);
std::size_t start = session->token_stream->cursor();
///@todo solve -1 thing
StatementAST *decl_ast = 0;
bool maybe_amb = parseDeclarationStatement(decl_ast);
maybe_amb &= session->token_stream->kind(session->token_stream->cursor() - 1) == ';';
// if parsing as a declaration succeeded, then any pending errors are genuine.
// Otherwise this is not a declaration so ignore the errors.
if (decl_ast)
reportPendingErrors();
else
m_pendingErrors.clear();
std::size_t end = session->token_stream->cursor();
rewind(start);
StatementAST *expr_ast = 0;
maybe_amb &= parseExpressionStatement(expr_ast);
maybe_amb &= session->token_stream->kind(session->token_stream->cursor() - 1) == ';';
// if parsing as an expression succeeded, then any pending errors are genuine.
// Otherwise this is not an expression so ignore the errors.
if (expr_ast)
reportPendingErrors();
else
m_pendingErrors.clear();
if (maybe_amb)
{
Q_ASSERT(decl_ast != 0 && expr_ast != 0);
ExpressionOrDeclarationStatementAST *ast
= CreateNode<ExpressionOrDeclarationStatementAST>(session->mempool);
ast->declaration = decl_ast;
ast->expression = expr_ast;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
else
{
rewind(std::max(end, session->token_stream->cursor()));
node = decl_ast;
if (!node)
node = expr_ast;
}
holdErrors(hold);
if (!node)
syntaxError();
return node != 0;
}
bool Parser::parseCondition(ConditionAST *&node, bool initRequired)
{
std::size_t start = session->token_stream->cursor();
ConditionAST *ast = CreateNode<ConditionAST>(session->mempool);
TypeSpecifierAST *spec = 0;
if (parseTypeSpecifier(spec))
{
ast->type_specifier = spec;
std::size_t declarator_start = session->token_stream->cursor();
DeclaratorAST *decl = 0;
if (!parseDeclarator(decl))
{
rewind(declarator_start);
if (!initRequired && !parseAbstractDeclarator(decl))
decl = 0;
}
if (decl && (!initRequired || session->token_stream->lookAhead() == '='))
{
ast->declarator = decl;
if (session->token_stream->lookAhead() == '=')
{
advance();
parseExpression(ast->expression);
}
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
}
ast->type_specifier = 0;
rewind(start);
if (!parseCommaExpression(ast->expression)) {
return false;
}
Q_ASSERT(ast->expression);
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseWhileStatement(StatementAST *&node)
{
std::size_t start = session->token_stream->cursor();
ADVANCE(Token_while, "while");
ADVANCE('(' , "(");
ConditionAST *cond = 0;
if (!parseCondition(cond))
{
reportError("Condition expected");
return false;
}
ADVANCE(')', ")");
StatementAST *body = 0;
if (!parseStatement(body))
{
reportError("Statement expected");
return false;
}
WhileStatementAST *ast = CreateNode<WhileStatementAST>(session->mempool);
ast->condition = cond;
ast->statement = body;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseDoStatement(StatementAST *&node)
{
std::size_t start = session->token_stream->cursor();
ADVANCE(Token_do, "do");
StatementAST *body = 0;
if (!parseStatement(body))
{
reportError(("Statement expected"));
//return false;
}
ADVANCE_NR(Token_while, "while");
ADVANCE_NR('(' , "(");
ExpressionAST *expr = 0;
if (!parseCommaExpression(expr))
{
reportError(("Expression expected"));
//return false;
}
ADVANCE_NR(')', ")");
ADVANCE_NR(';', ";");
DoStatementAST *ast = CreateNode<DoStatementAST>(session->mempool);
ast->statement = body;
ast->expression = expr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseForStatement(StatementAST *&node)
{
std::size_t start = session->token_stream->cursor();
ADVANCE(Token_for, "for");
ADVANCE('(', "(");
StatementAST *init = 0;
if (!parseForInitStatement(init))
{
reportError(("'for' initialization expected"));
return false;
}
ConditionAST *cond = 0;
parseCondition(cond);
ADVANCE(';', ";");
ExpressionAST *expr = 0;
parseCommaExpression(expr);
ADVANCE(')', ")");
StatementAST *body = 0;
if (!parseStatement(body))
return false;
ForStatementAST *ast = CreateNode<ForStatementAST>(session->mempool);
ast->init_statement = init;
ast->condition = cond;
ast->expression = expr;
ast->statement = body;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseForInitStatement(StatementAST *&node)
{
if (parseDeclarationStatement(node))
return true;
return parseExpressionStatement(node);
}
bool Parser::parseCompoundStatement(StatementAST *&node)
{
std::size_t start = session->token_stream->cursor();
CHECK('{');
CompoundStatementAST *ast = CreateNode<CompoundStatementAST>(session->mempool);
while (session->token_stream->lookAhead())
{
if (session->token_stream->lookAhead() == '}')
break;
std::size_t startStmt = session->token_stream->cursor();
StatementAST *stmt = 0;
if (!parseStatement(stmt))
{
if (startStmt == session->token_stream->cursor())
advance();
skipUntilStatement();
}
else
{
ast->statements = snoc(ast->statements, stmt, session->mempool);
}
}
clearComment();
ADVANCE_NR('}', "}");
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseIfStatement(StatementAST *&node)
{
std::size_t start = session->token_stream->cursor();
ADVANCE(Token_if, "if");
ADVANCE('(' , "(");
IfStatementAST *ast = CreateNode<IfStatementAST>(session->mempool);
ConditionAST *cond = 0;
if (!parseCondition(cond))
{
reportError(("Condition expected"));
return false;
}
ADVANCE(')', ")");
StatementAST *stmt = 0;
if (!parseStatement(stmt))
{
reportError(("Statement expected"));
return false;
}
ast->condition = cond;
ast->statement = stmt;
if (session->token_stream->lookAhead() == Token_else)
{
advance();
if (!parseStatement(ast->else_statement))
{
reportError(("Statement expected"));
return false;
}
}
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseSwitchStatement(StatementAST *&node)
{
std::size_t start = session->token_stream->cursor();
ADVANCE(Token_switch, "switch");
ADVANCE('(' , "(");
ConditionAST *cond = 0;
if (!parseCondition(cond))
{
reportError(("Condition expected"));
return false;
}
ADVANCE(')', ")");
StatementAST *stmt = 0;
if (!parseCompoundStatement(stmt))
{
syntaxError();
return false;
}
SwitchStatementAST *ast = CreateNode<SwitchStatementAST>(session->mempool);
ast->condition = cond;
ast->statement = stmt;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseLabeledStatement(StatementAST *&node)
{
switch(session->token_stream->lookAhead())
{
case Token_identifier:
case Token_default:
{
std::size_t start = session->token_stream->cursor();
if (session->token_stream->lookAhead(1) == ':')
{
advance();
advance();
StatementAST *stmt = 0;
if (parseStatement(stmt))
{
LabeledStatementAST* ast = CreateNode<LabeledStatementAST>(session->mempool);
ast->label = start;
ast->statement = stmt;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
}
break;
}
case Token_case:
{
std::size_t start = session->token_stream->cursor();
advance();
ExpressionAST *expr = 0;
if (!parseConstantExpression(expr))
{
reportError(("Expression expected"));
}
else if (session->token_stream->lookAhead() == Token_ellipsis)
{
advance();
if (!parseConstantExpression(expr))
{
reportError(("Expression expected"));
}
}
ADVANCE(':', ":");
LabeledStatementAST* ast = CreateNode<LabeledStatementAST>(session->mempool);
ast->label = start;
ast->expression = expr;
parseStatement(ast->statement);
if(ast->expression || ast->statement) {
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
}
break;
}
return false;
}
bool Parser::parseBlockDeclaration(DeclarationAST *&node)
{
switch(session->token_stream->lookAhead())
{
case Token_typedef:
return parseTypedef(node);
case Token_using:
return parseUsing(node);
case Token_asm:
return parseAsmDefinition(node);
case Token_namespace:
return parseNamespaceAliasDefinition(node);
}
Comment mcomment = comment();
clearComment();
std::size_t start = session->token_stream->cursor();
const ListNode<std::size_t> *cv = 0;
parseCvQualify(cv);
const ListNode<std::size_t> *storageSpec = 0;
parseStorageClassSpecifier(storageSpec);
parseCvQualify(cv);
TypeSpecifierAST *spec = 0;
if (!parseTypeSpecifierOrClassSpec(spec))
{ // replace with simpleTypeSpecifier?!?!
rewind(start);
return false;
}
parseCvQualify(cv);
spec->cv = cv;
const ListNode<InitDeclaratorAST*> *declarators = 0;
parseInitDeclaratorList(declarators);
if (session->token_stream->lookAhead() != ';')
{
rewind(start);
return false;
}
advance();
SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(session->mempool);
ast->type_specifier = spec;
ast->init_declarators = declarators;
if(mcomment)
addComment(ast, mcomment);
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseNamespaceAliasDefinition(DeclarationAST *&node)
{
std::size_t start = session->token_stream->cursor();
CHECK(Token_namespace);
NamespaceAliasDefinitionAST *ast
= CreateNode<NamespaceAliasDefinitionAST>(session->mempool);
size_t pos = session->token_stream->cursor();
ADVANCE(Token_identifier, "identifier");
ast->namespace_name = pos;
ADVANCE('=', "=");
if (!parseName(ast->alias_name))
{
reportError(("Namespace name expected"));
}
ADVANCE(';', ";");
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseDeclarationStatement(StatementAST *&node)
{
std::size_t start = session->token_stream->cursor();
DeclarationAST *decl = 0;
if (!parseBlockDeclaration(decl))
return false;
DeclarationStatementAST *ast = CreateNode<DeclarationStatementAST>(session->mempool);
ast->declaration = decl;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseDeclarationInternal(DeclarationAST *&node)
{
std::size_t start = session->token_stream->cursor();
// that is for the case '__declspec(dllexport) int ...' or
// '__declspec(dllexport) inline int ...', etc.
WinDeclSpecAST *winDeclSpec = 0;
parseWinDeclSpec(winDeclSpec);
const ListNode<std::size_t> *funSpec = 0;
bool hasFunSpec = parseFunctionSpecifier(funSpec);
const ListNode<std::size_t> *cv = 0;
parseCvQualify(cv);
const ListNode<std::size_t> *storageSpec = 0;
bool hasStorageSpec = parseStorageClassSpecifier(storageSpec);
// needed here for 'friend __declspec(dllimport) inline ...'
if (!winDeclSpec)
parseWinDeclSpec(winDeclSpec);
if (hasStorageSpec && !hasFunSpec)
hasFunSpec = parseFunctionSpecifier(funSpec);
// that is for the case 'friend __declspec(dllexport) ....'
if (!winDeclSpec)
parseWinDeclSpec(winDeclSpec);
if (!cv)
parseCvQualify(cv);
int index = session->token_stream->cursor();
NameAST *name = 0;
if (parseName(name, AcceptTemplate) && session->token_stream->lookAhead() == '(')
{
// no type specifier, maybe a constructor or a cast operator??
rewind(index);
InitDeclaratorAST *declarator = 0;
if (parseInitDeclarator(declarator))
{
switch(session->token_stream->lookAhead())
{
case ';':
{
advance();
SimpleDeclarationAST *ast
= CreateNode<SimpleDeclarationAST>(session->mempool);
ast->init_declarators = snoc(ast->init_declarators,
declarator, session->mempool);
ast->function_specifiers = funSpec;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
case ':':
{
CtorInitializerAST *ctorInit = 0;
StatementAST *funBody = 0;
if (parseCtorInitializer(ctorInit)
&& parseFunctionBody(funBody))
{
FunctionDefinitionAST *ast
= CreateNode<FunctionDefinitionAST>(session->mempool);
ast->storage_specifiers = storageSpec;
ast->function_specifiers = funSpec;
ast->init_declarator = declarator;
ast->function_body = funBody;
ast->constructor_initializers = ctorInit;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
}
break;
case Token_try:
case '{':
{
StatementAST *funBody = 0;
if (parseFunctionBody(funBody))
{
FunctionDefinitionAST *ast
= CreateNode<FunctionDefinitionAST>(session->mempool);
generator/parser/parser.cpp view on Meta::CPAN
node = ast;
return true;
}
}
break;
case '(':
case '[':
// ops!! it seems a declarator
goto start_decl;
break;
}
}
}
start_decl:
rewind(index);
if (session->token_stream->lookAhead() == Token_const
&& session->token_stream->lookAhead(1) == Token_identifier
&& session->token_stream->lookAhead(2) == '=')
{
// constant definition
advance(); // skip const
const ListNode<InitDeclaratorAST*> *declarators = 0;
if (!parseInitDeclaratorList(declarators))
{
syntaxError();
return false;
}
ADVANCE(';', ";");
#if defined(__GNUC__)
#warning "mark the ast as constant"
#endif
SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(session->mempool);
ast->init_declarators = declarators;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
TypeSpecifierAST *spec = 0;
if (parseTypeSpecifier(spec))
{
Q_ASSERT(spec != 0);
if (!hasFunSpec)
parseFunctionSpecifier(funSpec); // e.g. "void inline"
spec->cv = cv;
const ListNode<InitDeclaratorAST*> *declarators = 0;
InitDeclaratorAST *decl = 0;
int startDeclarator = session->token_stream->cursor();
bool maybeFunctionDefinition = false;
if (session->token_stream->lookAhead() != ';')
{
if (parseInitDeclarator(decl) && (session->token_stream->lookAhead() == '{' || session->token_stream->lookAhead() == Token_try))
{
// function definition
maybeFunctionDefinition = true;
}
else
{
rewind(startDeclarator);
if (!parseInitDeclaratorList(declarators))
{
syntaxError();
return false;
}
}
}
switch(session->token_stream->lookAhead())
{
case ';':
{
advance();
SimpleDeclarationAST *ast
= CreateNode<SimpleDeclarationAST>(session->mempool);
ast->storage_specifiers = storageSpec;
ast->function_specifiers = funSpec;
ast->type_specifier = spec;
ast->win_decl_specifiers = winDeclSpec;
ast->init_declarators = declarators;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
case Token_try:
case '{':
{
if (!maybeFunctionDefinition)
{
syntaxError();
return false;
}
StatementAST *funBody = 0;
if (parseFunctionBody(funBody))
{
FunctionDefinitionAST *ast
= CreateNode<FunctionDefinitionAST>(session->mempool);
ast->win_decl_specifiers = winDeclSpec;
ast->storage_specifiers = storageSpec;
ast->function_specifiers = funSpec;
ast->type_specifier = spec;
ast->init_declarator = decl;
ast->function_body = funBody;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
}
break;
} // end switch
}
syntaxError();
return false;
}
bool Parser::parseFunctionBody(StatementAST *&node)
{
if (session->token_stream->lookAhead() == Token_try)
return parseTryBlockStatement(node);
return parseCompoundStatement(node);
}
bool Parser::parseTypeSpecifierOrClassSpec(TypeSpecifierAST *&node)
{
if (parseClassSpecifier(node))
return true;
else if (parseEnumSpecifier(node))
return true;
else if (parseTypeSpecifier(node))
return true;
return false;
}
bool Parser::parseTryBlockStatement(StatementAST *&node)
{
std::size_t start = session->token_stream->cursor();
CHECK(Token_try);
TryBlockStatementAST *ast = CreateNode<TryBlockStatementAST>(session->mempool);
StatementAST *stmt = 0;
if (!parseCompoundStatement(stmt))
{
syntaxError();
return false;
}
ast->try_block = stmt;
if (session->token_stream->lookAhead() != Token_catch)
{
reportError(("'catch' expected after try block"));
return false;
}
while (session->token_stream->lookAhead() == Token_catch)
{
std::size_t catchStart = session->token_stream->cursor();
advance();
ADVANCE('(', "(");
ConditionAST *cond = 0;
if (session->token_stream->lookAhead() == Token_ellipsis)
{
advance();
}
else if(session->token_stream->lookAhead() == ')') {
//Do nothing, this is equivalent to ellipsis
} else if (!parseCondition(cond, false))
{
reportError(("condition expected"));
return false;
}
ADVANCE(')', ")");
StatementAST *body = 0;
if (!parseCompoundStatement(body))
{
syntaxError();
return false;
}
CatchStatementAST *catch_ast = CreateNode<CatchStatementAST>(session->mempool);
catch_ast->condition = cond;
catch_ast->statement = body;
UPDATE_POS(catch_ast, catchStart, _M_last_valid_token+1);
ast->catch_blocks = snoc(ast->catch_blocks, catch_ast, session->mempool);
}
node = ast;
UPDATE_POS(ast, start, _M_last_valid_token+1);
return true;
}
bool Parser::parsePrimaryExpression(ExpressionAST *&node)
{
std::size_t start = session->token_stream->cursor();
PrimaryExpressionAST *ast = CreateNode<PrimaryExpressionAST>(session->mempool);
switch(session->token_stream->lookAhead())
{
case Token_string_literal:
parseStringLiteral(ast->literal);
break;
case Token_number_literal:
case Token_char_literal:
case Token_true:
case Token_false:
case Token_this:
ast->token = session->token_stream->cursor();
advance();
break;
case '(':
advance();
if (session->token_stream->lookAhead() == '{')
{
if (!parseCompoundStatement(ast->expression_statement))
return false;
}
else
{
if (!parseExpression(ast->sub_expression))
return false;
}
CHECK(')');
break;
default:
if (!parseName(ast->name, EventuallyAcceptTemplate))
return false;
break;
}
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
/*
postfix-expression-internal:
[ expression ]
( expression-list [opt] )
(.|->) template [opt] id-expression
(.|->) pseudo-destructor-name
++
--
*/
bool Parser::parsePostfixExpressionInternal(ExpressionAST *&node)
{
std::size_t start = session->token_stream->cursor();
switch (session->token_stream->lookAhead())
{
case '[':
{
advance();
ExpressionAST *expr = 0;
parseExpression(expr);
CHECK(']');
SubscriptExpressionAST *ast
= CreateNode<SubscriptExpressionAST>(session->mempool);
ast->subscript = expr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
case '(':
{
advance();
ExpressionAST *expr = 0;
parseExpression(expr);
CHECK(')');
FunctionCallAST *ast = CreateNode<FunctionCallAST>(session->mempool);
ast->arguments = expr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
case '.':
case Token_arrow:
{
std::size_t op = session->token_stream->cursor();
advance();
// std::size_t templ = 0;
// if (session->token_stream->lookAhead() == Token_template)
// {
// templ = session->token_stream->cursor();
// advance();
// }
NameAST *name = 0;
if (!parseName(name, EventuallyAcceptTemplate))
return false;
ClassMemberAccessAST *ast = CreateNode<ClassMemberAccessAST>(session->mempool);
ast->op = op;
ast->name = name;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
case Token_incr:
case Token_decr:
{
std::size_t op = session->token_stream->cursor();
advance();
IncrDecrExpressionAST *ast = CreateNode<IncrDecrExpressionAST>(session->mempool);
ast->op = op;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
default:
return false;
}
}
/*
postfix-expression:
simple-type-specifier ( expression-list [opt] )
primary-expression postfix-expression-internal*
*/
bool Parser::parsePostfixExpression(ExpressionAST *&node)
{
std::size_t start = session->token_stream->cursor();
switch (session->token_stream->lookAhead())
{
case Token_dynamic_cast:
case Token_static_cast:
case Token_reinterpret_cast:
case Token_const_cast:
{
std::size_t castOp = session->token_stream->cursor();
advance();
CHECK('<');
TypeIdAST *typeId = 0;
parseTypeId(typeId);
CHECK('>');
CHECK('(');
ExpressionAST *expr = 0;
parseCommaExpression(expr);
CHECK(')');
CppCastExpressionAST *ast = CreateNode<CppCastExpressionAST>(session->mempool);
ast->op = castOp;
ast->type_id = typeId;
ast->expression = expr;
ExpressionAST *e = 0;
while (parsePostfixExpressionInternal(e))
{
ast->sub_expressions = snoc(ast->sub_expressions, e, session->mempool);
}
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
case Token_typename:
{
std::size_t token = session->token_stream->cursor();
advance();
NameAST* name = 0;
if (!parseName(name, AcceptTemplate))
return false;
CHECK('(');
ExpressionAST *expr = 0;
parseCommaExpression(expr);
CHECK(')');
TypeIdentificationAST *ast = CreateNode<TypeIdentificationAST>(session->mempool);
ast->typename_token = token;
ast->name = name;
ast->expression = expr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
case Token_typeid:
{
advance();
CHECK('(');
TypeIdAST *typeId = 0;
parseTypeId(typeId);
CHECK(')');
TypeIdentificationAST *ast = CreateNode<TypeIdentificationAST>(session->mempool);
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
default:
break;
}
std::size_t saved_pos = session->token_stream->cursor();
TypeSpecifierAST *typeSpec = 0;
ExpressionAST *expr = 0;
// let's try to parse a type
NameAST *name = 0;
if (parseName(name, AcceptTemplate))
{
Q_ASSERT(name->unqualified_name != 0);
bool has_template_args
= name->unqualified_name->template_arguments != 0;
if (has_template_args && session->token_stream->lookAhead() == '(')
{
ExpressionAST *cast_expr = 0;
if (parseCastExpression(cast_expr)
&& cast_expr->kind == AST::Kind_CastExpression)
{
rewind(saved_pos);
parsePrimaryExpression(expr);
goto L_no_rewind;
}
}
}
rewind(saved_pos);
L_no_rewind:
if (!expr && parseSimpleTypeSpecifier(typeSpec,true)
&& session->token_stream->lookAhead() == '(')
{
advance(); // skip '('
parseCommaExpression(expr);
CHECK(')');
}
else if (expr)
{
typeSpec = 0;
}
else
{
typeSpec = 0;
rewind(start);
if (!parsePrimaryExpression(expr))
return false;
}
const ListNode<ExpressionAST*> *sub_expressions = 0;
ExpressionAST *sub_expression = 0;
while (parsePostfixExpressionInternal(sub_expression))
{
sub_expressions = snoc(sub_expressions, sub_expression, session->mempool);
}
node = expr;
if (sub_expressions || !node)
{
PostfixExpressionAST *ast = CreateNode<PostfixExpressionAST>(session->mempool);
ast->type_specifier = typeSpec;
ast->expression = expr;
ast->sub_expressions = sub_expressions;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
}
bool Parser::parseUnaryExpression(ExpressionAST *&node)
{
std::size_t start = session->token_stream->cursor();
switch(session->token_stream->lookAhead())
{
case Token_incr:
case Token_decr:
case '*':
case '&':
case '+':
case '-':
case '!':
case Token_not:
case '~':
{
std::size_t op = session->token_stream->cursor();
advance();
ExpressionAST *expr = 0;
if (!parseCastExpression(expr))
return false;
UnaryExpressionAST *ast = CreateNode<UnaryExpressionAST>(session->mempool);
ast->op = op;
ast->expression = expr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
case Token_sizeof:
{
std::size_t sizeof_token = session->token_stream->cursor();
advance();
SizeofExpressionAST *ast = CreateNode<SizeofExpressionAST>(session->mempool);
ast->sizeof_token = sizeof_token;
std::size_t index = session->token_stream->cursor();
if (session->token_stream->lookAhead() == '(')
{
advance();
if (parseTypeId(ast->type_id) && session->token_stream->lookAhead() == ')')
{
advance(); // skip )
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
ast->type_id = 0;
rewind(index);
}
if (!parseUnaryExpression(ast->expression))
return false;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
default:
break;
}
int token = session->token_stream->lookAhead();
if (token == Token_new
|| (token == Token_scope && session->token_stream->lookAhead(1) == Token_new))
return parseNewExpression(node);
if (token == Token_delete
|| (token == Token_scope && session->token_stream->lookAhead(1) == Token_delete))
return parseDeleteExpression(node);
return parsePostfixExpression(node);
}
bool Parser::parseNewExpression(ExpressionAST *&node)
{
std::size_t start = session->token_stream->cursor();
NewExpressionAST *ast = CreateNode<NewExpressionAST>(session->mempool);
if (session->token_stream->lookAhead() == Token_scope
&& session->token_stream->lookAhead(1) == Token_new)
{
ast->scope_token = session->token_stream->cursor();
advance();
}
size_t pos = session->token_stream->cursor();
CHECK(Token_new);
ast->new_token = pos;
if (session->token_stream->lookAhead() == '(')
{
advance();
parseCommaExpression(ast->expression);
CHECK(')');
}
if (session->token_stream->lookAhead() == '(')
{
advance();
parseTypeId(ast->type_id);
CHECK(')');
}
else
{
parseNewTypeId(ast->new_type_id);
}
parseNewInitializer(ast->new_initializer);
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseNewTypeId(NewTypeIdAST *&node)
{
std::size_t start = session->token_stream->cursor();
TypeSpecifierAST *typeSpec = 0;
if (!parseTypeSpecifier(typeSpec))
return false;
NewTypeIdAST *ast = CreateNode<NewTypeIdAST>(session->mempool);
ast->type_specifier = typeSpec;
parseNewDeclarator(ast->new_declarator);
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseNewDeclarator(NewDeclaratorAST *&node)
{
std::size_t start = session->token_stream->cursor();
NewDeclaratorAST *ast = CreateNode<NewDeclaratorAST>(session->mempool);
PtrOperatorAST *ptrOp = 0;
if (parsePtrOperator(ptrOp))
{
ast->ptr_op = ptrOp;
parseNewDeclarator(ast->sub_declarator);
}
while (session->token_stream->lookAhead() == '[')
{
advance();
ExpressionAST *expr = 0;
parseExpression(expr);
ast->expressions = snoc(ast->expressions, expr, session->mempool);
ADVANCE(']', "]");
}
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseNewInitializer(NewInitializerAST *&node)
{
std::size_t start = session->token_stream->cursor();
CHECK('(');
NewInitializerAST *ast = CreateNode<NewInitializerAST>(session->mempool);
parseCommaExpression(ast->expression);
CHECK(')');
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseDeleteExpression(ExpressionAST *&node)
{
std::size_t start = session->token_stream->cursor();
DeleteExpressionAST *ast = CreateNode<DeleteExpressionAST>(session->mempool);
if (session->token_stream->lookAhead() == Token_scope
&& session->token_stream->lookAhead(1) == Token_delete)
{
ast->scope_token = session->token_stream->cursor();
advance();
}
size_t pos = session->token_stream->cursor();
CHECK(Token_delete);
ast->delete_token = pos;
if (session->token_stream->lookAhead() == '[')
{
ast->lbracket_token = session->token_stream->cursor();
advance();
size_t pos = session->token_stream->cursor();
CHECK(']');
ast->rbracket_token = pos;
}
if (!parseCastExpression(ast->expression))
return false;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::parseCastExpression(ExpressionAST *&node)
{
std::size_t start = session->token_stream->cursor();
if (session->token_stream->lookAhead() == '(')
{
advance();
CastExpressionAST *ast = CreateNode<CastExpressionAST>(session->mempool);
if (parseTypeId(ast->type_id))
{
if (session->token_stream->lookAhead() == ')')
{
advance();
if (parseCastExpression(ast->expression))
{
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
}
}
}
rewind(start);
return parseUnaryExpression(node);
}
bool Parser::parsePmExpression(ExpressionAST *&node)
{
std::size_t start = session->token_stream->cursor();
if (!parseCastExpression(node) || !node) // ### fixme
return false;
while (session->token_stream->lookAhead() == Token_ptrmem)
{
std::size_t op = session->token_stream->cursor();
advance();
ExpressionAST *rightExpr = 0;
if (!parseCastExpression(rightExpr))
return false;
BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(session->mempool);
ast->op = op;
ast->left_expression = node;
ast->right_expression = rightExpr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
}
bool Parser::parseMultiplicativeExpression(ExpressionAST *&node)
{
std::size_t start = session->token_stream->cursor();
if (!parsePmExpression(node))
return false;
while (session->token_stream->lookAhead() == '*'
|| session->token_stream->lookAhead() == '/'
|| session->token_stream->lookAhead() == '%')
{
std::size_t op = session->token_stream->cursor();
advance();
ExpressionAST *rightExpr = 0;
if (!parsePmExpression(rightExpr))
return false;
BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(session->mempool);
ast->op = op;
ast->left_expression = node;
ast->right_expression = rightExpr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
}
bool Parser::parseAdditiveExpression(ExpressionAST *&node)
{
std::size_t start = session->token_stream->cursor();
if (!parseMultiplicativeExpression(node))
return false;
while (session->token_stream->lookAhead() == '+' || session->token_stream->lookAhead() == '-')
{
std::size_t op = session->token_stream->cursor();
advance();
ExpressionAST *rightExpr = 0;
if (!parseMultiplicativeExpression(rightExpr))
return false;
BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(session->mempool);
ast->op = op;
ast->left_expression = node;
ast->right_expression = rightExpr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
}
bool Parser::parseShiftExpression(ExpressionAST *&node)
{
std::size_t start = session->token_stream->cursor();
if (!parseAdditiveExpression(node))
return false;
while (session->token_stream->lookAhead() == Token_shift)
{
std::size_t op = session->token_stream->cursor();
advance();
ExpressionAST *rightExpr = 0;
if (!parseAdditiveExpression(rightExpr))
return false;
BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(session->mempool);
ast->op = op;
ast->left_expression = node;
ast->right_expression = rightExpr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
}
bool Parser::parseRelationalExpression(ExpressionAST *&node, bool templArgs)
{
std::size_t start = session->token_stream->cursor();
if (!parseShiftExpression(node))
return false;
while (session->token_stream->lookAhead() == '<'
|| (session->token_stream->lookAhead() == '>' && !templArgs)
|| session->token_stream->lookAhead() == Token_leq
|| session->token_stream->lookAhead() == Token_geq)
{
std::size_t op = session->token_stream->cursor();
advance();
ExpressionAST *rightExpr = 0;
if (!parseShiftExpression(rightExpr))
return false;
BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(session->mempool);
ast->op = op;
ast->left_expression = node;
ast->right_expression = rightExpr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
}
bool Parser::parseEqualityExpression(ExpressionAST *&node, bool templArgs)
{
std::size_t start = session->token_stream->cursor();
if (!parseRelationalExpression(node, templArgs))
return false;
while (session->token_stream->lookAhead() == Token_eq
|| session->token_stream->lookAhead() == Token_not_eq)
{
std::size_t op = session->token_stream->cursor();
advance();
ExpressionAST *rightExpr = 0;
if (!parseRelationalExpression(rightExpr, templArgs))
return false;
BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(session->mempool);
ast->op = op;
ast->left_expression = node;
ast->right_expression = rightExpr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
}
bool Parser::parseAndExpression(ExpressionAST *&node, bool templArgs)
{
std::size_t start = session->token_stream->cursor();
if (!parseEqualityExpression(node, templArgs))
return false;
while (session->token_stream->lookAhead() == '&')
{
std::size_t op = session->token_stream->cursor();
advance();
ExpressionAST *rightExpr = 0;
if (!parseEqualityExpression(rightExpr, templArgs))
return false;
BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(session->mempool);
ast->op = op;
ast->left_expression = node;
ast->right_expression = rightExpr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
}
bool Parser::parseExclusiveOrExpression(ExpressionAST *&node, bool templArgs)
{
std::size_t start = session->token_stream->cursor();
if (!parseAndExpression(node, templArgs))
return false;
while (session->token_stream->lookAhead() == '^')
{
std::size_t op = session->token_stream->cursor();
advance();
ExpressionAST *rightExpr = 0;
if (!parseAndExpression(rightExpr, templArgs))
return false;
BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(session->mempool);
ast->op = op;
ast->left_expression = node;
ast->right_expression = rightExpr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
}
bool Parser::parseInclusiveOrExpression(ExpressionAST *&node, bool templArgs)
{
std::size_t start = session->token_stream->cursor();
if (!parseExclusiveOrExpression(node, templArgs))
return false;
while (session->token_stream->lookAhead() == '|')
{
std::size_t op = session->token_stream->cursor();
advance();
ExpressionAST *rightExpr = 0;
if (!parseExclusiveOrExpression(rightExpr, templArgs))
return false;
BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(session->mempool);
ast->op = op;
ast->left_expression = node;
ast->right_expression = rightExpr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
}
bool Parser::parseLogicalAndExpression(ExpressionAST *&node, bool templArgs)
{
std::size_t start = session->token_stream->cursor();
if (!parseInclusiveOrExpression(node, templArgs))
return false;
while (session->token_stream->lookAhead() == Token_and)
{
std::size_t op = session->token_stream->cursor();
advance();
ExpressionAST *rightExpr = 0;
if (!parseInclusiveOrExpression(rightExpr, templArgs))
return false;
BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(session->mempool);
ast->op = op;
ast->left_expression = node;
ast->right_expression = rightExpr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
}
bool Parser::parseLogicalOrExpression(ExpressionAST *&node, bool templArgs)
{
std::size_t start = session->token_stream->cursor();
if (!parseLogicalAndExpression(node, templArgs))
return false;
while (session->token_stream->lookAhead() == Token_or)
{
std::size_t op = session->token_stream->cursor();
advance();
ExpressionAST *rightExpr = 0;
if (!parseLogicalAndExpression(rightExpr, templArgs))
return false;
BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(session->mempool);
ast->op = op;
ast->left_expression = node;
ast->right_expression = rightExpr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
}
bool Parser::parseConditionalExpression(ExpressionAST *&node)
{
std::size_t start = session->token_stream->cursor();
if (!parseLogicalOrExpression(node))
return false;
if (session->token_stream->lookAhead() == '?')
{
advance();
ExpressionAST *leftExpr = 0;
if (!parseExpression(leftExpr))
return false;
CHECK(':');
ExpressionAST *rightExpr = 0;
if (!parseAssignmentExpression(rightExpr))
return false;
ConditionalExpressionAST *ast
= CreateNode<ConditionalExpressionAST>(session->mempool);
ast->condition = node;
ast->left_expression = leftExpr;
ast->right_expression = rightExpr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
}
bool Parser::parseAssignmentExpression(ExpressionAST *&node)
{
std::size_t start = session->token_stream->cursor();
if(parseSignalSlotExpression(node))
return true;
//Parsed a signal/slot expression, fine
if (session->token_stream->lookAhead() == Token_throw && !parseThrowExpression(node))
return false;
else if (!parseConditionalExpression(node))
return false;
while (session->token_stream->lookAhead() == Token_assign
|| session->token_stream->lookAhead() == '=')
{
std::size_t op = session->token_stream->cursor();
advance();
ExpressionAST *rightExpr = 0;
if (!parseConditionalExpression(rightExpr))
return false;
BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(session->mempool);
ast->op = op;
ast->left_expression = node;
ast->right_expression = rightExpr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
}
bool Parser::parseConstantExpression(ExpressionAST *&node)
{
return parseConditionalExpression(node);
}
bool Parser::parseExpression(ExpressionAST *&node)
{
return parseCommaExpression(node);
}
bool Parser::parseSignalSlotExpression(ExpressionAST *&node) {
if(session->token_stream->lookAhead() == Token___qt_sig_slot__) {
std::size_t start = session->token_stream->cursor();
CHECK(Token___qt_sig_slot__);
CHECK('(');
SignalSlotExpressionAST *ast = CreateNode<SignalSlotExpressionAST>(session->mempool);
parseUnqualifiedName(ast->name, false);
CHECK('(');
if(ast->name)
parseTemplateArgumentList(ast->name->template_arguments);
CHECK(')');
if(ast->name)
ast->name->end_token = _M_last_valid_token+1;
CHECK(')');
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}else{
return false;
}
}
bool Parser::parseCommaExpression(ExpressionAST *&node)
{
std::size_t start = session->token_stream->cursor();
if (!parseAssignmentExpression(node))
return false;
while (session->token_stream->lookAhead() == ',')
{
std::size_t op = session->token_stream->cursor();
advance();
ExpressionAST *rightExpr = 0;
if (!parseAssignmentExpression(rightExpr))
return false;
BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(session->mempool);
ast->op = op;
ast->left_expression = node;
ast->right_expression = rightExpr;
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
}
return true;
}
bool Parser::parseThrowExpression(ExpressionAST *&node)
{
std::size_t start = session->token_stream->cursor();
size_t pos = session->token_stream->cursor();
CHECK(Token_throw);
ThrowExpressionAST *ast = CreateNode<ThrowExpressionAST>(session->mempool);
ast->throw_token = pos;
parseAssignmentExpression(ast->expression);
UPDATE_POS(ast, start, _M_last_valid_token+1);
node = ast;
return true;
}
bool Parser::holdErrors(bool hold)
{
bool current = _M_hold_errors;
_M_hold_errors = hold;
return current;
}
( run in 0.378 second using v1.01-cache-2.11-cpan-524268b4103 )