📄 parser.cpp
字号:
case _WRITE:
temp = write_stmt(); break;
case _PRINTF:
temp = printf_stmt(); break;
case SEMI:// ';'
case _NUM:
case _CHARACTER:
case LOGICAL_NOT:
case LPARAN:
temp = expression_stmt(); break;
case _ID:
temp = subcompound_stmt(); break;
case _IF:
temp = if_stmt(); break;
case _WHILE:
temp = while_stmt(); break;
case _FOR:
temp = for_stmt(); break;
case _GOTO:
temp = goto_stmt(); break;
case _BREAK:
temp = break_stmt(); break;
case _CONTINUE:
temp = continue_stmt(); break;
case _RETURN:
temp = return_stmt(); break;
case _ELSE:
OutputErrMsg( "error in line %d: unpaired 'else' statement", m_pScaner->LineNo() );
ConsumeUntil( SEMI, RBRACE );
break;
default:
OutputErrMsg( "error in line %d: undefined symbol \"%s\"",
m_pScaner->LineNo(), (LPCTSTR)m_token.str );
ConsumeUntil( SEMI, RBRACE );
}
if( bHasNoBraces ) return temp;// has no braces, return when reach the first ';'
if( temp )
// link all statements together
if( !first ) { first = temp; last = temp->LastSibling(); }
else { last->sibling = temp; last = temp->LastSibling(); }
m_token = m_pScaner->NextToken();
}
return first;
}
// Grammar:
// 11. local_declarations->local_declarations var_declaration | var_declaration
// m_token is a supported type-specifier token
CTreeNode* CParser::local_declarations()
{
CTreeNode* temp = NULL;
IDToken = m_token = m_pScaner->NextToken();// ID or error
if( IDToken.type != _ID ) {
OutputErrMsg( "error in line %d: \"%s\" is a reserved token",
m_pScaner->LineNo(), (LPCTSTR)IDToken.str );
ConsumeUntil( SEMI );// error recovery
return NULL;
}
m_token = m_pScaner->NextToken();// ';', '[', ',' or error
if( m_token.type == SEMI || m_token.type == LSQUARE || m_token.type == COMMA )
temp = var_declaration();
else {
OutputErrMsg( "error in line %d: missing ';' after identifier \"%s\"",
m_pScaner->LineNo(), (LPCTSTR)IDToken.str );
m_pScaner->PushBack();// error recovery
}
return temp;
}
// Grammar:
// 12. `read` `(` var `)` `;`
// m_token.str == "read"
CTreeNode* CParser::read_stmt()
{
CTreeNode* temp = NULL;
if( !match(LPARAN) ) {// '('
OutputErrMsg( "error in line %d: syntax error, missing '('", m_pScaner->LineNo() );
ConsumeUntil( SEMI, RBRACE );// error recovery
return NULL;
}
IDToken = m_token = m_pScaner->NextToken();
if( m_token.type != _ID ) {
OutputErrMsg( "error in line %d: \"%s\" bad arguments", m_pScaner->LineNo(), (LPCTSTR)m_token.str );
ConsumeUntil( SEMI, RBRACE );// error recovery
return NULL;
}
temp = newStmtNode( kRead, CString("read") );
if( (temp->child[0] = var()) != NULL ) temp->child[0]->father = temp;
if( !match(RPARAN) ) {// ')'
OutputErrMsg( "error in line %d: syntax error, missing ')'", m_pScaner->LineNo() );
ConsumeUntil( SEMI, RBRACE );// error recovery
return temp;
}
if( !match(SEMI) ) {// ';'
OutputErrMsg( "error in line %d: syntax error, missing ';'", m_pScaner->LineNo() );
m_pScaner->PushBack();// error recovery
}
return temp;
}
// Grammar:
// 13. `write` `(` expression `)` `;`
// m_token.str == "write"
CTreeNode* CParser::write_stmt()
{
CTreeNode* temp = NULL;
if( !match(LPARAN) ) {// '('
OutputErrMsg( "error in line %d: syntax error, missing '('", m_pScaner->LineNo() );
ConsumeUntil( SEMI, RBRACE );// error recovery
return NULL;
}
temp = newStmtNode( kWrite, CString("write") );
m_token = m_pScaner->NextToken();
// m_token contains the first token of expression
if( (temp->child[0] = expression()) != NULL ) temp->child[0]->father = temp;
if( !match(RPARAN) ) {// ')'
OutputErrMsg( "error in line %d: syntax error, missing ')'", m_pScaner->LineNo() );
ConsumeUntil( SEMI, RBRACE );// error recovery
return temp;
}
if( !match(SEMI) ) {// ';'
OutputErrMsg( "error in line %d: syntax error, missing ';'", m_pScaner->LineNo() );
m_pScaner->PushBack();// error recovery
}
return temp;
}
// Grammar:
// 14. `printf` `(` `"` STRING `"` `)` `;`
// m_token.str == "printf"
CTreeNode* CParser::printf_stmt()
{
CTreeNode* temp = NULL;
if( !match(LPARAN) ) {// '('
OutputErrMsg( "error in line %d: syntax error, missing '('", m_pScaner->LineNo() );
ConsumeUntil( SEMI, RBRACE );// error recovery
return NULL;
}
m_token = m_pScaner->NextToken();
if( m_token.type != _STRING ) {
OutputErrMsg( "error in line %d: arguments should be strings", m_pScaner->LineNo() );
ConsumeUntil( SEMI, RBRACE );// error recovery
return NULL;
}
temp = newStmtNode( kPrintf, m_token.str );
if( !match(RPARAN) ) {// ')'
OutputErrMsg( "error in line %d: syntax error, missing ')'", m_pScaner->LineNo() );
ConsumeUntil( SEMI, RBRACE );// error recovery
return temp;
}
if( !match(SEMI) ) {// ';'
OutputErrMsg( "error in line %d: syntax error, missing ';'", m_pScaner->LineNo() );
m_pScaner->PushBack();// error recovery
}
return temp;
}
// Grammar:
// 15. expression_stmt->expression `;` | `;`
// m_token is '!', '(', ID, NUM, CHARACTER or ';'
CTreeNode* CParser::expression_stmt()
{
if( m_token.type == SEMI ) return NULL;
CTreeNode* temp = expression();
if( !match(SEMI) ) {
OutputErrMsg( "error in line %d: missing ';'", m_pScaner->LineNo() );
m_pScaner->PushBack();// error recovery
}
return temp;
}
// Grammar:
// 16. expression->var `=` expression | logic1_expression
// FIRST( expression ) = { `!`, `(`, ID, NUM, CHARACTER }
// m_token contains the first token of expression
CTreeNode* CParser::expression()
{
CTreeNode *temp = logic1_expression(), *p = temp;
m_token = m_pScaner->NextToken();
if( m_token.type == ASSIGN ) {
if( temp->type != _ID && temp->type != ASSIGN ) {// left of '=' should be a ID
OutputErrMsg( "error in line %d: left of '=' syntax error", m_pScaner->LineNo() );
ConsumeUntil( SEMI, RPARAN );
delete temp;
return NULL;
}
p = newExpNode( kOp, m_token.type, m_token.str );
p->child[0] = temp;
if( p->child[0] ) p->child[0]->father = p;
m_token = m_pScaner->NextToken();
p->child[1] = expression();
if( p->child[1] ) p->child[1]->father = p;
} else
m_pScaner->PushBack();
return p;
}
// Grammar:
// 17. logic1_expression->logic1_expression `||` logic2_expression | logic2_expression
// m_token contains the first token of logic1_expression
CTreeNode* CParser::logic1_expression()
{
CTreeNode *p = logic2_expression();
m_token = m_pScaner->NextToken();
while( m_token.type == LOGICAL_OR ) {
CTreeNode* temp = newExpNode( kOp, m_token.type, m_token.str );
temp->child[0] = p;
p = temp;
if( p->child[0] ) p->child[0]->father = p;
m_token = m_pScaner->NextToken();
if( (p->child[1] = logic2_expression()) ) p->child[1]->father = p;
m_token = m_pScaner->NextToken();
}
m_pScaner->PushBack();// put the next token back
return p;
}
// Grammar:
// 18. logic2_expression-> logic2_expression `&&` simple_expression | simple_expression
// m_token contains the first token of logic2_expression
CTreeNode* CParser::logic2_expression()
{
CTreeNode *p = simple_expression();
m_token = m_pScaner->NextToken();
while( m_token.type == LOGICAL_AND ) {
CTreeNode* temp = newExpNode( kOp, m_token.type, m_token.str );
temp->child[0] = p;
p = temp;
if( p->child[0] ) p->child[0]->father = p;
m_token = m_pScaner->NextToken();
if( (p->child[1] = simple_expression()) ) p->child[1]->father = p;
m_token = m_pScaner->NextToken();
}
m_pScaner->PushBack();// put the next token back
return p;
}
// Grammar:
// 19. simple_expression->additive_expression relop additive_expression | additive_expression
// 20. relop-> `<=` | `<` | `>` | `>=` | `==` | `!=`
// m_token contains the first token of simple_expression
CTreeNode* CParser::simple_expression()
{
CTreeNode* p = additive_expression();
m_token = m_pScaner->NextToken();
if( m_token.type == NGT || m_token.type == LT || m_token.type == GT ||
m_token.type == NLT || m_token.type == EQ || m_token.type == NEQ ) {
CTreeNode* temp = newExpNode( kOp, m_token.type, m_token.str );
temp->child[0] = p;
p = temp;
if( p->child[0] ) p->child[0]->father = p;
m_token = m_pScaner->NextToken();
if( (p->child[1] = additive_expression()) ) p->child[1]->father = p;
} else
m_pScaner->PushBack();
return p;
}
// Grammar:
// 21. additive_expression -> additive_expression addop term | term
// 22. addop-> `+` | `-`
// m_token contains the first token of add_expression
CTreeNode* CParser::additive_expression()
{
CTreeNode* p = term();
m_token = m_pScaner->NextToken();
while( m_token.type == PLUS || m_token.type == MINUS ) {
CTreeNode* temp = newExpNode( kOp, m_token.type, m_token.str );
temp->child[0] = p;
p = temp;
if( p->child[0] ) p->child[0]->father = p;
m_token = m_pScaner->NextToken();
if( (p->child[1] = term()) ) p->child[1]->father = p;
m_token = m_pScaner->NextToken();
}
m_pScaner->PushBack();// put the next token back
return p;
}
// Grammar:
// 23. term->term mulop logic3_expression | logic3_expression
// 24. mulop-> `*` | `/` | `%`
// m_token contains the first token of term
CTreeNode* CParser::term()
{
CTreeNode* p = logic3_expression();
m_token = m_pScaner->NextToken();
while( m_token.type == TIMES || m_token.type == DIV || m_token.type == MOD ) {
CTreeNode* temp = newExpNode( kOp, m_token.type, m_token.str );
temp->child[0] = p;
p = temp;
if( p->child[0] ) p->child[0]->father = p;
m_token = m_pScaner->NextToken();
if( (p->child[1] = logic3_expression()) ) p->child[1]->father = p;
m_token = m_pScaner->NextToken();
}
m_pScaner->PushBack();// put the next token back
return p;
}
// Grammar:
// 25. logic3_expression-> `!` logic3_expression | factor
// m_token contains the first token of logic3_expression
CTreeNode* CParser::logic3_expression()
{
CTreeNode *p = NULL, *temp = NULL;
if( m_token.type == LOGICAL_NOT ) {
p = newExpNode( kOp, m_token.type, m_token.str );
m_token = m_pScaner->NextToken();
if( (temp = factor()) ) {
p->child[0] = temp;
p->child[0]->father = p;
}
} else
p = factor();
return p;
}
// Grammar:
// 26. factor->`(` expression `)` | var | call | NUM
// m_token contains the first token of factor
CTreeNode* CParser::factor()
{
CTreeNode* temp = NULL;
switch( m_token.type ) {
case _NUM:
case _CHARACTER:
temp = newExpNode( kConst, m_token.type, m_token.str );
break;
case _ID:
IDToken = m_token;
m_token = m_pScaner->NextToken();
if( m_token.type == LPARAN ) temp = call();
else {
m_pScaner->PushBack();// push the next token back
temp = var();
}
break;
case LPARAN:
m_token = m_pScaner->NextToken();// m_token contain the first token of expression
temp = expression();
if( !match(RPARAN) ) {// match ')'
OutputErrMsg( "error in line %d: missing ')'", m_pScaner->LineNo() );
m_pScaner->PushBack();// error recovery
}
break;
default:
OutputErrMsg( "error in line %d: '%s' expression syntax error",
m_pScaner->LineNo(), (LPCTSTR)m_token.str );
ConsumeUntil( SEMI, RBRACE );// error recovery
}
return temp;
}
// Grammar:
// 27. var->ID | ID `[` expression `]`
// IDToken contains ID
CTreeNode* CParser::var()
{
CTreeNode* temp = newExpNode( kID, IDToken.type, IDToken.str );
m_token = m_pScaner->NextToken();// should be `[` or just push back
if( m_token.type == LSQUARE ) {
temp->bArray = TRUE;
m_token = m_pScaner->NextToken();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -