1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*
   Copyright (C) 2009-2019 Andreas Franz Borchert
                 2019 Michael Lehn
   ----------------------------------------------------------------------------
   Astl-ULMcalc is free software; you can redistribute it
   and/or modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either version
   2 of the License, or (at your option) any later version.

   Astl-ULMcalc is distributed in the hope that it will be
   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

%{
namespace AstlULMcalc {
   class Scanner;
}

#include <cassert>
#include <memory>
#include <string>
#include <astl/syntax-tree.hpp>
#include "operators.hpp"
#include "scanner.hpp"
#include "yystype.hpp"
#include "yytname.hpp"

using namespace Astl;

/* location which is computed by the YYLLOC_DEFAULT macro
   in case of a reduce before the corresponding action is executed */
#define YYLLOC (yylhs.location)

#define NODE(op) \
   (std::make_shared<Node>(make_loc(YYLLOC), Op::op))
#define UNARY(unop, op1) \
   (std::make_shared<Node>(make_loc(YYLLOC), Op::unop, (op1)))
#define BINARY(binop, op1,op2) \
   (std::make_shared<Node>(make_loc(YYLLOC), Op::binop, (op1), (op2)))
#define TERTIARY(top, op1,op2,op3) \
   (std::make_shared<Node>(make_loc(YYLLOC), Op::top, (op1), (op2), (op3)))
#define QUATERNARY(top, op1,op2,op3,op4) \
   (std::make_shared<Node>(make_loc(YYLLOC), Op::top, \
      (op1), (op2), (op3), (op4)))
#define QUINARY(top, op1,op2,op3,op4,op5) \
   (std::make_shared<Node>(make_loc(YYLLOC), Op::top, \
      (op1), (op2), (op3), (op4), (op5)))

#define LEAF(tk) \
   (std::make_shared<Node>(make_loc(YYLLOC), Token(token::tk, \
      yytname[token::tk - 255])))

#define FLATTEN(node, subnodes, op) \
   (flatten(node, subnodes, Op::op))

NodePtr flatten(NodePtr node, NodePtr subnodes, const Operator& op);

%}

%skeleton "lalr1.cc"
%define api.prefix {astlulmcalc}
%define api.namespace { AstlULMcalc }
%defines
%verbose
%locations
%token-table
%parse-param { Scanner& scanner }
%parse-param { Astl::NodePtr& root }
%lex-param { Scanner& scanner }

/* keywords */

/* identifiers */

%token  IDENT

/* whitespace */

%token  EOL

/* literals */

%token  DECIMAL_CONSTANT

/* delimiters and operators */

%token  LPAREN RPAREN
%token  ASTERISK MINUS PERCENT PLUS SLASH ASSIGN
%start  start

%%

start: calc
        { root = $1; }

calc: statement_list
        { $$ = FLATTEN(NODE(calc), $1, statement_list); }

statement_list : statement EOL
    | statement_list statement EOL
        { $$ = BINARY(statement_list, $1, $2); }
    ;

statement: expression
    | assignment
    ;


assignment: identifier ASSIGN exp
        { $$ = BINARY(ASSIGN, $1, $3); }
    ;

expression: exp
        { $$ = UNARY(expression, $1); }
    ;

exp: term
    | exp PLUS term
        { $$ = BINARY(PLUS, $1, $3); }
    | exp MINUS term
        { $$ = BINARY(MINUS, $1, $3); }
    ;

term: factor
    | term ASTERISK factor
        { $$ = BINARY(ASTERISK, $1, $3); }
    | term SLASH factor
        { $$ = BINARY(SLASH, $1, $3); }
    | term PERCENT factor
        { $$ = BINARY(PERCENT, $1, $3); }
    ;

factor: primary
    | unary_minus
    ;

unary_minus: MINUS primary
        { $$ = UNARY(unary_minus, $2); }
    ;

primary: integer
        { $$ = UNARY(integer, $1); }
    | identifier
    | LPAREN exp RPAREN
        { $$ = $2; }

identifier: IDENT
        { $$ = UNARY(identifier, $1); }
    ;

integer: DECIMAL_CONSTANT
        { $$ = $1; }
    ;

%%

using namespace AstlULMcalc;