2012-11-30 21:26:26 +04:00
//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author: Vassil Vassilev <vvasilev@cern.ch>
//------------------------------------------------------------------------------
# include "MetaParser.h"
# include "MetaLexer.h"
# include "MetaSema.h"
# include "llvm/ADT/StringRef.h"
# include "llvm/Support/Path.h"
namespace cling {
MetaParser : : MetaParser ( MetaSema * Actions ) {
m_Lexer . reset ( 0 ) ;
m_Actions . reset ( Actions ) ;
}
void MetaParser : : enterNewInputLine ( llvm : : StringRef Line ) {
m_Lexer . reset ( new MetaLexer ( Line ) ) ;
m_TokenCache . clear ( ) ;
}
void MetaParser : : consumeToken ( ) {
if ( m_TokenCache . size ( ) )
m_TokenCache . erase ( m_TokenCache . begin ( ) ) ;
lookAhead ( 0 ) ;
}
void MetaParser : : consumeAnyStringToken ( tok : : TokenKind stopAt /*=tok::space*/ ) {
consumeToken ( ) ;
// we have to merge the tokens from the queue until we reach eof token or
// space token
SkipWhitespace ( ) ;
// Add the new token in which we will merge the others.
Token & MergedTok = m_TokenCache . front ( ) ;
if ( MergedTok . is ( stopAt ) | | MergedTok . is ( tok : : eof )
| | MergedTok . is ( tok : : comment ) )
return ;
Token Tok = lookAhead ( 1 ) ;
2012-12-01 04:54:25 +04:00
while ( Tok . isNot ( stopAt ) & & Tok . isNot ( tok : : eof ) ) {
2012-11-30 21:26:26 +04:00
//MergedTok.setLength(MergedTok.getLength() + Tok.getLength());
m_TokenCache . erase ( m_TokenCache . begin ( ) + 1 ) ;
Tok = lookAhead ( 1 ) ;
}
MergedTok . setKind ( tok : : raw_ident ) ;
MergedTok . setLength ( Tok . getBufStart ( ) - MergedTok . getBufStart ( ) ) ;
}
const Token & MetaParser : : lookAhead ( unsigned N ) {
if ( N < m_TokenCache . size ( ) )
return m_TokenCache [ N ] ;
for ( unsigned C = N + 1 - m_TokenCache . size ( ) ; C > 0 ; - - C ) {
m_TokenCache . push_back ( Token ( ) ) ;
m_Lexer - > Lex ( m_TokenCache . back ( ) ) ;
}
return m_TokenCache . back ( ) ;
}
void MetaParser : : SkipWhitespace ( ) {
while ( getCurTok ( ) . is ( tok : : space ) )
consumeToken ( ) ;
}
bool MetaParser : : isMetaCommand ( ) {
return isCommandSymbol ( ) & & isCommand ( ) ;
}
bool MetaParser : : isCommandSymbol ( ) {
consumeToken ( ) ;
if ( getCurTok ( ) . is ( tok : : dot ) /*TODO: || Tok.is(//.)*/ )
return true ;
return false ;
}
bool MetaParser : : isCommand ( ) {
consumeToken ( ) ;
2012-12-01 04:54:25 +04:00
return isLCommand ( ) | | isxCommand ( ) /*|| isXCommand() */ | | isqCommand ( )
2012-11-30 21:26:26 +04:00
| | isUCommand ( ) | | isICommand ( ) | | israwInputCommand ( )
| | isprintASTCommand ( ) | | isdynamicExtensionsCommand ( ) | | ishelpCommand ( )
2012-12-01 17:46:50 +04:00
| | isfileExCommand ( ) | | isfilesCommand ( ) | | isClassCommand ( ) ;
2012-11-30 21:26:26 +04:00
}
// L := 'L' FilePath
// FilePath := AnyString
// AnyString := .*^(' ' | '\t')
bool MetaParser : : isLCommand ( ) {
bool result = false ;
if ( getCurTok ( ) . is ( tok : : ident ) & & getCurTok ( ) . getIdent ( ) . equals ( " L " ) ) {
consumeAnyStringToken ( ) ;
if ( getCurTok ( ) . is ( tok : : raw_ident ) ) {
result = true ;
m_Actions - > ActOnLCommand ( llvm : : sys : : Path ( getCurTok ( ) . getIdent ( ) ) ) ;
consumeToken ( ) ;
if ( getCurTok ( ) . is ( tok : : comment ) ) {
consumeAnyStringToken ( ) ;
m_Actions - > ActOnComment ( getCurTok ( ) . getIdent ( ) ) ;
}
}
}
// TODO: Some fine grained diagnostics
return result ;
}
// xCommand := 'x' FilePath[ArgList]
// FilePath := AnyString
// ArgList := (ExtraArgList) ' ' [ArgList]
// ExtraArgList := AnyString [, ExtraArgList]
bool MetaParser : : isxCommand ( ) {
bool result = false ;
2012-12-01 04:54:25 +04:00
if ( getCurTok ( ) . is ( tok : : ident ) & & ( getCurTok ( ) . getIdent ( ) . equals ( " x " )
| | getCurTok ( ) . getIdent ( ) . equals ( " X " ) ) ) {
2012-11-30 21:26:26 +04:00
// There might be ArgList
consumeAnyStringToken ( tok : : l_paren ) ;
llvm : : sys : : Path file ( getCurTok ( ) . getIdent ( ) ) ;
llvm : : StringRef args ;
result = true ;
consumeToken ( ) ;
if ( getCurTok ( ) . is ( tok : : l_paren ) & & isExtraArgList ( ) ) {
args = getCurTok ( ) . getIdent ( ) ;
consumeToken ( ) ; // consume the closing paren
}
m_Actions - > ActOnxCommand ( file , args ) ;
if ( getCurTok ( ) . is ( tok : : comment ) ) {
consumeAnyStringToken ( ) ;
m_Actions - > ActOnComment ( getCurTok ( ) . getIdent ( ) ) ;
}
}
return result ;
}
// ExtraArgList := AnyString [, ExtraArgList]
bool MetaParser : : isExtraArgList ( ) {
// This might be expanded if we need better arg parsing.
consumeAnyStringToken ( tok : : r_paren ) ;
return getCurTok ( ) . is ( tok : : raw_ident ) ;
}
bool MetaParser : : isXCommand ( ) {
// TODO: For now we don't distinguish both cases. In future we will have to.
return isxCommand ( ) ;
}
bool MetaParser : : isqCommand ( ) {
bool result = false ;
if ( getCurTok ( ) . is ( tok : : ident ) & & getCurTok ( ) . getIdent ( ) . equals ( " q " ) ) {
result = true ;
m_Actions - > ActOnqCommand ( ) ;
}
return result ;
}
bool MetaParser : : isUCommand ( ) {
if ( getCurTok ( ) . is ( tok : : ident ) & & getCurTok ( ) . getIdent ( ) . equals ( " q " ) ) {
m_Actions - > ActOnUCommand ( ) ;
return true ;
}
return false ;
}
bool MetaParser : : isICommand ( ) {
if ( getCurTok ( ) . is ( tok : : ident ) & & getCurTok ( ) . getIdent ( ) . equals ( " I " ) ) {
consumeAnyStringToken ( ) ;
llvm : : sys : : Path path ;
if ( getCurTok ( ) . is ( tok : : raw_ident ) )
path = getCurTok ( ) . getIdent ( ) ;
m_Actions - > ActOnICommand ( path ) ;
return true ;
}
return false ;
}
bool MetaParser : : israwInputCommand ( ) {
if ( getCurTok ( ) . is ( tok : : ident ) & &
getCurTok ( ) . getIdent ( ) . equals ( " rawInput " ) ) {
MetaSema : : SwitchMode mode = MetaSema : : kToggle ;
consumeToken ( ) ;
SkipWhitespace ( ) ;
if ( getCurTok ( ) . is ( tok : : constant ) )
mode = ( MetaSema : : SwitchMode ) getCurTok ( ) . getConstant ( ) ;
m_Actions - > ActOnrawInputCommand ( mode ) ;
return true ;
}
return false ;
}
bool MetaParser : : isprintASTCommand ( ) {
if ( getCurTok ( ) . is ( tok : : ident ) & &
getCurTok ( ) . getIdent ( ) . equals ( " printAST " ) ) {
MetaSema : : SwitchMode mode = MetaSema : : kToggle ;
consumeToken ( ) ;
SkipWhitespace ( ) ;
if ( getCurTok ( ) . is ( tok : : constant ) )
mode = ( MetaSema : : SwitchMode ) getCurTok ( ) . getConstant ( ) ;
m_Actions - > ActOnprintASTCommand ( mode ) ;
return true ;
}
return false ;
}
bool MetaParser : : isdynamicExtensionsCommand ( ) {
if ( getCurTok ( ) . is ( tok : : ident ) & &
getCurTok ( ) . getIdent ( ) . equals ( " dynamicExtensions " ) ) {
MetaSema : : SwitchMode mode = MetaSema : : kToggle ;
consumeToken ( ) ;
SkipWhitespace ( ) ;
if ( getCurTok ( ) . is ( tok : : constant ) )
mode = ( MetaSema : : SwitchMode ) getCurTok ( ) . getConstant ( ) ;
m_Actions - > ActOndynamicExtensionsCommand ( mode ) ;
return true ;
}
return false ;
}
bool MetaParser : : ishelpCommand ( ) {
if ( getCurTok ( ) . is ( tok : : ident ) & & getCurTok ( ) . getIdent ( ) . equals ( " help " ) ) {
m_Actions - > ActOnhelpCommand ( ) ;
return true ;
}
return false ;
}
bool MetaParser : : isfileExCommand ( ) {
if ( getCurTok ( ) . is ( tok : : ident ) & & getCurTok ( ) . getIdent ( ) . equals ( " fileEx " ) ) {
m_Actions - > ActOnfileExCommand ( ) ;
return true ;
}
return false ;
}
bool MetaParser : : isfilesCommand ( ) {
if ( getCurTok ( ) . is ( tok : : ident ) & & getCurTok ( ) . getIdent ( ) . equals ( " files " ) ) {
m_Actions - > ActOnfilesCommand ( ) ;
return true ;
}
return false ;
}
2012-12-01 17:46:50 +04:00
bool MetaParser : : isClassCommand ( ) {
const Token & Tok = getCurTok ( ) ;
if ( Tok . is ( tok : : ident ) ) {
if ( Tok . getIdent ( ) . equals ( " class " ) ) {
consumeAnyStringToken ( ) ;
const Token & NextTok = getCurTok ( ) ;
llvm : : StringRef className ;
if ( NextTok . is ( tok : : raw_ident ) )
className = Tok . getIdent ( ) ;
m_Actions - > ActOnclassCommand ( className ) ;
return true ;
}
else if ( Tok . getIdent ( ) . equals ( " Class " ) ) {
m_Actions - > ActOnClassCommand ( ) ;
return true ;
}
}
return false ;
}
2012-11-30 21:26:26 +04:00
} // end namespace cling