⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parser.cpp

📁 C-编译器的设计文档与源代码下载,1. 具有比较友好的GUI界面(仿照了我自己正在用的emacs); 2. 语法支持比较全面(毕竟是C-
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		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 + -