Go で書き直した Ikemen
Revisión | c0faa54a05f9f979fa280b47d97419271909221c (tree) |
---|---|
Tiempo | 2016-12-15 00:57:39 |
Autor | SUEHIRO <supersuehiro@user...> |
Commiter | SUEHIRO |
バイトコード実行時と定数評価時の関数を共通化した方がいいと思った
@@ -153,6 +153,8 @@ func (_ *Compiler) tokenizer(in *string) string { | ||
153 | 153 | } |
154 | 154 | func (_ *Compiler) isOperator(token string) int { |
155 | 155 | switch token { |
156 | + case "", ",", ")", "]": | |
157 | + return -1 | |
156 | 158 | case "||": |
157 | 159 | return 1 |
158 | 160 | case "^^": |
@@ -181,9 +183,9 @@ func (_ *Compiler) isOperator(token string) int { | ||
181 | 183 | func (c *Compiler) operator(in *string) (string, error) { |
182 | 184 | if len(c.maeOp) > 0 { |
183 | 185 | if opp := c.isOperator(c.token); opp <= c.isOperator(c.maeOp) { |
184 | - if opp > 0 || len(c.token) == 0 || | |
185 | - (c.token[0] != '(' && (c.token[0] < 'A' || c.token[0] > 'Z') && | |
186 | - (c.token[0] < 'a' || c.token[0] > 'z')) { | |
186 | + if opp < 0 || ((!c.usiroOp || c.token[0] != '(') && | |
187 | + (c.token[0] < 'A' || c.token[0] > 'Z') && | |
188 | + (c.token[0] < 'a' || c.token[0] > 'z')) { | |
187 | 189 | return "", Error(c.maeOp + "が不正です") |
188 | 190 | } |
189 | 191 | *in = c.token + " " + *in |
@@ -224,11 +226,29 @@ func (c *Compiler) expValue(out *BytecodeExp, in *string) (BytecodeValue, | ||
224 | 226 | c.token = c.tokenizer(in) |
225 | 227 | return bv, nil |
226 | 228 | } |
229 | + if !sys.ignoreMostErrors { | |
230 | + defer func() { c.usiroOp = false }() | |
231 | + } | |
227 | 232 | unimplemented() |
228 | 233 | c.valCnt++ |
229 | 234 | c.token = c.tokenizer(in) |
230 | 235 | return bv, nil |
231 | 236 | } |
237 | +func (c *Compiler) renzikuEnzansihaError(in *string) error { | |
238 | + *in = strings.TrimSpace(*in) | |
239 | + if len(*in) > 0 { | |
240 | + switch (*in)[0] { | |
241 | + default: | |
242 | + if len(*in) < 2 || (*in)[:2] != "!=" { | |
243 | + break | |
244 | + } | |
245 | + fallthrough | |
246 | + case '=', '<', '>', '|', '&', '+', '*', '/', '%', '^': | |
247 | + return Error(c.tokenizer(in) + "が不正です") | |
248 | + } | |
249 | + } | |
250 | + return nil | |
251 | +} | |
232 | 252 | func (c *Compiler) expPostNot(out *BytecodeExp, in *string) (BytecodeValue, |
233 | 253 | error) { |
234 | 254 | bv, err := c.expValue(out, in) |
@@ -249,17 +269,31 @@ func (c *Compiler) expPostNot(out *BytecodeExp, in *string) (BytecodeValue, | ||
249 | 269 | } |
250 | 270 | c.token = c.tokenizer(in) |
251 | 271 | } |
252 | - if len(c.maeOp) == 0 && c.usiroOp && c.token == "(" { | |
253 | - oldin := *in | |
254 | - var dummyout BytecodeExp | |
255 | - if _, err := c.expValue(&dummyout, in); err != nil { | |
256 | - return BytecodeNaN(), err | |
257 | - } | |
258 | - if c.isOperator(c.token) <= 0 { | |
259 | - return BytecodeNaN(), Error("演算子がありません") | |
272 | + | |
273 | + if len(c.maeOp) == 0 { | |
274 | + opp := c.isOperator(c.token) | |
275 | + if opp == 0 { | |
276 | + if !c.usiroOp && c.token == "(" { | |
277 | + return BytecodeNaN(), Error("演算子がありません") | |
278 | + } | |
279 | + oldin := *in | |
280 | + var dummyout BytecodeExp | |
281 | + if _, err := c.expValue(&dummyout, in); err != nil { | |
282 | + return BytecodeNaN(), err | |
283 | + } | |
284 | + if c.isOperator(c.token) <= 0 { | |
285 | + return BytecodeNaN(), Error("演算子がありません") | |
286 | + } | |
287 | + if err := c.renzikuEnzansihaError(in); err != nil { | |
288 | + return BytecodeNaN(), err | |
289 | + } | |
290 | + oldin = oldin[:len(oldin)-len(*in)] | |
291 | + *in = "(" + oldin[:strings.LastIndex(oldin, c.token)] + *in | |
292 | + } else if opp > 0 { | |
293 | + if err := c.renzikuEnzansihaError(in); err != nil { | |
294 | + return BytecodeNaN(), err | |
295 | + } | |
260 | 296 | } |
261 | - oldin = oldin[:len(oldin)-len(*in)] | |
262 | - *in = "(" + oldin[:strings.LastIndex(oldin, c.token)] + *in | |
263 | 297 | } |
264 | 298 | return bv, nil |
265 | 299 | } |