0
|
1 #include <functional>
|
|
2 #include <iostream>
|
|
3 #include <iomanip>
|
|
4 #include "node.h"
|
|
5 #include "compiler.h"
|
|
6 #include "script-parser.hh"
|
|
7
|
|
8 // ノード生成
|
|
9 // ただし、定数同士の計算は、leftノードに結果を代入し、それを返す
|
|
10
|
|
11 CNode *CNode::MakeNode(compiler &c, const yy::location& l, int op, CNode *left, CNode *right)
|
|
12 {
|
|
13 if (right == 0) {
|
|
14 switch (op) {
|
|
15 case OP_NEG:
|
|
16 if (left->op_ == OP_CONST) { // 定数演算を計算する
|
|
17 left->value_ = -left->value_;
|
|
18 return left;
|
|
19 }
|
|
20 break;
|
|
21 }
|
|
22 return new CNode(l, op, left);
|
|
23 }
|
|
24
|
|
25 // 定数演算を計算する
|
|
26 if (left->op_ == OP_CONST && right->op_ == OP_CONST) {
|
|
27 switch (op) {
|
|
28 case OP_EQ:
|
|
29 left->value_ = (left->value_ == right->value_)? 1: 0;
|
|
30 break;
|
|
31
|
|
32 case OP_NE:
|
|
33 left->value_ = (left->value_ != right->value_)? 1: 0;
|
|
34 break;
|
|
35
|
|
36 case OP_GT:
|
|
37 left->value_ = (left->value_ > right->value_)? 1: 0;
|
|
38 break;
|
|
39
|
|
40 case OP_GE:
|
|
41 left->value_ = (left->value_ >= right->value_)? 1: 0;
|
|
42 break;
|
|
43
|
|
44 case OP_LT:
|
|
45 left->value_ = (left->value_ < right->value_)? 1: 0;
|
|
46 break;
|
|
47
|
|
48 case OP_LE:
|
|
49 left->value_ = (left->value_ <= right->value_)? 1: 0;
|
|
50 break;
|
|
51
|
|
52 case OP_MINUS:
|
|
53 left->value_ -= right->value_;
|
|
54 break;
|
|
55
|
|
56 case OP_PLUS:
|
|
57 left->value_ += right->value_;
|
|
58 break;
|
|
59
|
|
60 case OP_TIMES:
|
|
61 left->value_ *= right->value_;
|
|
62 break;
|
|
63
|
|
64 case OP_DIVIDE:
|
|
65 if (right->value_ == 0) {
|
|
66 c.error(l, "定数計算を0で除算しました。");
|
|
67 }
|
|
68 else {
|
|
69 left->value_ /= right->value_;
|
|
70 }
|
|
71 break;
|
|
72
|
|
73 case OP_MOD:
|
|
74 if (right->value_ == 0) {
|
|
75 c.error(l, "定数計算を0で除算しました。");
|
|
76 }
|
|
77 else {
|
|
78 left->value_ %= right->value_;
|
|
79 }
|
|
80 break;
|
|
81
|
|
82 default:
|
|
83 return new CNode(l, op, left, right);
|
|
84 }
|
|
85 delete right;
|
|
86 return left;
|
|
87 }
|
|
88 return new CNode(l, op, left, right);
|
|
89 }
|
|
90
|
|
91 void CNode::push(compiler *c) const
|
|
92 {
|
|
93 switch (op_) {
|
|
94 case OP_NEG:
|
|
95 left_->push(c);
|
|
96 c->OpNeg();
|
|
97 return;
|
|
98
|
|
99 case OP_RANDFUNC:
|
|
100 left_->push(c);
|
|
101 c->OpRand();
|
|
102 return;
|
|
103
|
|
104 case OP_CONST:
|
|
105 c->PushConst(value_);
|
|
106 return;
|
|
107 }
|
|
108
|
|
109 left_->push(c);
|
|
110 right_->push(c);
|
|
111
|
|
112 // 整数計算ノードの処理
|
|
113 switch (op_) {
|
|
114 case OP_EQ:
|
|
115 c->OpEq();
|
|
116 break;
|
|
117
|
|
118 case OP_NE:
|
|
119 c->OpNe();
|
|
120 break;
|
|
121
|
|
122 case OP_GT:
|
|
123 c->OpGt();
|
|
124 break;
|
|
125
|
|
126 case OP_GE:
|
|
127 c->OpGe();
|
|
128 break;
|
|
129
|
|
130 case OP_LT:
|
|
131 c->OpLt();
|
|
132 break;
|
|
133
|
|
134 case OP_LE:
|
|
135 c->OpLe();
|
|
136 break;
|
|
137
|
|
138 case OP_MINUS:
|
|
139 c->OpSub();
|
|
140 break;
|
|
141
|
|
142 case OP_PLUS:
|
|
143 c->OpAdd();
|
|
144 break;
|
|
145
|
|
146 case OP_TIMES:
|
|
147 c->OpMul();
|
|
148 break;
|
|
149
|
|
150 case OP_DIVIDE:
|
|
151 c->OpDiv();
|
|
152 break;
|
|
153
|
|
154 case OP_MOD:
|
|
155 c->OpMod();
|
|
156 break;
|
|
157
|
|
158 default:
|
|
159 c->error(l_, "内部エラー:処理できない計算ノードがありました。");
|
|
160 break;
|
|
161 }
|
|
162 }
|
|
163
|
|
164 void CNode::pop(compiler *c) const
|
|
165 {
|
|
166 c->error(l_, "内部エラー:計算ノードをpopしています。");
|
|
167 }
|
|
168
|
|
169 void CValueNode::push(compiler *c) const
|
|
170 {
|
|
171 if (op_ != OP_VALUE) {
|
|
172 c->error(l_, "内部エラー:変数ノードに変数以外が登録されています。");
|
|
173 }
|
|
174 else {
|
|
175 const CValueTag *tag = c->GetValueTag(*string_);
|
|
176 if (tag == 0) {
|
|
177 c->error(l_, "変数 " + *string_ + " は定義されていません。");
|
|
178 }
|
|
179 else {
|
|
180 c->PushValue(tag->addr_);
|
|
181 }
|
|
182 }
|
|
183 }
|
|
184
|
|
185 void CValueNode::pop(compiler *c) const
|
|
186 {
|
|
187 if (op_ != OP_VALUE) {
|
|
188 c->error(l_, "内部エラー:変数ノードに変数以外が登録されています。");
|
|
189 }
|
|
190 else {
|
|
191 const CValueTag *tag = c->GetValueTag(*string_);
|
|
192 if (tag == 0) {
|
|
193 tag = c->AddValue(*string_);
|
|
194 }
|
|
195 if (tag == 0) {
|
|
196 c->error(l_, "変数 " + *string_ + " が定義できません。");
|
|
197 }
|
|
198 else {
|
|
199 c->PopValue(tag->addr_);
|
|
200 }
|
|
201 }
|
|
202 }
|
|
203
|
|
204 // 代入命令を生成
|
|
205 //
|
|
206 // > push b
|
|
207 // > pop a
|
|
208 //
|
|
209 void CAssign::analyze(compiler *c)
|
|
210 {
|
|
211 expr_->push(c);
|
|
212 value_->pop(c);
|
|
213 }
|