Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <vector>
- #include <iostream>
- #include <stdexcept>
- #include <cassert>
- enum class Key{
- Number,
- OpAdd,
- OpSub,
- OpMul,
- OpDiv,
- OpBracketL,
- OpBracketR,
- Eof
- };
- struct Token{
- Key key;
- std::string val;
- Token(Key key):key(key){}
- Token(Key key, const std::string& val):key(key), val(val){}
- Token(Key key, std::string&& val):key(key), val(std::move(val)){}
- };
- std::vector<Token> scan(std::istream& in){
- std::vector<Token> tokens;
- while(1){
- int i = in.get();
- DENGO:
- switch(i){
- case ' ':
- case '\t':
- continue;
- case '\n':
- tokens.emplace_back(Key::Eof);
- return tokens;
- case '+':
- tokens.emplace_back(Key::OpAdd);
- continue;
- case '-':
- tokens.emplace_back(Key::OpSub);
- continue;
- case '*':
- tokens.emplace_back(Key::OpMul);
- continue;
- case '/':
- tokens.emplace_back(Key::OpDiv);
- continue;
- case '(':
- tokens.emplace_back(Key::OpBracketL);
- continue;
- case ')':
- tokens.emplace_back(Key::OpBracketR);
- continue;
- case '0':case '1':case '2':case '3':case '4':
- case '5':case '6':case '7':case '8':case '9': {
- std::string str;
- str += (char)i;
- while(1) switch((i = in.get())){
- case '0':case '1':case '2':case '3':case '4':
- case '5':case '6':case '7':case '8':case '9':
- str += (char)i;
- continue;
- case '\n':
- tokens.emplace_back(Key::Number, str);
- tokens.emplace_back(Key::Eof);
- return tokens;
- default:
- tokens.emplace_back(Key::Number, str);
- goto DENGO;
- };
- continue;
- }
- }
- throw std::logic_error("Neznamy symbol");
- }
- assert(0);
- }
- double parseValue(std::vector<Token>::const_iterator& tok);
- double parseAdd(std::vector<Token>::const_iterator& tok);
- double parseMul(std::vector<Token>::const_iterator& tok);
- double parseValue(std::vector<Token>::const_iterator& tok){
- switch(tok->key){
- case Key::Number:{
- double d = std::stod(tok->val);
- ++tok;
- return d;
- }
- case Key::OpBracketL:{
- double d = parseAdd(++tok);
- if(tok->key != Key::OpBracketR)throw std::logic_error("chyba znak ')'");
- ++tok;
- return d;
- }
- default:
- throw std::logic_error("Neznama hodnota");
- }
- assert(0);
- }
- double parseMul(std::vector<Token>::const_iterator& tok){
- double left = parseValue(tok);
- while(1) switch(tok->key){
- case Key::OpMul:
- left *= parseValue(++tok);
- break;
- case Key::OpDiv:
- left /= parseValue(++tok);
- break;
- default:
- return left;
- }
- assert(0);
- }
- double parseAdd(std::vector<Token>::const_iterator& tok){
- double left = parseMul(tok);
- while(1) switch(tok->key){
- case Key::OpAdd:
- left += parseMul(++tok);
- break;
- case Key::OpSub:
- left -= parseMul(++tok);
- break;
- default:
- return left;
- }
- assert(0);
- }
- double parse(const std::vector<Token>& tokens){
- //for(auto& tok : tokens)std::cout << "(" << (int)tok.key << "\t:\t" << tok.val << ")\n";
- auto tok = tokens.begin();
- double d = parseAdd(tok);
- if(tok->key == Key::Eof)return d;
- std::cout << (int)tok->key;
- throw std::logic_error("PARSE ERROR");
- }
- int main(){
- using namespace std;
- while(1){
- std::cout << "= " << parse(scan(std::cin)) << ";\n\n";
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement