Poincare: RuleGen now uses a more explicit grammar

Change-Id: I22ca00a7115d8c60fd0aa95ec17deec829e0a69d
Examples: Integer.a and Integer["0"]
This commit is contained in:
Romain Goyet
2016-04-07 15:39:47 +02:00
parent 1f64dfda9d
commit d2a010be70
11 changed files with 215 additions and 193 deletions

View File

@@ -3,10 +3,8 @@ dir=poincare/src/simplify/rules_generation
rulegen_objs := $(addprefix $(dir)/,\
rules_parser.o\
rules_lexer.o\
builder.o\
node.o\
rule.o\
selector.o\
)
$(dir)/rules_parser.cpp: $(dir)/rules_parser.y

View File

@@ -1,33 +0,0 @@
#include "builder.h"
#include "rule.h"
#include <iostream>
#include <cassert>
Builder::Builder(Type type, std::string * name, std::vector<Builder *> * children) :
Node(name, (std::vector<Node *> *)children),
m_type(type)
{
}
void Builder::generateFields(Rule * context, std::string &indentation) {
Selector * selector = context->selector();
switch (m_type) {
case Type::ExpressionType:
std::cout << indentation << ".m_action = ExpressionBuilder::Action::BuildFromTypeAndValue," << std::endl;
std::cout << indentation << ".m_expressionType = Expression::Type::" << *m_name << "," << std::endl;
break;
case Type::Variable:
std::cout << indentation << ".m_action = ExpressionBuilder::Action::Clone," << std::endl;
assert(m_children->size() == 0);
std::cout << indentation << ".m_matchIndex = " << selector->flatIndexOfChildNamed(*m_name) << "," << std::endl;
break;
case Type::Wildcard:
std::cout << indentation << ".m_action = ExpressionBuilder::Action::BringUpWildcard," << std::endl;
assert(m_children->size() == 0);
std::cout << indentation << ".m_matchIndex = " << selector->flatIndexOfChildNamed(*m_name) << "," << std::endl;
break;
case Type::ExpressionGenerator:
assert(false); // Not implemented yet.
break;
}
}

View File

@@ -1,22 +0,0 @@
#ifndef POINCARE_SIMPLIFY_RULES_GENERATION_BUILDER_H
#define POINCARE_SIMPLIFY_RULES_GENERATION_BUILDER_H
#include "node.h"
#include <string>
class Builder : public Node {
public:
enum class Type {
ExpressionGenerator,
ExpressionType,
Variable,
Wildcard
};
Builder(Type type, std::string * name, std::vector<Builder *> * children = nullptr);
protected:
void generateFields(Rule * context, std::string &indentation) override;
private:
Type m_type;
};
#endif

View File

@@ -1,25 +1,113 @@
#include "builder.h"
#include "node.h"
#include "rule.h"
#include <iostream>
#include <sstream>
#include <cassert>
Node::Node(std::string * name, std::vector<Node *> * children) :
m_name(name),
m_children(children)
Node::Node(Type type, std::string * typeName) :
m_type(type),
m_typeName(typeName),
m_referenceMode(ReferenceMode::None),
m_referenceName(nullptr),
m_value(nullptr),
m_parent(nullptr)
{
if (children == nullptr) {
m_children = new std::vector<Node *>();
}
for (Node * child : *m_children) {
child->m_parent = this;
}
m_children = new std::vector<Node *>();
}
Node::~Node() {
delete m_children;
}
void Node::setReference(ReferenceMode mode, std::string * referenceName) {
assert(m_referenceName == nullptr);
m_referenceName = referenceName;
m_referenceMode = mode;
}
void Node::setValue(std::string * value) {
assert(m_value == nullptr);
m_value = value;
}
void Node::setChildren(std::vector<Node *> * children) {
assert(m_children->size() == 0);
delete m_children;
m_children = children;
for (Node * child : *m_children) {
child->m_parent = this;
}
}
// Generation
std::string Node::generateSelectorConstructor(Rule * context) {
std::ostringstream result;
switch (m_type) {
case Node::Type::Any:
switch (m_referenceMode) {
case Node::ReferenceMode::None:
case Node::ReferenceMode::SingleNode:
result << "ExpressionSelector::Any(";
break;
case Node::ReferenceMode::Wildcard:
result << "ExpressionSelector::Wildcard(";
break;
}
break;
case Node::Type::Expression:
if (m_value == nullptr) {
result << "ExpressionSelector::Type(Expression::Type::" << *m_typeName << ", ";
} else {
result << "ExpressionSelector::TypeAndValue(Expression::Type::" << *m_typeName << ", " << *m_value << ",";
}
break;
case Node::Type::Generator:
//assert(false);
break;
}
result << m_children->size() << ")";
return result.str();
}
std::string Node::generateBuilderConstructor(Rule * context) {
Node * selector = context->selector();
std::ostringstream result;
switch (m_type) {
case Node::Type::Any:
switch (m_referenceMode) {
case Node::ReferenceMode::None:
assert(false);
break;
case Node::ReferenceMode::SingleNode:
assert(m_referenceName != nullptr);
result << "ExpressionBuilder::Clone(" << selector->flatIndexOfChildNamed(*m_referenceName) << ", " ;
break;
case Node::ReferenceMode::Wildcard:
result << "ExpressionBuilder::BringUpWildcard(" << selector->flatIndexOfChildNamed(*m_referenceName) << ", ";
break;
}
break;
case Node::Type::Expression:
if (m_value == nullptr) {
// Here we could assert that m_typeName is among the kinds that expect no value
result << "ExpressionBuilder::BuildFromType(Expression::Type::" << *m_typeName << ", ";
} else {
// Here we could assert that m_typeName is among the kinds that expect a value
result << "ExpressionBuilder::BuildFromTypeAndValue(Expression::Type::" << *m_typeName << ", " << *m_value << ", ";
}
break;
case Node::Type::Generator:
result << "ExpressionBuilder::CallExternalGenerator(SimplificationGenerator::" << *m_typeName << ", ";
//assert(false);
break;
}
result << m_children->size() << ")";
return result.str();
}
int Node::flatIndexOfChildNamed(std::string name) {
if (name == *m_name) {
if (m_referenceName != nullptr && *m_referenceName == name) {
return 0;
}
int sum=1;
@@ -54,17 +142,26 @@ std::string indentation_string(int i) {
return result;
}
int Node::generate(Rule * context, int index, int indentationLevel) {
void Node::generateSelectorTree(Rule * context) {
generateTree(true, context, 0, 0);
}
void Node::generateBuilderTree(Rule * context) {
generateTree(false, context, 0, 0);
}
int Node::generateTree(bool selector, Rule * context, int index, int indentationLevel) {
std::string indentation = indentation_string(indentationLevel);
std::string nextIndentation = indentation_string(indentationLevel+1);
std::cout << indentation << "{" << std::endl;
std::cout << nextIndentation << "// #" << index << std::endl;
this->generateFields(context, nextIndentation);
std::cout << nextIndentation << ".m_numberOfChildren = " << m_children->size() << "," << std::endl;
std::cout << indentation << "}," << std::endl;
std::cout << indentation;
if (selector) {
std::cout << generateSelectorConstructor(context);
} else {
std::cout << generateBuilderConstructor(context);
}
std::cout << ", // #" << index << std::endl;
int generatedCount = 1;
for (Node * child : *m_children) {
generatedCount += child->generate(context, index+generatedCount, indentationLevel+1);
generatedCount += child->generateTree(selector, context, index+generatedCount, indentationLevel+1);
}
return generatedCount;
}

View File

@@ -8,14 +8,39 @@ class Rule;
class Node {
public:
Node(std::string * name, std::vector<Node *> * m_children);
enum class Type {
Expression,
Generator,
Any
};
enum class ReferenceMode {
None,
SingleNode,
Wildcard
};
// Creating Nodes
Node(Type type, std::string * typeName = nullptr);
~Node();
int generate(Rule * context = nullptr, int index = 0, int indentationLevel = 0);
void setReference(ReferenceMode mode, std::string * referenceName);
void setValue(std::string * value);
void setChildren(std::vector<Node *> * children);
int totalDescendantCountIncludingSelf();
int flatIndexOfChildNamed(std::string name);
protected:
virtual void generateFields(Rule * context, std::string &indentation) = 0;
std::string * m_name;
void generateSelectorTree(Rule * context);
void generateBuilderTree(Rule * context);
private:
int generateTree(bool selector, Rule * context, int index, int indentationLevel);
std::string generateSelectorConstructor(Rule * context);
std::string generateBuilderConstructor(Rule * context);
Type m_type;
std::string * m_typeName;
ReferenceMode m_referenceMode;
std::string * m_referenceName;
std::string * m_value;
std::vector<Node *> * m_children;
Node * m_parent;
};

View File

@@ -1,7 +1,7 @@
#include "rule.h"
#include <iostream>
Rule::Rule(Selector * selector, Builder * builder) :
Rule::Rule(Node * selector, Node * builder) :
m_selector(selector), m_builder(builder) {
}
@@ -10,16 +10,16 @@ Rule::~Rule() {
delete m_selector;
}
Selector * Rule::selector() {
Node * Rule::selector() {
return m_selector;
}
void Rule::generate(std::string rule_name) {
std::cout << "const ExpressionSelector " << rule_name << "Selector[" << m_selector->totalDescendantCountIncludingSelf() << "] = {" << std::endl;
m_selector->generate(this);
std::cout << "constexpr ExpressionSelector " << rule_name << "Selector[" << m_selector->totalDescendantCountIncludingSelf() << "] = {" << std::endl;
m_selector->generateSelectorTree(this);
std::cout << "};" << std::endl;
std::cout << "const ExpressionBuilder " << rule_name << "Builder[" << m_builder->totalDescendantCountIncludingSelf() << "] = {" << std::endl;
m_builder->generate(this);
std::cout << "constexpr ExpressionBuilder " << rule_name << "Builder[" << m_builder->totalDescendantCountIncludingSelf() << "] = {" << std::endl;
m_builder->generateBuilderTree(this);
std::cout << "};" << std::endl;
}

View File

@@ -1,18 +1,17 @@
#ifndef POINCARE_SIMPLIFY_RULES_GENERATION_RULE_H
#define POINCARE_SIMPLIFY_RULES_GENERATION_RULE_H
#include "selector.h"
#include "builder.h"
#include "node.h"
class Rule {
public:
Rule(Selector * selector, Builder * builder);
Rule(Node * selector, Node * builder);
~Rule();
void generate(std::string rule_name);
Selector * selector();
Node * selector();
private:
Selector * m_selector;
Builder * m_builder;
Node * m_selector;
Node * m_builder;
};
#endif

View File

@@ -9,14 +9,18 @@
%%
[A-Z][a-z]+ { yylval.string = new std::string(yytext); return(EXPRESSION_TYPE); }
\$[a-zA-Z]+ { yylval.string = new std::string(yytext); return(EXPRESSION_GENERATOR); }
[a-z]+\* { yylval.string = new std::string(yytext); return(WILDCARD); }
[a-z]+ { yylval.string = new std::string(yytext); return(VARIABLE); }
[a-z]+ { yylval.string = new std::string(yytext); return (IDENTIFIER); }
[A-Za-z]+ { yylval.string = new std::string(yytext); return (CAPITALIZED_IDENTIFIER); }
[0-9]+ { yylval.string = new std::string(yytext); return (VALUE); }
\$ { return(DOLLAR); }
\* { return (ASTERISK); }
\-\> { return(SIMPLIFIES_TO); }
\( { return(LEFT_PARENTHESIS); }
\) { return(RIGHT_PARENTHESIS); }
\[ { return(LEFT_BRACKET); }
\] { return(RIGHT_BRACKET); }
\, { return(COMMA); }
\; { return(SEMICOLON); }
\. { return(PERIOD); }
%%

View File

@@ -23,39 +23,38 @@ int yyerror(std::vector<Rule *> ** rules, const char *s);
* when parsing (a/b) we want to create a new Fraction), or a string (this will
* be useful to retrieve the value of Integers for example). */
%union {
std::vector<Builder *> * builder_list;
std::vector<Selector *> * selector_list;
std::vector<Rule *> * rule_list;
std::vector<Node *> * node_list;
Rule * rule;
Selector * selector;
Builder * builder;
Node * node;
std::string * string;
}
/* The INTEGER token uses the "string" part of the union to store its value */
%token <string> INTEGER
%token <string> SYMBOL
/* The IDENTIFIER, CAPITALIZED_IDENTIFIER and VALUE token uses the "string" part
* of the union to store their value */
%token <string> EXPRESSION_TYPE
%token <string> EXPRESSION_GENERATOR
%token <string> WILDCARD
%token <string> VARIABLE
%token <string> IDENTIFIER
%token <string> CAPITALIZED_IDENTIFIER
%token <string> VALUE
/* Some tokens don't store any value */
%token SIMPLIFIES_TO
%token LEFT_PARENTHESIS
%token RIGHT_PARENTHESIS
%token LEFT_BRACKET
%token RIGHT_BRACKET
%token COMMA
%token SEMICOLON
%token PERIOD
%token DOLLAR
%token ASTERISK
/* The "rule_list" symbol uses the "rule_list" part of the union, and so on */
%type <rule_list> rule_list;
%type <rule> rule;
%type <selector> selector;
%type <selector_list> selector_list;
%type <builder> builder;
%type <builder_list> builder_list;
/* The "exp" symbol uses the "expression" part of the union. */
/*%type <expression> exp;*/
%type <node> node;
%type <node_list> node_list;
%%
@@ -67,32 +66,39 @@ rule_list:
| rule_list rule { $1->push_back($2); $$ = $1; }
rule:
selector SIMPLIFIES_TO builder SEMICOLON { $$ = new Rule($1, $3); }
node SIMPLIFIES_TO node SEMICOLON { $$ = new Rule($1, $3); }
selector:
VARIABLE { $$ = new Selector(Selector::Type::Variable, $1); }
| WILDCARD { $$ = new Selector(Selector::Type::Wildcard, $1); }
| EXPRESSION_TYPE LEFT_PARENTHESIS selector_list RIGHT_PARENTHESIS {
$$ = new Selector(Selector::Type::ExpressionType, $1, $3);
node:
CAPITALIZED_IDENTIFIER {
$$ = new Node(Node::Type::Expression, $1);
}
| DOLLAR CAPITALIZED_IDENTIFIER {
$$ = new Node(Node::Type::Generator, $2);
}
| IDENTIFIER {
$$ = new Node(Node::Type::Any);
$$->setReference(Node::ReferenceMode::SingleNode, $1);
}
| IDENTIFIER ASTERISK {
$$ = new Node(Node::Type::Any);
$$->setReference(Node::ReferenceMode::Wildcard, $1);
}
| node PERIOD IDENTIFIER {
$$ = $1;
$$->setReference(Node::ReferenceMode::SingleNode, $3);
}
| node LEFT_BRACKET IDENTIFIER RIGHT_BRACKET {
$$ = $1;
$$->setValue($3);
}
| node LEFT_PARENTHESIS node_list RIGHT_PARENTHESIS {
$$ = $1;
$$->setChildren($3);
}
selector_list:
selector { $$ = new std::vector<Selector *>(); $$->push_back($1); }
| selector_list COMMA selector { $1->push_back($3); $$ = $1; }
builder:
VARIABLE { $$ = new Builder(Builder::Type::Variable, $1); }
| WILDCARD { $$ = new Builder(Builder::Type::Wildcard, $1); }
| EXPRESSION_GENERATOR LEFT_PARENTHESIS builder_list RIGHT_PARENTHESIS {
$$ = new Builder(Builder::Type::ExpressionGenerator, $1, $3);
}
| EXPRESSION_TYPE LEFT_PARENTHESIS builder_list RIGHT_PARENTHESIS {
$$ = new Builder(Builder::Type::ExpressionType, $1, $3);
}
builder_list:
builder { $$ = new std::vector<Builder *>(); $$->push_back($1); }
| builder_list COMMA builder { $1->push_back($3); $$ = $1; }
node_list:
node { $$ = new std::vector<Node *>(); $$->push_back($1); }
| node_list COMMA node { $1->push_back($3); $$ = $1; }
%%
@@ -120,20 +126,16 @@ int main(void) {
rules->at(i)->generate(name.str());
std::cout << std::endl;
}
std::cout << "const Simplification simplifications[" << rules->size() << "] = {" << std::endl;
std::cout << "constexpr Simplification simplifications[" << rules->size() << "] = {" << std::endl;
for (int i=0; i<rules->size(); i++) {
std::stringstream name;
name << "rule" << i;
std::cout << " {" << std::endl;
std::cout << " .m_selector = (ExpressionSelector *)" << name.str() << "Selector," << std::endl;
std::cout << " .m_builder = (ExpressionBuilder *)" << name.str() << "Builder," << std::endl;
std::cout << " }," << std::endl;
std::cout << " Simplification((ExpressionSelector *)" << name.str() << "Selector, (ExpressionBuilder *)" << name.str() << "Builder)," << std::endl;
}
std::cout << "};" << std::endl;
std::cout << std::endl;
std::cout << "const int knumberOfSimplifications = " << rules->size() << ";" << std::endl;
std::cout << "constexpr int knumberOfSimplifications = " << rules->size() << ";" << std::endl;
delete rules;
return 0;

View File

@@ -1,27 +0,0 @@
#include "selector.h"
#include <iostream>
#include <cassert>
Selector::Selector(Type type, std::string * name, std::vector<Selector *> * children) :
Node(name, (std::vector<Node *> *)children),
m_type(type)
{
}
void Selector::generateFields(Rule * context, std::string &indentation) {
Selector * parent = (Selector *)m_parent;
switch (m_type) {
case Type::Variable:
std::cout << indentation << ".m_match = ExpressionSelector::Match::Any," << std::endl;
break;
case Type::Wildcard:
std::cout << indentation << ".m_match = ExpressionSelector::Match::Wildcard," << std::endl;
// Wildcard should always be the last element of a parent
assert(parent->m_children->back() == this);
break;
case Type::ExpressionType:
std::cout << indentation << ".m_match = ExpressionSelector::Match::Type," << std::endl;
std::cout << indentation << ".m_expressionType = Expression::Type::" << *m_name << "," << std::endl;
break;
}
}

View File

@@ -1,21 +0,0 @@
#ifndef POINCARE_SIMPLIFY_RULES_GENERATION_SELECTOR_H
#define POINCARE_SIMPLIFY_RULES_GENERATION_SELECTOR_H
#include "node.h"
#include <string>
class Selector : public Node {
public:
enum class Type {
Variable,
Wildcard,
ExpressionType
};
Selector(Type type, std::string * name, std::vector<Selector *> * children = nullptr);
protected:
void generateFields(Rule * context, std::string &indentation) override;
private:
Type m_type;
};
#endif