Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <cstdio>
- struct Token
- {
- enum Kind { Value, Plus, Minus, Mult, Div, Eof };
- int value;
- Kind kind;
- Token():kind(Eof){}
- Token(Kind kind):kind(kind){}
- Token(int value):value(value), kind(Value){}
- bool isOperator() const { return kind != Value; }
- bool operator==(Kind kind) const { return this->kind == kind; }
- bool operator!=(Kind kind) const { return this->kind != kind; }
- std::string toString() {
- switch(kind) {
- case Plus: return "+";
- case Minus: return "-";
- case Mult: return "*";
- case Div: return "/";
- case Eof: return "\0";
- default: break;
- }
- char buff[30];
- sprintf(buff, "%d", value);
- return buff;
- }
- };
- class Lexer
- {
- std::string str;
- size_t cursor;
- char last_char;
- Token last_token;
- char getchar() {
- if(cursor >= str.length())
- return '\0';
- return str[cursor++];
- }
- Token getToken()
- {
- while(last_char == ' ')
- last_char = getchar();
- if(std::isdigit(last_char))
- {
- int val = last_char - '0';
- while(std::isdigit(last_char = getchar()))
- {
- val = val * 10 + last_char - '0';
- }
- return Token(val);
- }
- Token ret;
- if(last_char == '+')
- ret = Token(Token::Plus);
- else if(last_char == '-')
- ret = Token(Token::Minus);
- else if(last_char == '*')
- ret = Token(Token::Mult);
- else if(last_char == '/')
- ret = Token(Token::Div);
- last_char = getchar();
- return ret;
- }
- public:
- Lexer(const std::string & str):str(str),cursor(0),last_char(' '){}
- Token get() { return last_token = getToken(); }
- Token last() const { return last_token; }
- };
- struct Ast
- {
- virtual float eval() const = 0;
- virtual std::string infix() const = 0;
- };
- struct BinaryOpAst : public Ast
- {
- Ast * left;
- Ast * right;
- BinaryOpAst(Ast * left, Ast * right):left(left),right(right){}
- };
- struct OpAddAst : public BinaryOpAst
- {
- OpAddAst(Ast * left, Ast * right):BinaryOpAst(left, right) {}
- float eval() const { return left->eval() + right->eval(); }
- std::string infix() const { return "(" + left->infix() + " + " + right->infix() + ")"; }
- };
- struct OpSubAst : public BinaryOpAst
- {
- OpSubAst(Ast * left, Ast * right):BinaryOpAst(left, right) {}
- float eval() const { return left->eval() - right->eval(); }
- std::string infix() const { return "(" + left->infix() + " - " + right->infix() + ")"; }
- };
- struct OpMultAst : public BinaryOpAst
- {
- OpMultAst(Ast * left, Ast * right):BinaryOpAst(left, right) {}
- float eval() const { return left->eval() * right->eval(); }
- std::string infix() const { return "(" + left->infix() + " * " + right->infix() + ")"; }
- };
- struct OpDivAst : public BinaryOpAst
- {
- OpDivAst(Ast * left, Ast * right):BinaryOpAst(left, right) {}
- float eval() const { return left->eval() / right->eval(); }
- std::string infix() const { return "(" + left->infix() + " / " + right->infix() + ")"; }
- };
- struct ValueAst : public Ast
- {
- float value;
- ValueAst(float value):value(value){}
- float eval() const { return value; }
- std::string infix() const {
- char buff[30];
- sprintf(buff, "%d", (int)value);
- return buff;
- }
- };
- class Parser
- {
- Ast * parseBinaryOperation(Lexer & lex);
- Ast * parseValue(Lexer & lex);
- Ast * parse(Lexer & lex);
- public:
- static Ast * parseString(const std::string & str);
- };
- Ast * Parser::parseString(const std::string & str)
- {
- Lexer lex(str);
- Parser parser;
- return parser.parse(lex);
- }
- Ast * Parser::parseBinaryOperation(Lexer & lex)
- {
- switch(lex.last().kind)
- {
- case Token::Plus: return new OpAddAst(parse(lex), parse(lex));
- case Token::Minus: return new OpSubAst(parse(lex), parse(lex));
- case Token::Mult: return new OpMultAst(parse(lex), parse(lex));
- case Token::Div: return new OpDivAst(parse(lex), parse(lex));
- default: return 0; // nullptr
- }
- }
- Ast * Parser::parseValue(Lexer & lex)
- {
- return new ValueAst(lex.last().value);
- }
- Ast * Parser::parse(Lexer & lex)
- {
- if(lex.get().isOperator())
- return parseBinaryOperation(lex);
- else
- return parseValue(lex);
- }
- int main()
- {
- std::string str = "+ 5 - - 4 2 + 3 1";
- Ast * ast = Parser::parseString(str);
- std::cout << ast->infix() << std::endl
- << "= " << ast->eval() << std::endl;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement