Subversion Repositories psp

Rev

Rev 1353 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1284 mrbrown 1
/* 中間記法電卓 -- calc */
2
 
3
%{
1353 mrbrown 4
typedef float NumType;
1284 mrbrown 5
 
1353 mrbrown 6
#define YYSTYPE float
1284 mrbrown 7
#define YYERROR_VERBOSE
8
 
9
#include <cmath>
10
#include <cctype>
2463 jim 11
#include <cstring>
1284 mrbrown 12
 
13
#include <vector>
14
#include <sstream>
15
 
16
#include "calc.h"
17
#include "formula.h"
18
#include "formula-variables.h"
19
 
20
int yyerror(char* s);
21
int yylex();
22
 
23
const char* yyinStr;
24
 
25
typedef Formula<NumType> CalcFormula;
26
typedef Number<NumType> CalcNumber;
27
typedef Random<NumType> CalcRandom;
28
typedef Rank<NumType> CalcRank;
29
typedef Param<NumType> CalcParam;
30
typedef Operator CalcOperator;
31
 
32
namespace {
33
	CalcFormula* formula;
34
	std::vector<CalcFormula*> formulas;
35
 
1353 mrbrown 36
	CalcFormula* f(float d) { return formulas[(int)d]; }
1284 mrbrown 37
 
38
	int paramId;
39
}
40
 
41
%}
42
 
43
/* BISON宣言 */
44
%token NUM RAND RANK PARAM
45
%left '-' '+'
46
%left '*' '/'
47
%left NEG     /* negation--単項マイナス */
48
%right '^'    /* べき乗関数        */
49
 
50
/* 文法規則が続く */
51
%%
52
input:    /* 空文字列 */
53
        | input line
54
;
55
 
56
line:     '\n'
57
| exp '\n'  { formula = f($1); return 0; }
58
;
59
 
60
exp:    NUM {
61
	        $$ = formulas.size();
62
	        formulas.push_back(new CalcFormula(new CalcNumber($1)));
63
        }
64
        | RAND {
65
	        $$ = formulas.size();
66
            formulas.push_back(new CalcFormula(new CalcRandom()));
67
        }
68
        | RANK {
69
			$$ = formulas.size();
70
			formulas.push_back(new CalcFormula(new CalcRank()));
71
		}
72
        | PARAM {
73
			$$ = formulas.size();
74
			formulas.push_back(new CalcFormula(new CalcParam(paramId)));
75
		}
76
        | exp '+' exp {
77
		    $$ = formulas.size();
78
			formulas.push_back(new CalcFormula(f($1), op_add, f($3)));
79
		}
80
        | exp '-' exp {
81
		    $$ = formulas.size();
82
			formulas.push_back(new CalcFormula(f($1), op_sub, f($3)));
83
		}
84
        | exp '*' exp {
85
		    $$ = formulas.size();
86
			formulas.push_back(new CalcFormula(f($1), op_mul, f($3)));
87
		}
88
        | exp '/' exp {
89
		    $$ = formulas.size();
90
			formulas.push_back(new CalcFormula(f($1), op_div, f($3)));
91
		}
92
        | '-' exp  %prec NEG {
93
		    $$ = $2;
94
			f($2)->setHeadSub();
95
		}
96
        | '(' exp ')' {
97
		    $$ = $2;
98
		}
99
;
100
%%
101
 
102
/**
103
 * 字句解析器は、数値を読めば、double型の値をスタックに積んで
104
 * トークン「NUM」を返し、数値以外を読めば、その文字のアスキー符号を返す。
105
 * 空白とタブは読み飛ばされる。ファイルが終わると0を返す。
106
 */
107
 
108
#include <ctype.h>
109
#include <stdio.h>
110
 
111
int yylex ()
112
{
113
	int c;
114
 
115
	/* 空白類を読み飛ばす  */
116
	while ((c = *(yyinStr++)) == ' ' || c == '\t')
117
		;
118
	/* 数値を処理する   */
119
	if (c == '.' || isdigit (c))
120
    {
121
		yyinStr--;
1353 mrbrown 122
		sscanf (yyinStr, "%f", &yylval);
1284 mrbrown 123
		while ((c = *(++yyinStr)) == '.' || isdigit(c)) {}
124
		return NUM;
125
    }
126
 
127
	// 変数を処理する */
128
	if (c == '$') {
129
		if (strncmp(yyinStr, "rand", 4) == 0) {
130
			yyinStr += 4;
131
			return RAND;
132
		}
133
		else if (strncmp(yyinStr, "rank", 4) == 0) {
134
		    yyinStr += 4;
135
			return RANK;
136
        }
137
		else {
138
			std::istringstream iss(std::string(yyinStr).substr(0, 1));
139
			iss >> paramId;
140
			yyinStr++;
141
			return PARAM;
142
		}
143
	}
144
 
145
	/* ファイルの終わりを処理する  */
146
	if (c == '\0')
147
		return 0;
148
	/* 1文字を返す */
149
	return c;
150
}
151
 
152
int yyerror(char* s) {
153
	printf("yyerror: %s\n", s);
154
	return 0;
155
}
156
 
157
std::auto_ptr<CalcFormula> calc(const std::string& str) {
158
	std::string fml = str + '\n';
159
	yyinStr = fml.c_str();
160
	yyparse();
161
	return std::auto_ptr<CalcFormula>(formula);
162
}
163