Interpreter_Pattern - 8BitsCoding/RobotMentor GitHub Wiki
-
Interpreter are all around us. Even now, in this very room.
-
A component that processes structed text data.
-
Does so by turning it into separate lexical tokens and then interpreting sequences of said tokens.
-
Handmade Interpreter:Lexing
-
Handmade Interpreter:Parsing
입력으로 들어온
(13-4)-(12+1)를 문자단위로 나누고 싶다?
struct Token
{
enum Type {interger, plus, minus, lparen, rparen} type;
string text;
Token(Type type, const string & text) : type(type), text(text) {}
friend ostream &operator << (ostream& os, const Token& token) {
os << "`" << token.text << "`";
return os;
}
};
vector<Token> lex(const string& input)
{
vector<Token> result;
for(int i = 0; i < input.size(); i++) {
swithc(input[i])
{
case '+':
result.push_back(Token{Token::plus,"+"});
break;
case '-':
result.push_back(Token{Token::minus,"-"});
break;
case '(':
result.push_back(Token{Token::lparen,"("});
break;
case ')':
result.push_back(Token{Token::rparen,")"});
break;
default:
ostringstream buffer;
buffer << input[i];
for(int j = i+1; j < input.size(); j++)
{
if(isdigit(input[j]))
{
buffer << input[j];
++i;
} else {
result.push_back(Token{ Token::integer, buffer.str()});
break;
}
}
break;
}
}
return result;
}
int main()
{
// 다음을 파싱해보자.
string input{"(13-4)-(12+1)"};
auto tokens = lex(input);
for(auto& t : tokens)
cout << t << " ";
cout << "\n";
/*
'(' '13' '-' '4' ')' '-' '(' '12' '+' '1' ')'
*/
return 0;
}struct Element
{
virtual int eval() const = 0;
};
struct Integer : Element
{
int value;
Integer(int value) : value(value) {}
int eval() const override {
return value;
}
};
struct BinaryOperation : Element
{
enum Type {addition, substraction} type;
shared_ptr<Element> lhs, rhs;
int eval() const override {
auto left = lhs->eval();
auto right = rhs->eval();
if(type == addition)
return left+right;
else return left - right;
}
};
shared_ptr<Element> parse(const vector<Token>& tokens)
{
auto result = make_unique<BinaryOperation>();
bool have_lhs{false};
for(int i = 0; i < tokens.size(); i++) {
auto& token = tokens[i];
switch(token.type)
{
case Token::integer:
int value = lexical_cast<int>(token.text);
auto integer = make_shared<Integer>(value);
if(!have_lhs)
{
result->lhs = integer;
have_lhs = true;
}
else result->rhs = integer;
break;
case Token::plus:
result->type = BinaryOperation::addition;
break;
case Token::minus:
result->type = BinaryOperation::substraction;
break;
case Token::lparen:
int j = i;
for(; j < tokens.size(); ++j)
if(tokens[j].type == Token::rparen)
break;
vector<Token> subexpression(&tokens[i+1], &tokens[j]);
auto element = parse(subexpression);
if(!have_lhs)
{
result->lhs = element;
have_lhs = true;
} else resutl->rhs = elements;
break;
}
}
}
int main()
{
// 다음을 파싱해보자.
string input{"(13-4)-(12+1)"};
auto tokens = lex(input);
for(auto& t : tokens)
cout << t << " ";
cout << "\n";
/*
'(' '13' '-' '4' ')' '-' '(' '12' '+' '1' ')'
*/
try {
auto parsed = parse(tokens);
cout << input << " = " << parse->eval() << endl;
} catch (const exception& e)
{
cout << e.what() << endl;
}
/*
(13-4)-(12+1) = -4
*/
return 0;
}#include <iostream>
#include <string>
#include <vector>
#include <cctype>
#include <sstream>
#include <memory>
using namespace std;
#include <boost/lexical_cast.hpp>
struct Token
{
enum Type { integer, plus, minus, lparen, rparen } type;
string text;
explicit Token(Type type, const string& text) :
type{type}, text{text} {}
friend ostream& operator<<(ostream& os, const Token& obj)
{
return os << "`" << obj.text << "`";
}
};
struct Element
{
virtual ~Element() = default;
virtual int eval() const = 0;
};
struct Integer : Element
{
int value;
explicit Integer(const int value)
: value(value)
{
}
int eval() const override { return value; }
};
struct BinaryOperation : Element
{
enum Type { addition, subtraction } type;
shared_ptr<Element> lhs, rhs;
int eval() const override
{
if (type == addition)
return lhs->eval() + rhs->eval();
return lhs->eval() - rhs->eval();
}
};
shared_ptr<Element> parse(const vector<Token>& tokens)
{
auto result = make_unique<BinaryOperation>();
bool have_lhs = false;
for (size_t i = 0; i < tokens.size(); i++)
{
auto token = tokens[i];
switch(token.type)
{
case Token::integer:
{
int value = boost::lexical_cast<int>(token.text);
auto integer = make_shared<Integer>(value);
if (!have_lhs) {
result->lhs = integer;
have_lhs = true;
}
else result->rhs = integer;
}
break;
case Token::plus:
result->type = BinaryOperation::addition;
break;
case Token::minus:
result->type = BinaryOperation::subtraction;
break;
case Token::lparen:
{
int j = i;
for (; j < tokens.size(); ++j)
if (tokens[j].type == Token::rparen)
break; // found it!
vector<Token> subexpression(&tokens[i + 1], &tokens[j]);
auto element = parse(subexpression);
if (!have_lhs)
{
result->lhs = element;
have_lhs = true;
}
else result->rhs = element;
i = j; // advance
}
break;
}
}
return result;
}
vector<Token> lex(const string& input)
{
vector<Token> result;
for (int i = 0; i < input.size(); ++i)
{
switch (input[i])
{
case '+':
result.push_back(Token{ Token::plus, "+" });
break;
case '-':
result.push_back(Token{ Token::minus, "-" });
break;
case '(':
result.push_back(Token{ Token::lparen, "(" });
break;
case ')':
result.push_back(Token{ Token::rparen, ")" });
break;
default:
// number
ostringstream buffer;
buffer << input[i];
for (int j = i + 1; j < input.size(); ++j)
{
if (isdigit(input[j]))
{
buffer << input[j];
++i;
}
else
{
result.push_back(Token{ Token::integer, buffer.str() });
break;
}
}
}
}
return result;
}
int main()
{
string input{ "(13-4)-(12+1)" }; // see if you can make nested braces work
auto tokens = lex(input);
// let's see the tokens
for (auto& t : tokens)
cout << t << " ";
cout << endl;
try {
auto parsed = parse(tokens);
cout << input << " = " << parsed->eval() << endl;
}
catch (const exception& e)
{
cout << e.what() << endl;
}
getchar();
return 0;
}