1
/***************************************************************************
2
* Copyright (c) 2010 Jürgen Riegel <FreeCAD@juergen-riegel.net> *
3
* Copyright (c) 2015 Eivind Kvedalen <eivind@kvedalen.name> *
5
* This file is part of the FreeCAD CAx development system. *
7
* This library is free software; you can redistribute it and/or *
8
* modify it under the terms of the GNU Library General Public *
9
* License as published by the Free Software Foundation; either *
10
* version 2 of the License, or (at your option) any later version. *
12
* This library is distributed in the hope that it will be useful, *
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15
* GNU Library General Public License for more details. *
17
* You should have received a copy of the GNU Library General Public *
18
* License along with this library; see the file COPYING.LIB. If not, *
19
* write to the Free Software Foundation, Inc., 59 Temple Place, *
20
* Suite 330, Boston, MA 02111-1307, USA *
22
***************************************************************************/
24
/* Parser for the FreeCAD Units language */
25
/* Represents the many different ways we can access our data */
30
#define YYSTYPE App::ExpressionParser::semantic_type
32
std::stack<FunctionExpression::Function> functions; /**< Function identifier */
34
//#define YYSTYPE yystype
35
#define yyparse ExpressionParser_yyparse
36
#define yyerror ExpressionParser_yyerror
47
%token EQ NEQ LT GT GTE LTE
48
%token STRING MINUSSIGN PROPERTY_REF
49
%token DOCUMENT OBJECT
51
%type <arguments> args
52
%type <expr> input unit_num us_building_unit other_unit exp unit_exp cond indexable
53
%type <quantity> UNIT USUNIT
54
%type <string> id_or_cell STRING IDENTIFIER CELLADDRESS
55
%type <ivalue> INTEGER
56
%type <string> PROPERTY_REF
59
%type <constant> CONSTANT
62
%type <path> identifier iden
63
%type <component> indexer
65
%type <string_or_identifier> document
66
%type <string_or_identifier> object
67
%type <ivalue> integer
68
%precedence EQ NEQ LT GT GTE LTE
72
%precedence NUM_AND_UNIT
77
%destructor { delete $$; } num range exp cond unit_exp indexable
78
%destructor { delete $$; } <component>
79
%destructor { std::vector<Expression*>::const_iterator i = $$.begin(); while (i != $$.end()) { delete *i; ++i; } } args
85
input: exp { ScanResult = $1; valueExpression = true; }
86
| unit_exp { ScanResult = $1; unitExpression = true; }
89
unit_num: num unit_exp %prec NUM_AND_UNIT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::UNIT, $2); }
90
| num us_building_unit num us_building_unit %prec NUM_AND_UNIT { $$ = new OperatorExpression(DocumentObject, new OperatorExpression(DocumentObject, $1, OperatorExpression::UNIT, $2), OperatorExpression::ADD, new OperatorExpression(DocumentObject, $3, OperatorExpression::UNIT, $4));}
94
| unit_num { $$ = $1; }
95
| STRING { $$ = new StringExpression(DocumentObject, $1); }
96
| identifier { $$ = new VariableExpression(DocumentObject, $1); }
97
| MINUSSIGN exp %prec NEG { $$ = new OperatorExpression(DocumentObject, $2, OperatorExpression::NEG, new NumberExpression(DocumentObject, Quantity(-1))); }
98
| '+' exp %prec POS { $$ = new OperatorExpression(DocumentObject, $2, OperatorExpression::POS, new NumberExpression(DocumentObject, Quantity(1))); }
99
| exp '+' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::ADD, $3); }
100
| exp MINUSSIGN exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::SUB, $3); }
101
| exp '*' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MUL, $3); }
102
| exp '/' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); }
103
| exp '%' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MOD, $3); }
104
| exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); }
105
| exp '^' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, $3); }
106
| indexable { $$ = $1; }
107
| FUNC args ')' { $$ = new FunctionExpression(DocumentObject, $1.first, std::move($1.second), $2);}
108
| cond '?' exp ':' exp { $$ = new ConditionalExpression(DocumentObject, $1, $3, $5); }
109
| '(' exp ')' { $$ = $2; }
112
num: ONE { $$ = new NumberExpression(DocumentObject, Quantity($1)); }
113
| NUM { $$ = new NumberExpression(DocumentObject, Quantity($1)); }
114
| INTEGER { $$ = new NumberExpression(DocumentObject, Quantity((double)$1)); }
115
| CONSTANT { $$ = new ConstantExpression(DocumentObject, $1.name, Quantity($1.fvalue)); }
117
args: exp { $$.push_back($1); }
118
| range { $$.push_back($1); }
119
| args ',' exp { $1.push_back($3); $$ = $1; }
120
| args ';' exp { $1.push_back($3); $$ = $1; }
121
| args ',' range { $1.push_back($3); $$ = $1; }
122
| args ';' range { $1.push_back($3); $$ = $1; }
125
range: id_or_cell ':' id_or_cell { $$ = new RangeExpression(DocumentObject, $1, $3); }
128
cond: exp EQ exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::EQ, $3); }
129
| exp NEQ exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::NEQ, $3); }
130
| exp LT exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::LT, $3); }
131
| exp GT exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::GT, $3); }
132
| exp GTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::GTE, $3); }
133
| exp LTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::LTE, $3); }
134
| '(' cond ')' { $$ = $2; }
137
us_building_unit: USUNIT { $$ = new UnitExpression(DocumentObject, $1.scaler, $1.unitStr ); }
138
other_unit: UNIT { $$ = new UnitExpression(DocumentObject, $1.scaler, $1.unitStr ); }
140
unit_exp: other_unit { $$ = $1; }
141
| us_building_unit { $$ = $1; }
142
| unit_exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); }
143
| unit_exp '*' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MUL, $3); }
144
| unit_exp '^' integer { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, new NumberExpression(DocumentObject, Quantity((double)$3))); }
145
| unit_exp '^' MINUSSIGN integer { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, new OperatorExpression(DocumentObject, new NumberExpression(DocumentObject, Quantity((double)$4)), OperatorExpression::NEG, new NumberExpression(DocumentObject, Quantity(-1)))); }
146
| '(' unit_exp ')' { $$ = $2; }
149
integer: INTEGER { $$ = $1; }
154
: IDENTIFIER { $$ = std::move($1); }
155
| CELLADDRESS { $$ = std::move($1); }
159
: id_or_cell { $$ = ObjectIdentifier(DocumentObject); $$ << ObjectIdentifier::SimpleComponent($1); }
160
| iden { $$ = std::move($1); }
164
: '.' STRING '.' id_or_cell { /* Path to property of a sub-object of the current object*/
165
$$ = ObjectIdentifier(DocumentObject,true);
166
$$.setDocumentObjectName(DocumentObject,false,ObjectIdentifier::String(std::move($2),true),true);
167
$$.addComponent(ObjectIdentifier::SimpleComponent($4));
169
| '.' id_or_cell { /* Path to property of the current document object */
170
$$ = ObjectIdentifier(DocumentObject,true);
171
$$.setDocumentObjectName(DocumentObject);
172
$$.addComponent(ObjectIdentifier::SimpleComponent($2));
174
| object '.' STRING '.' id_or_cell { /* Path to property of a sub-object */
175
$$ = ObjectIdentifier(DocumentObject);
176
$$.setDocumentObjectName(std::move($1), true, ObjectIdentifier::String(std::move($3),true),true);
177
$$.addComponent(ObjectIdentifier::SimpleComponent($5));
178
$$.resolveAmbiguity();
180
| object '.' id_or_cell { /* Path to property of a given document object */
181
$$ = ObjectIdentifier(DocumentObject);
182
$1.checkImport(DocumentObject);
183
$$.addComponent(ObjectIdentifier::SimpleComponent($1));
184
$$.addComponent(ObjectIdentifier::SimpleComponent($3));
185
$$.resolveAmbiguity();
187
| document '#' object '.' id_or_cell { /* Path to property from an external document, within a named document object */
188
$$ = ObjectIdentifier(DocumentObject);
189
$$.setDocumentName(std::move($1), true);
190
$$.setDocumentObjectName(std::move($3), true);
191
$$.addComponent(ObjectIdentifier::SimpleComponent($5));
192
$$.resolveAmbiguity();
194
| document '#' object '.' STRING '.' id_or_cell
195
{ $$ = ObjectIdentifier(DocumentObject);
196
$$.setDocumentName(std::move($1), true);
197
$$.setDocumentObjectName(std::move($3), true, ObjectIdentifier::String(std::move($5),true));
198
$$.addComponent(ObjectIdentifier::SimpleComponent($7));
199
$$.resolveAmbiguity();
201
| iden '.' IDENTIFIER { $$= std::move($1); $$.addComponent(ObjectIdentifier::SimpleComponent($3)); }
205
: '[' exp ']' { $$ = Expression::createComponent($2); }
206
| '[' exp ':' ']' { $$ = Expression::createComponent($2,0,0,true); }
207
| '[' ':' exp ']' { $$ = Expression::createComponent(0,$3); }
208
| '[' ':' ':' exp ']' { $$ = Expression::createComponent(0,0,$4); }
209
| '[' exp ':' exp ']' { $$ = Expression::createComponent($2,$4);}
210
| '[' exp ':' ':' exp ']' { $$ = Expression::createComponent($2,0,$5); }
211
| '[' ':' exp ':' exp ']' { $$ = Expression::createComponent(0,$3,$5); }
212
| '[' exp ':' exp ':' exp ']' { $$ = Expression::createComponent($2,$4,$6);}
216
: identifier indexer { $$ = new VariableExpression(DocumentObject,$1); $$->addComponent($2); }
217
| indexable indexer { $1->addComponent(std::move($2)); $$ = $1; }
218
| indexable '.' IDENTIFIER { $1->addComponent(Expression::createComponent($3)); $$ = $1; }
222
: STRING { $$ = ObjectIdentifier::String(std::move($1), true); }
223
| IDENTIFIER { $$ = ObjectIdentifier::String(std::move($1), false, true);}
227
: STRING { $$ = ObjectIdentifier::String(std::move($1), true); }
228
| id_or_cell { $$ = ObjectIdentifier::String(std::move($1), false);}