📄 parser.cpp
字号:
temp->child[0] = expression();
if( !match(RSQUARE) ) {
OutputErrMsg( "error in line %d: missing ']'", m_pScaner->LineNo() );
m_pScaner->PushBack();// error recovery
}
} else
m_pScaner->PushBack();
return temp;
}
// Grammar:
// 28. call->ID `(` args `)`
// m_token.str == "(", IDToken contains ID
CTreeNode* CParser::call()
{
CTreeNode *p = newStmtNode( kCall, IDToken.str ), *temp = NULL;
p->szScope = _T("global");
// CTreeNode* temp = newExpNode( kID, IDToken.type, IDToken.str );
// p->child[0] = temp;
// p->child[0]->father = p;
if( (p->child[0] = args()) ) p->child[0]->father = p;
temp = p->child[0];
while( temp && temp->sibling ) {
temp = temp->sibling;
temp->father = p;
}
if( !match(RPARAN) ) {// match ')'
OutputErrMsg( "error in line %d: missing ')'", m_pScaner->LineNo() );
m_pScaner->PushBack();// error recovery
}
return p;
}
// Grammar:
// 29. args->args_list | empty
// 30. args_list->args_list `,` expression | expression
// m_token.str == "("
CTreeNode* CParser::args()
{
CTreeNode *first = NULL, *temp = NULL;
m_token = m_pScaner->NextToken();
if( m_token.type == RPARAN ) {
m_pScaner->PushBack();// push the next token back
return NULL;
}
while( 1 ) {
if( (temp = expression()) != NULL )
// link all args together, the LAST argument is the FIRST in the list
if( !first ) first = temp;
else { temp->sibling = first; first = temp; }
m_token = m_pScaner->NextToken();
if( m_token.type == COMMA ) m_token = m_pScaner->NextToken();
else break;
}
m_pScaner->PushBack();
return first;
}
// Grammar:
// 31: sub_compoundstmt->ID `:` | call `;` | expression_stmt
// m_token contains the first token of sub_compoundstmt
CTreeNode* CParser::subcompound_stmt()
{
CTreeNode* temp = NULL;
IDToken = m_token;
m_token = m_pScaner->NextToken();
if( m_token.type == COLON ) {// label
temp = newStmtNode( kLabel, IDToken.str );
} else if( m_token.type == LPARAN ) {// call statement
temp = call();
if( !match(SEMI) ) {
OutputErrMsg( "error in line %d: missing ';'", m_pScaner->LineNo() );
m_pScaner->PushBack();// error recovery
}
} else {
m_pScaner->PushBack();
m_token = IDToken;
temp = expression_stmt();
}
return temp;
}
// Grammar:
// 32: if_stmt->`if` `(` expression `)` compound_stmt
// | `if` `(` expression `)` compound_stmt `else` compound_stmt
// m_token.str == "if"
CTreeNode* CParser::if_stmt()
{
CTreeNode *temp = newStmtNode( kIf, m_token.str ), *p = NULL;
if( !match(LPARAN) )// match '('
OutputErrMsg( "error in line %d: missing '(' in 'if' statement", m_pScaner->LineNo() );
else m_token = m_pScaner->NextToken();
// m_token should be the first token of expression
temp->child[0] = expression();
if( temp->child[0] ) temp->child[0]->father = temp;
if( !match(RPARAN) ) {// match ')'
OutputErrMsg( "error in line %d: missing ')' in 'if' statement", m_pScaner->LineNo() );
m_pScaner->PushBack();
}
p = temp->child[1] = compound_stmt();
if( p ) p->father = temp;
while( p && p->sibling ) { p = p->sibling; p->father = temp; }
m_token = m_pScaner->NextToken();
if( m_token.type == _ELSE ) {
p = temp->child[2] = compound_stmt();
if( p ) p->father = temp;
while( p && p->sibling ) { p = p->sibling; p->father = temp; }
} else
m_pScaner->PushBack();// push the next token back
return temp;
}
// Grammar:
// 33. while_stmt->`while` `(` expression `)` compound_stmt
// m_token.str == "while"
CTreeNode* CParser::while_stmt()
{
CTreeNode *temp = newStmtNode( kWhile, m_token.str ), *p = NULL;
if( !match(LPARAN) )// match '('
OutputErrMsg( "error in line %d: missing '(' in 'while' statement", m_pScaner->LineNo() );
else m_token = m_pScaner->NextToken();
// m_token should be the first token of expression
temp->child[0] = expression();
if( temp->child[0] ) temp->child[0]->father = temp;
if( !match(RPARAN) ) {// match ')'
OutputErrMsg( "error in line %d: missing ')' in 'while' statement", m_pScaner->LineNo() );
m_pScaner->PushBack();
}
// the next token should be '{'
p = temp->child[1] = compound_stmt();
if( p ) p->father = temp;
while( p && p->sibling ) { p = p->sibling; p->father = temp; }
return temp;
}
// Grammar:
// 34. for_stmt->`for` `(` var `=` expression `;` expression `;` var `=` expression `)` compound_stmt
// m_token.str == "for"
CTreeNode* CParser::for_stmt()
{
CTreeNode *temp = NULL, *p1 = NULL, *p2 = NULL, *p3 = NULL;
if( !match(LPARAN) ) // match '('
OutputErrMsg( "error in line %d: missing '(' in 'for' statement", m_pScaner->LineNo() );
else m_token = m_pScaner->NextToken();
// m_token should be var or ';'
if( m_token.type == SEMI ) {
p1 = temp = newStmtNode( kWhile, CString("while") );
m_token = m_pScaner->NextToken();
} else {
if( (temp = expression()) == NULL ) {
OutputErrMsg( "error in line %d: syntax error in the first expression, ignore the whole", m_pScaner->LineNo() );
ConsumeUntil( RBRACE );
return NULL;
} else
p1 = temp->sibling = newStmtNode( kWhile, CString("while") );
if( !match(SEMI) ) // match ';'
OutputErrMsg( "error in line %d: missing the first ';' in 'for' statement", m_pScaner->LineNo() );
else m_token = m_pScaner->NextToken();
}
// m_token should be the first token of expression
p1->child[0] = expression();
if( !p1->child[0] ) {
OutputErrMsg( "error in line %d: missing the second parameter in 'for' statement, ignore the whole", m_pScaner->LineNo() );
ConsumeUntil( RBRACE );
if( temp ) delete temp;
return NULL;
}
p1->child[0]->father = p1;
if( !match(SEMI) ) // match ';'
OutputErrMsg( "error in line %d: missing the second ';' in 'for' statement", m_pScaner->LineNo() );
else m_token = m_pScaner->NextToken();
// m_token should be var
p2 = expression();
if( p2 ) p2->father = p1;
if( !match(RPARAN) ) {// match ')'
OutputErrMsg( "error in line %d: missing ')' in 'for' statement", m_pScaner->LineNo() );
m_pScaner->PushBack();
}
// the next token should be '{'
p3 = p1->child[1] = compound_stmt();
if( p3 ) p3->father = p1;
if( p3 && p3->sibling ) {
p3 = p3->sibling; p3->father = p1;
}
if( p3 ) p3->sibling = p2;
else p1->child[1] = p2;
return temp;
}
// Grammar:
// 35. goto_stmt->`goto` ID `;`
// m_token.str == "goto"
CTreeNode* CParser::goto_stmt()
{
if( !match(_ID) ) {
OutputErrMsg( "error in line %d: a label should follow 'goto'", m_pScaner->LineNo() );
ConsumeUntil( SEMI, RBRACE );// error recovery
return NULL;
}
CTreeNode* temp = newStmtNode( kGoto, m_token.str );
if( !match(SEMI) ) {
OutputErrMsg( "error in line %d: missing ';' in 'goto' statement", m_pScaner->LineNo() );
m_pScaner->PushBack();
}
return temp;
}
// Grammar:
// 36. break_stmt->`break` `;`
// m_token.str == "break"
CTreeNode* CParser::break_stmt()
{
CTreeNode* temp = newStmtNode( kBreak, m_token.str );
if( !match(SEMI) ) {// match ';'
OutputErrMsg( "error in line %d: missing ';' in 'break' statement", m_pScaner->LineNo() );
m_pScaner->PushBack();
}
return temp;
}
// Grammar:
// 37. continue_stmt->`continue` `;`
// m_token.str = "continue"
CTreeNode* CParser::continue_stmt()
{
CTreeNode* temp = newStmtNode( kContinue, m_token.str );
if( !match(SEMI) ) {
OutputErrMsg( "error in line %d: missing ';' in 'continue' statement", m_pScaner->LineNo() );
m_pScaner->PushBack();
}
return temp;
}
// Grammar:
// 38. return_stmt->`return` `;` | `return` expression `;`
// m_token.str = "return"
CTreeNode* CParser::return_stmt()
{
CTreeNode* temp = newStmtNode( kReturn, m_token.str );
m_token = m_pScaner->NextToken();
if( m_token.type != SEMI ) {
temp->child[0] = expression();
if( !match(SEMI) ) {
OutputErrMsg( "error in line %d: missing ';' in 'return' statement", m_pScaner->LineNo() );
m_pScaner->PushBack();
}
}
return temp;
}
/* * CParser
* print the tree from the specified node to the trace file, the file must be existed
* * *
*** Programer: 陆晓春
* Date: 2004.05.19 */
void CParser::PrintTree( CTreeNode* pNode )
{
int i;
indent++;
while( pNode != NULL ) {
for( i = 0; i < indent; i++ ) write( "\t" );
switch( pNode->nodekind ) {
case kFunDec:
write( "Function declaration: " );
write( ReservedKeywordList[(int)pNode->type] );
write( " " );
write( pNode->szName );
write( "\r\n" );
break;
case kVarDec:
write( "Variable declaration: " );
write( ReservedKeywordList[(int)pNode->type] );
write( " " );
write( pNode->szName );
if( pNode->bArray ) write( "[%d]", pNode->iArraySize );
write( "\r\n" );
break;
case kParam:
write( "parameter: " );
write( ReservedKeywordList[(int)pNode->type] );
write( " " );
write( pNode->szName );
if( pNode->bArray ) write( "[]" );
write( "\r\n" );
break;
case kStmt:
switch( pNode->kind.stmt ) {
case kRead:
write( "call write(), args:\r\n" );
break;
case kWrite:
write( "call read(), args:\r\n" );
break;
case kPrintf:
write( "printf( \"%s\" )\r\n", (LPCTSTR)pNode->szName );
break;
case kLabel:
write( "label: \"%s\"\r\n", (LPCTSTR)pNode->szName );
break;
case kGoto:
write( "goto\r\n" );
for( i = 0; i <= indent; i++ ) write( "\t" );
write( "label: \"%s\"\r\n", (LPCTSTR)pNode->szName );
break;
case kCall:
write( "call %s(), args:\r\n", (LPCTSTR)pNode->szName );
break;
case kIf: write( "if\r\n" ); break;
case kWhile: write( "while\r\n" ); break;
case kBreak: write( "break\r\n" ); break;
case kContinue: write( "continue\r\n" ); break;
case kReturn: write( "return\r\n" ); break;
default: write( "Unknown node kind\r\n" );
}
break;
case kExp:
switch( pNode->kind.exp ) {
case kOp:
write( "Op: %s\r\n", (LPCTSTR)pNode->szName );
break;
case kConst:
write( "const: %s\r\n", (LPCTSTR)pNode->szName );
break;
case kID:
write( "ID: %s", (LPCTSTR)pNode->szName );
if( pNode->bArray ) {
pNode = pNode->child[0];
write( "[%s]", pNode->szName );
}
write( "\r\n" );
break;
default:
write( "Unkown node kind\r\n" );
}
break;
default:
write( "Unkown node kind\r\n" );
}
for( i = 0; i < MAX_CHILDREN; i++ ) PrintTree( pNode->child[i] );
pNode = pNode->sibling;
}
indent--;
}
// write the string into the trace file, which must be existed
void CParser::write( char* format, ... )
{
va_list params;
static char buf[ 1024 ];
va_start( params, format );
_vsnprintf( buf, 1020, format, params );
va_end( params );
try {
m_fTraceFile.Write( buf, strlen(buf) );
} catch( CFileException* ) {
OutputErrMsg( "failed to write to file: %s", (LPCTSTR)m_fTraceFile.GetFilePath() );
}
}
void CParser::write( CString& str )
{
try {
m_fTraceFile.Write( (LPCTSTR)str, str.GetLength() );
} catch( CFileException* ) {
OutputErrMsg( "failed to write to file: %s", (LPCTSTR)m_fTraceFile.GetFilePath() );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -