#1 DMS
Mozes skusit takyto parser:
#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;
break;
};
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 ')'");
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 = parseValue(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 << "(" << tok.key << "\t:\t" << tok.val << ")\n";
auto tok = tokens.begin();
double d = parseAdd(tok);
if(tok->key == Key::Eof)return d;
throw std::logic_error("PARSE ERROR");
}
int main(){
using namespace std;
while(1){
std::cout << "= " << parse(scan(std::cin)) << ";\n\n";
}
return 0;
}
Tento konkretny parser vie spracovat matematicky vyraz obsahujuci operatory + - * / a zatvorky () .
Vyraz musy byt ukonceny znakom '\n'.
Operatory * a / maju vecsiu prioritu ako + a -.
Po urcitych upravach by sa tento parser dal pouzit aj pre tvoj pripad.