#include <iostream>
#include <sstream>
#include <cctype>
#include <deque>
#include <stack>
#include <vector>
struct Token{
enum TokenType{
END,
INTEGER,
PLUS,
MINUS,
} type;
long intValue;
Token(TokenType type=END):type(type),intValue(0){}
Token(long val):type(INTEGER),intValue(val){}
Token(char character){
//...
}
};
class NonTerminal{
enum NonTerminalType{
terminal,
expr,
} type;
NonTerminal *trunk;
std::vector<NonTerminal> branches;
bool reduced;
public:
Token leaf;
private:
void reduce_terminal(){
this->reduced=1;
switch (this->leaf.type){
case Token::INTEGER:
this->type=expr;
}
}
void reduce_expr(){
if (!this->branches.size())
return;
if (this->branches.size()<3)
this->leaf=this->branches[0].leaf;
else{
this->leaf.type=Token::INTEGER;
switch (this->branches[1].leaf.type){
case Token::PLUS:
this->leaf.intValue=this->branches[0].leaf.intValue+this->branches[2].leaf.intValue;
break;
case Token::MINUS:
this->leaf.intValue=this->branches[0].leaf.intValue-this->branches[2].leaf.intValue;
break;
default:;
}
}
this->reduced=1;
this->branches.clear();
}
public:
NonTerminal(NonTerminal *trunk=0){
this->type=expr;
this->trunk=trunk;
this->reduced=0;
}
NonTerminal(const Token &token,NonTerminal *trunk=0){
this->leaf=token;
this->type=terminal;
this->trunk=trunk;
this->reduced=0;
}
void set(const Token &token){
this->leaf=token;
this->type=terminal;
this->trunk=trunk;
this->reduced=0;
}
void push(const Token &token){
if (this->type==terminal)
return;
this->branches.push_back(NonTerminal(token));
}
NonTerminal *newBranch(const Token &token){
this->branches.push_back(NonTerminal(this));
return &this->branches.back();
}
bool isComplete(){
if (this->type==terminal)
return 1;
if (!this->branches.size())
return 0;
for (unsigned a=0;a<this->branches.size();a++)
if (this->branches[a].type!=terminal && !this->branches[a].reduced)
return 0;
switch (this->branches.size()){
case 1:
return this->branches[0].leaf.type==Token::INTEGER;
case 3:
if (this->branches[0].leaf.type!=Token::INTEGER ||
this->branches[1].leaf.type!=Token::PLUS &&
this->branches[1].leaf.type!=Token::MINUS ||
this->branches[2].leaf.type!=Token::INTEGER)
return 0;
return 1;
default:
return 0;
}
}
NonTerminal *reduce(){
if (!this->isComplete())
return 0;
switch (this->type){
case terminal:
this->reduce_terminal();
break;
case expr:
this->reduce_expr();
break;
}
return this->trunk?this->trunk:this;
}
};
class Parser{
std::deque<Token> expression;
std::stack<Token> stack;
long result;
unsigned state;
NonTerminal tree,
*current_node;
Token read(std::stringstream &stream){
//(lexer)
}
unsigned run_state(){
Token::TokenType front_token_type;
switch (this->state){
case 0:
front_token_type=this->expression.front().type;
if (front_token_type==Token::INTEGER)
return 3;
if (front_token_type==Token::END)
return 1;
return 2;
case 3:
this->current_node->push(this->expression.front());
this->expression.pop_front();
if (this->current_node->isComplete())
this->current_node=this->current_node->reduce();
front_token_type=this->expression.front().type;
if (front_token_type==Token::PLUS ||
front_token_type==Token::MINUS)
return 4;
if (front_token_type==Token::END)
return 1;
return 2;
case 4:
this->current_node->push(this->expression.front());
this->expression.pop_front();
front_token_type=this->expression.front().type;
if (front_token_type==Token::INTEGER)
return 3;
return 2;
default:
return this->state;
}
}
//1: continue, 0: accept, -1: abort
int to_state(unsigned n){
this->state=n;
switch (n){
case 1:
return 0;
case 2:
return -1;
default:
return 1;
}
}
public:
Parser(const std::string &str){
std::stringstream stream(str);
do
this->expression.push_back(this->read(stream));
while (this->expression.back().type!=Token::END);
this->result=0;
this->state=0;
this->current_node=&this->tree;
}
bool eval(long &res){
int ret;
while ((ret=this->to_state(this->run_state()))==1);
if (!ret){
this->tree.reduce();
res=this->tree.leaf.intValue;
}
return !ret;
}
};
int main(){
Parser evaluator("12+3-2");
long res;
std::cout <<evaluator.eval(res)<<std::endl;
std::cout <<res<<std::endl;
return 0;
}
#include <sstream>
#include <cctype>
#include <deque>
#include <stack>
#include <vector>
struct Token{
enum TokenType{
END,
INTEGER,
PLUS,
MINUS,
} type;
long intValue;
Token(TokenType type=END):type(type),intValue(0){}
Token(long val):type(INTEGER),intValue(val){}
Token(char character){
//...
}
};
class NonTerminal{
enum NonTerminalType{
terminal,
expr,
} type;
NonTerminal *trunk;
std::vector<NonTerminal> branches;
bool reduced;
public:
Token leaf;
private:
void reduce_terminal(){
this->reduced=1;
switch (this->leaf.type){
case Token::INTEGER:
this->type=expr;
}
}
void reduce_expr(){
if (!this->branches.size())
return;
if (this->branches.size()<3)
this->leaf=this->branches[0].leaf;
else{
this->leaf.type=Token::INTEGER;
switch (this->branches[1].leaf.type){
case Token::PLUS:
this->leaf.intValue=this->branches[0].leaf.intValue+this->branches[2].leaf.intValue;
break;
case Token::MINUS:
this->leaf.intValue=this->branches[0].leaf.intValue-this->branches[2].leaf.intValue;
break;
default:;
}
}
this->reduced=1;
this->branches.clear();
}
public:
NonTerminal(NonTerminal *trunk=0){
this->type=expr;
this->trunk=trunk;
this->reduced=0;
}
NonTerminal(const Token &token,NonTerminal *trunk=0){
this->leaf=token;
this->type=terminal;
this->trunk=trunk;
this->reduced=0;
}
void set(const Token &token){
this->leaf=token;
this->type=terminal;
this->trunk=trunk;
this->reduced=0;
}
void push(const Token &token){
if (this->type==terminal)
return;
this->branches.push_back(NonTerminal(token));
}
NonTerminal *newBranch(const Token &token){
this->branches.push_back(NonTerminal(this));
return &this->branches.back();
}
bool isComplete(){
if (this->type==terminal)
return 1;
if (!this->branches.size())
return 0;
for (unsigned a=0;a<this->branches.size();a++)
if (this->branches[a].type!=terminal && !this->branches[a].reduced)
return 0;
switch (this->branches.size()){
case 1:
return this->branches[0].leaf.type==Token::INTEGER;
case 3:
if (this->branches[0].leaf.type!=Token::INTEGER ||
this->branches[1].leaf.type!=Token::PLUS &&
this->branches[1].leaf.type!=Token::MINUS ||
this->branches[2].leaf.type!=Token::INTEGER)
return 0;
return 1;
default:
return 0;
}
}
NonTerminal *reduce(){
if (!this->isComplete())
return 0;
switch (this->type){
case terminal:
this->reduce_terminal();
break;
case expr:
this->reduce_expr();
break;
}
return this->trunk?this->trunk:this;
}
};
class Parser{
std::deque<Token> expression;
std::stack<Token> stack;
long result;
unsigned state;
NonTerminal tree,
*current_node;
Token read(std::stringstream &stream){
//(lexer)
}
unsigned run_state(){
Token::TokenType front_token_type;
switch (this->state){
case 0:
front_token_type=this->expression.front().type;
if (front_token_type==Token::INTEGER)
return 3;
if (front_token_type==Token::END)
return 1;
return 2;
case 3:
this->current_node->push(this->expression.front());
this->expression.pop_front();
if (this->current_node->isComplete())
this->current_node=this->current_node->reduce();
front_token_type=this->expression.front().type;
if (front_token_type==Token::PLUS ||
front_token_type==Token::MINUS)
return 4;
if (front_token_type==Token::END)
return 1;
return 2;
case 4:
this->current_node->push(this->expression.front());
this->expression.pop_front();
front_token_type=this->expression.front().type;
if (front_token_type==Token::INTEGER)
return 3;
return 2;
default:
return this->state;
}
}
//1: continue, 0: accept, -1: abort
int to_state(unsigned n){
this->state=n;
switch (n){
case 1:
return 0;
case 2:
return -1;
default:
return 1;
}
}
public:
Parser(const std::string &str){
std::stringstream stream(str);
do
this->expression.push_back(this->read(stream));
while (this->expression.back().type!=Token::END);
this->result=0;
this->state=0;
this->current_node=&this->tree;
}
bool eval(long &res){
int ret;
while ((ret=this->to_state(this->run_state()))==1);
if (!ret){
this->tree.reduce();
res=this->tree.leaf.intValue;
}
return !ret;
}
};
int main(){
Parser evaluator("12+3-2");
long res;
std::cout <<evaluator.eval(res)<<std::endl;
std::cout <<res<<std::endl;
return 0;
}
No comments:
Post a Comment