SCPP
A simple scripting language in C++
scpp_evaluater.hpp
Go to the documentation of this file.
1 
6 #pragma once
7 #include "scpp_ast.hpp"
8 #include <iostream>
9 #include <string>
10 #include <map>
11 
12 namespace SCPP
13 {
14  using std::map;
15  using std::string;
16  map<string, int> globalVars = {};
17  map<string, struct SFunction> globalFuncs = {};
18 
27  int evaluate(struct Expr &expr, map<string, int> &env = globalVars, map<string, struct SFunction> &functions = globalFuncs)
28  {
29  switch (expr.type)
30  {
31  case ExprType::Int:
32  return expr.u.i->value;
33  case ExprType::Not:
34  return !evaluate(expr.u.n->expr, env, functions);
35  case ExprType::Bin:
36  switch (expr.u.b->op)
37  {
38  case Op::Add:
39  return evaluate(expr.u.b->left, env, functions) + evaluate(expr.u.b->right, env, functions);
40  case Op::Sub:
41  return evaluate(expr.u.b->left, env, functions) - evaluate(expr.u.b->right, env, functions);
42  case Op::Mul:
43  return evaluate(expr.u.b->left, env, functions) * evaluate(expr.u.b->right, env, functions);
44  case Op::Div:
45  return evaluate(expr.u.b->left, env, functions) / evaluate(expr.u.b->right, env, functions);
46  case Op::Mod:
47  return evaluate(expr.u.b->left, env, functions) % evaluate(expr.u.b->right, env, functions);
48  case Op::And:
49  return evaluate(expr.u.b->left, env, functions) && evaluate(expr.u.b->right, env, functions);
50  case Op::Or:
51  return evaluate(expr.u.b->left, env, functions) || evaluate(expr.u.b->right, env, functions);
52  case Op::Nor:
53  return !(evaluate(expr.u.b->left, env, functions) || evaluate(expr.u.b->right, env, functions));
54  case Op::Nand:
55  return !(evaluate(expr.u.b->left, env, functions) && evaluate(expr.u.b->right, env, functions));
56  case Op::Xor:
57  return (evaluate(expr.u.b->left, env, functions) || evaluate(expr.u.b->right, env, functions)) && !(evaluate(expr.u.b->left, env, functions) && evaluate(expr.u.b->right, env, functions));
58  case Op::Lt:
59  return evaluate(expr.u.b->left, env, functions) < evaluate(expr.u.b->right, env, functions);
60  case Op::Leq:
61  return evaluate(expr.u.b->left, env, functions) <= evaluate(expr.u.b->right, env, functions);
62  case Op::Gt:
63  return evaluate(expr.u.b->left, env, functions) > evaluate(expr.u.b->right, env, functions);
64  case Op::Geq:
65  return evaluate(expr.u.b->left, env, functions) >= evaluate(expr.u.b->right, env, functions);
66  case Op::Eq:
67  return evaluate(expr.u.b->left, env, functions) == evaluate(expr.u.b->right, env, functions);
68  case Op::Neq:
69  return evaluate(expr.u.b->left, env, functions) != evaluate(expr.u.b->right, env, functions);
70  default:
71  break;
72  }
73  case ExprType::Seq:
74  {
75  int result = 0;
76  for (auto &&i : expr.u.s->exprs)
77  {
78  result = evaluate(i, env, functions);
79  }
80  return result;
81  }
82  case ExprType::Assign:
83  env.insert_or_assign(expr.u.a->name, evaluate(expr.u.a->value, env, functions));
84  return env[expr.u.a->name];
85  case ExprType::Ident:
86  return env[expr.u.id->name]; /* 存在しない場合は0が生成される */
87  case ExprType::If:
88  if (evaluate(expr.u.if_->condition, env, functions))
89  {
90  return evaluate(expr.u.if_->thenClause, env, functions);
91  }
92  else
93  {
94  return evaluate(expr.u.if_->elseClause, env, functions);
95  }
96  case ExprType::While:
97  {
98  int result = 0;
99  while (evaluate(expr.u.w->condition, env, functions))
100  {
101  result = evaluate(expr.u.w->body, env, functions);
102  }
103  return result;
104  }
105  case ExprType::For:
106  {
107  int result = 0;
108  evaluate(expr.u.f->init, env, functions);
109  while (evaluate(expr.u.f->condition, env, functions))
110  {
111  result = evaluate(expr.u.f->body, env, functions);
112  evaluate(expr.u.f->update, env, functions);
113  }
114  return result;
115  }
116  case ExprType::Call:
117  {
118  try
119  {
120  struct SFunction function = functions.at(expr.u.c->name);
121  map<string, int> newEnv = {};
122  for (struct Expr i : expr.u.c->args)
123  {
124  // newEnv.insert_or_assign(i.u.a->name, evaluate(i.u.a->value, env, functions));
125  newEnv.insert_or_assign(function.args.front(), evaluate(i, env, functions));
126  function.args.pop_front();
127  }
128  return evaluate(function.body, newEnv);
129  }
130  catch (const std::out_of_range &e)
131  {
132  std::cerr << "Error Out of Range in Function Call" << e.what() << std::endl;
133  break;
134  }
135  }
136 
137  default:
138  std::cerr << "Something went wrong." << std::endl;
139  break;
140  }
141  return 0;
142  }
143 
150  int evaluateProgram(struct SProgram &program)
151  {
152  map<string, int> vars = {};
153  map<string, struct SFunction> funcs = {};
154  for (struct SFunction function : program.functions)
155  {
156  funcs.insert_or_assign(function.name, function);
157  }
158  int result = 0;
159  for (struct Expr expr : program.bodies)
160  {
161  result = evaluate(expr, vars, funcs);
162  }
163  return result;
164  }
165 } // namespace SCPP
SCPP::SProgram
プログラムを表す構造体
Definition: scpp_ast.hpp:184
SCPP::evaluateProgram
int evaluateProgram(struct SProgram &program)
プログラムを評価する
Definition: scpp_evaluater.hpp:150
scpp_ast.hpp
Abstract Syntax Tree for SCPP.
SCPP::SFunction
関数を表す構造体
Definition: scpp_ast.hpp:198
SCPP::evaluate
int evaluate(struct Expr &expr, map< string, int > &env=globalVars, map< string, struct SFunction > &functions=globalFuncs)
与えられた式を評価する
Definition: scpp_evaluater.hpp:27
SCPP::Expr
式を表す構造体
Definition: scpp_ast.hpp:38