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

📄 parser.cpp

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