Subversion Repositories psp

Rev

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