MacroBison.yy 5.34 KB
Newer Older
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
/*
 * Copyright (C) 2008 Dynare Team
 *
 * This file is part of Dynare.
 *
 * Dynare is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Dynare 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 */

%skeleton "lalr1.cc"
%require "2.3"
%defines

%{
using namespace std;

27
28
#include "MacroValue.hh"

29
30
31
32
33
34
35
36
37
38
39
40
41
42
class MacroDriver;
%}

%name-prefix="Macro"

%parse-param { MacroDriver &driver }
%parse-param { ostream &out }
%lex-param { MacroDriver &driver }

%locations
%initial-action
{
  // Initialize the location filenames
  @$.begin.filename = @$.end.filename = &driver.file;
43
44
  // Output first @#line statement
  out << "@#line \"" << driver.file << "\" 1" << endl;
45
46
47
48
49
50
51
52
53
};

%debug
%error-verbose

%union
{
  string *string_val;
  int int_val;
54
  const MacroValue *mv;
55
56
57
};

%{
58
#include <cstdlib>  // Pour atoi()
59
60
61
62
63
64
65
#include "MacroDriver.hh"

/* this "connects" the bison parser in the driver to the flex scanner class
 * object. it defines the yylex() function call to pull the next token from the
 * current lexer object of the driver context. */
#undef yylex
#define yylex driver.lexer->lex
66

67
#define TYPERR_CATCH(statement, loc) try        \
68
    {                                           \
69
      statement;                                \
70
71
72
73
74
75
    }                                           \
  catch(MacroValue::TypeError &e)               \
    {                                           \
      driver.error(loc, e.message);             \
    }

76
77
%}

sebastien's avatar
sebastien committed
78
%token DEFINE LINE FOR IN IF ELSE ENDIF ECHO_DIR ERROR
sebastien's avatar
sebastien committed
79
%token LPAREN RPAREN LBRACKET RBRACKET EQUAL EOL
80
81
82
83

%token <int_val> INTEGER
%token <string_val> NAME STRING

84
%left COMMA
85
86
87
%left LOGICAL_OR
%left LOGICAL_AND
%left LESS GREATER LESS_EQUAL GREATER_EQUAL EQUAL_EQUAL EXCLAMATION_EQUAL
88
%nonassoc IN
89
%nonassoc COLON
90
%left PLUS MINUS
91
%left TIMES DIVIDE
92
93
94
%left UMINUS UPLUS EXCLAMATION
%left LBRACKET

95
%type <mv> expr array_expr
96
97
98
99
%%

%start statement_list_or_nothing;

100
statement_list_or_nothing : /* empty */
101
102
                          | statement_list
                          ;
103
104

statement_list : statement EOL
105
106
               | statement_list statement EOL
               ;
107
108

statement : expr
sebastien's avatar
sebastien committed
109
            { out << $1->toString(); }
110
          | DEFINE NAME EQUAL expr
111
            { driver.set_variable(*$2, $4); delete $2; }
112
113
          | FOR NAME IN expr
            { TYPERR_CATCH(driver.init_loop(*$2, $4), @$); delete $2; }
sebastien's avatar
sebastien committed
114
115
116
117
118
119
          | IF expr
            { TYPERR_CATCH(driver.begin_if($2), @$); }
          | ECHO_DIR expr
            { TYPERR_CATCH(driver.echo(@$, $2), @$); }
          | ERROR expr
            { TYPERR_CATCH(driver.error(@$, $2), @$); }
sebastien's avatar
sebastien committed
120
          | LINE STRING INTEGER
121
            /* Ignore @#line declarations */
122
          ;
123
124

expr : INTEGER
125
       { $$ = new IntMV(driver, $1); }
126
     | STRING
127
       { $$ = new StringMV(driver, *$1); delete $1; }
128
     | NAME
129
130
       {
         try
131
132
133
134
135
136
137
           {
             $$ = driver.get_variable(*$1);
           }
         catch(MacroDriver::UnknownVariable(&e))
           {
             error(@$, "Unknown variable: " + e.name);
           }
138
139
         delete $1;
       }
140
141
142
     | LPAREN expr RPAREN
       { $$ = $2; }
     | expr PLUS expr
143
       { TYPERR_CATCH($$ = *$1 + *$3, @$); }
144
     | expr MINUS expr
145
       { TYPERR_CATCH($$ = *$1 - *$3, @$); }
146
     | expr TIMES expr
147
       { TYPERR_CATCH($$ = *$1 * *$3, @$); }
148
     | expr DIVIDE expr
149
       { TYPERR_CATCH($$ = *$1 / *$3, @$); }
150
     | expr LESS expr
151
       { TYPERR_CATCH($$ = *$1 < *$3, @$); }
152
     | expr GREATER expr
153
       { TYPERR_CATCH($$ = *$1 > *$3, @$); }
154
     | expr LESS_EQUAL expr
155
       { TYPERR_CATCH($$ = *$1 <= *$3, @$); }
156
     | expr GREATER_EQUAL expr
157
       { TYPERR_CATCH($$ = *$1 >= *$3, @$); }
158
     | expr EQUAL_EQUAL expr
159
       { TYPERR_CATCH($$ = *$1 == *$3, @$); }
160
     | expr EXCLAMATION_EQUAL expr
161
       { TYPERR_CATCH($$ = *$1 != *$3, @$); }
162
     | expr LOGICAL_OR expr
163
       { TYPERR_CATCH($$ = *$1 || *$3, @$); }
164
     | expr LOGICAL_AND expr
165
       { TYPERR_CATCH($$ = *$1 && *$3, @$); }
166
     | MINUS expr %prec UMINUS
167
       { TYPERR_CATCH($$ = -*$2, @$); }
168
     | PLUS expr %prec UPLUS
169
       { TYPERR_CATCH($$ = +(*$2), @$); }
170
     | EXCLAMATION expr
171
       { TYPERR_CATCH($$ = !*$2, @$); }
172
     | expr LBRACKET array_expr RBRACKET
173
174
       {
         TYPERR_CATCH($$ = (*$1)[*$3], @$)
175
176
177
178
         catch(MacroValue::OutOfBoundsError)
           {
             error(@$, "Index out of bounds");
           }
179
       }
180
181
     | LBRACKET array_expr RBRACKET
       { $$ = $2; }
sebastien's avatar
sebastien committed
182
     | expr COLON expr
183
       { TYPERR_CATCH($$ = IntMV::new_range(driver, $1, $3), @$); }
184
185
     | expr IN expr
       { TYPERR_CATCH($$ = $1->in($3), @$); }
186
     ;
187

188
array_expr : expr
189
             { $$ = $1->toArray(); }
190
           | array_expr COMMA expr
191
             { TYPERR_CATCH($$ = $3->append($1), @$); }
192
193
           ;

194
195
196
197
198
199
200
201
202
203
204
205
206
207
%%

void
Macro::parser::error(const Macro::parser::location_type &l,
                     const string &m)
{
  driver.error(l, m);
}

/*
  Local variables:
  mode: C++
  End:
*/