C++プログラミング言語計算機ソースコード

7788 ワード

まず教科書が最初に出てきたソースコードで、実行できます.
#include "pch.h"
#include 
#include
#include
#include
#include

using namespace std;

enum Token_value{

	NAME,NUMBER,END,
	PLUS='+',MINUS='-',MUL='*',DIV='/',
	PRINT=';',ASSIGN='=',LP='(',RP=')'

};
Token_value curr_tok = PRINT;

int no_of_errors;
double term(bool get);
string string_value;
double number_value;

double error(const string&s)
{
	no_of_errors++;
	cout << "error" << s << '
'; return 1; } Token_value get_token() { char ch = 0; cin >> ch; switch (ch) { case 0: return curr_tok = END; case';': case'*': case'/': case'+': case'-': case'(': case')': case'=': return curr_tok = Token_value(ch); case'0':case'1':case'2':case'3':case'4':case'5': case'6':case'7':case'8':case'9':case'.': cin.putback(ch); cin >> number_value; default: if (isalpha(ch)) { string_value = ch; while (cin.get(ch) && isalnum(ch)); string_value.push_back(ch); return curr_tok = NAME; } error("bad token"); return curr_tok = PRINT; return curr_tok = NUMBER; } } double expr(bool get) { double left = term(get); for(;;) switch (curr_tok) { case PLUS: left += term(true); break; case MINUS: left -= term(true); break; default: return left; } } double prim(bool get) { if (get) get_token(); switch (curr_tok) { case NUMBER: { double v = number_value; get_token(); return v; } case NAME: { double&v = number_value; if (get_token() == ASSIGN) v = expr(true); return v; } case MINUS: return -prim(true); case LP: { double e = expr(true); if (curr_tok != RP) return error(")needed"); get_token(); return e; } default: return error(" "); } } double term(bool get) { double left = prim(get); for(;;) switch (curr_tok) { case MUL: left *= prim(true); break; case DIV: if (double d = prim(true)) { left /= d; break; } return error("divide by 0"); default: return left; } } istream* input; int main(int argc,char* argv[] ) { switch (argc) { case 1: { input = &cin; break; } case 2: { input = new istringstream(argv[1]); break; } default: error("too many!"); return 1; } while (*input) { get_token(); if (curr_tok == END)break; if (curr_tok == PRINT) continue; cout << expr(false) << '
'; } if (input != &cin) delete input; return no_of_errors; }

ネーミングスペースと例外処理コンテンツを追加した究極のバージョン
#include "pch.h"
#include 
#include
#include
#include
#include

using namespace std;

namespace Error {

	struct Zero_divide
	{

	};
	struct Syntax_error {
		const char*p;
		Syntax_error(const char*q) { p = q; }
	};
	struct Range_error {
		int i;
		Range_error(int ii) { i = ii; }
	};
}


namespace Parser {
	using namespace Error;
	double expr(bool get);
	double prim(bool get);
	double term(bool get);


}

namespace Lexer {
	enum Token_value {

		NAME, NUMBER, END,
		PLUS = '+', MINUS = '-', MUL = '*', DIV = '/',
		PRINT = ';', ASSIGN = '=', LP = '(', RP = ')'

	};
	Token_value curr_tok = PRINT;

	Token_value get_token();
	string string_value;
	double number_value;

};





double Parser::expr(bool get) {
	using Lexer::curr_tok;
	using Lexer::PLUS;
	using Lexer::MINUS;


	double left = term(get);
	for (;;)
		switch (curr_tok)
		{
		case PLUS:
			left += term(true);
			break;
		case MINUS:
			left -= term(true);
			break;
		default:
			return left;
		}
}






double Parser::prim(bool get) {
	if (get) Lexer::get_token();
	switch (Lexer::curr_tok)
	{
	case Lexer::NUMBER:
	{
		double v = Lexer::number_value;
		Lexer::get_token();
		return v;
	}
	case Lexer::NAME:
	{
		double&v = Lexer::number_value;
		if (Lexer::get_token() == Lexer::ASSIGN)
			v = expr(true);
		return v;
	}
	case Lexer::MINUS:
		return -prim(true);
	case Lexer::LP:
	{
		double e = expr(true);
		if (Lexer::curr_tok != Lexer::RP)
			throw Error::Syntax_error("    ");
		Lexer::get_token();
		return e;
	}
	default:
		throw Error::Syntax_error("    ");
	}
}

double Parser::term(bool get) {
	double left = prim(get);
	for (;;)
		switch (Lexer::curr_tok) {
		case Lexer::MUL:
			left *= prim(true);
			break;
		case Lexer::DIV:
			if (double d = prim(true)) {
				left /= d;
				break;
			}
			throw Error::Zero_divide();
		default:
			return left;
		}

}


Lexer::Token_value Lexer::get_token()
	{
		char ch = 0;
		cin >> ch;
		switch (ch) {
		case 0:
			return curr_tok = END;
		case';':
		case'*':
		case'/':
		case'+':
		case'-':
		case'(':
		case')':
		case'=':
			return curr_tok = Token_value(ch);
		case'0':case'1':case'2':case'3':case'4':case'5':
		case'6':case'7':case'8':case'9':case'.':
			cin.putback(ch);
			cin >> number_value;
			return curr_tok = NUMBER;
		default:
			if (isalpha(ch)) {
				string_value = ch;
				while (cin.get(ch) && isalnum(ch));
				string_value.push_back(ch);
				return curr_tok = NAME;
			}
			throw Error::Syntax_error("bad token");
			return curr_tok = PRINT;
			return curr_tok = NUMBER;
		}
	}


//    。
namespace Driver {
	int no_of_errors;
	istream* input;
	void skip();
}
void Driver::skip() {
	//skip                    ,  。
	no_of_errors++;

	while (*input) {
		char ch;
		input->get(ch);

		switch (ch) {
		case'
': case';': return; } } } int main(int argc, char* argv[]) { try { switch (argc) { case 1: { Driver::input = &cin; break; } case 2: { Driver::input = new istringstream(argv[1]); break; } default: throw Error::Range_error(1); } } catch (Error::Range_error) { cout << "too many"; Lexer::curr_tok = Lexer::PRINT; } /*using namespace Lexer; using namespace Parser; while (*Driver::input) try{ get_token(); if (curr_tok == END)break; if (curr_tok == PRINT) continue; cout << expr(false) << '
'; } catch(Error::Zero_divide){ cerr << " 。
"; if (Lexer::curr_tok != Lexer::PRINT)Driver::skip(); //skip() 。 } catch(Error::Syntax_error e){ cerr << " 。" << e.p << '
'; if (Lexer::curr_tok != Lexer::PRINT)Driver::skip(); } if (Driver::input != &cin) delete Driver::input; // 。 return Driver::no_of_errors;*/ bool in_error = false; // , , 。 while (*Driver::input) { try { Lexer::get_token(); if (Lexer::curr_tok == Lexer::END)break; if (Lexer::curr_tok == Lexer::PRINT) { in_error = false; continue; } if (in_error == false)cout << Parser::expr(false) << '
'; } catch (Error::Zero_divide) { cerr << "
"; in_error = true; } catch (Error::Syntax_error e) { cerr << " :" << e.p << '
'; in_error = true; cout << "error
"; } if (Driver::input != &cin) delete Driver::input; // 。 return Driver::no_of_errors; } }