/* puz.gr -- elkhound grammar for puz. Copyright (C) 2007 Casey Marshall */ verbatim { #include "TokenCode.h" } context_class PuzContext : public UserActions { public: virtual ~PuzContext() { } class expression { protected: expression *r, *l; expression() { } public: expression(expression *l, expression *r) : r(r), l(l) { } virtual double eval() { return 0.0; } }; class add_expr : public expression { public: add_expr(expression *l, expression *r) : expression(l, r) { } virtual double eval() { return l->eval() + r->eval(); } }; class sub_expr : public expression { public: sub_expr(expression *l, expression *r) : expression(l, r) { } virtual double eval() { return l->eval() - r->eval(); } }; class times_expr : public expression { public: times_expr(expression *l, expression *r) : expression(l, r) { } virtual double eval() { return l->eval() * r->eval(); } }; class div_expr : public expression { public: div_expr(expression *l, expression *r) : expression(l, r) { } virtual double eval() { return l->eval() / r->eval(); } }; class literal : public expression { private: double value; public: literal(double value) : value(value) { } virtual double eval() { return value; } }; class distance : public expression { private: TokenCode kind; public: distance(TokenCode kind) : kind(kind) { } virtual double eval() { extern double edgeDistance; extern double manhattanDistance; extern double manhattanDistanceNoBlank; extern double neighborDistance; extern double neighborDistanceNoBlank; switch (kind) { case TOK_EDGE: return edgeDistance; case TOK_MANHATTAN: return manhattanDistance; case TOK_MANHATTAN2: return manhattanDistanceNoBlank; case TOK_NEIGHBOR: return neighborDistance; case TOK_NEIGHBOR2: return neighborDistanceNoBlank; default: return 0.0; } } }; }; terminals { include("tokens.tok") token(double *) TOK_LITERAL; precedence { left 20 TOK_DIVIDE TOK_TIMES; left 10 TOK_PLUS TOK_MINUS; } } nonterm(PuzContext::expression*) Expr { -> n:TOK_LITERAL { double v = *n; delete n; return new PuzContext::literal(v); } -> TOK_EDGE { return new PuzContext::distance(TOK_EDGE); } -> TOK_MANHATTAN { return new PuzContext::distance(TOK_MANHATTAN); } -> TOK_MANHATTAN2 { return new PuzContext::distance(TOK_MANHATTAN2); } -> TOK_NEIGHBOR { return new PuzContext::distance(TOK_NEIGHBOR); } -> TOK_NEIGHBOR2 { return new PuzContext::distance(TOK_NEIGHBOR2); } -> e1:Expr TOK_PLUS e2:Expr { return new PuzContext::add_expr(e1, e2); } -> e1:Expr TOK_MINUS e2:Expr { return new PuzContext::sub_expr(e1, e2); } -> e1:Expr TOK_TIMES e2:Expr { return new PuzContext::times_expr(e1, e2); } -> e1:Expr TOK_DIVIDE e2:Expr { return new PuzContext::div_expr(e1, e2); } -> TOK_LPAREN e:Expr TOK_RPAREN { return e; } }