PropertyExpressionEngine is changed to derived from a new class PropertyExpressionContainer, which is in turn derives from PropertyXLinkContainer. This makes PropertyExpressionEngine a link type property that is capable of external linking. It now uses the unified link property APIs for dependency management and tracking of object life time, re-labeling, etc. ObjectIdentifier is modified to support sub-object reference, but is not exposed to end-user, because expression syntax is kept mostly unchanged, which will be submitted in future PR. There is, however, one small change in expression syntax (ExpressionParser.y) to introduce local property reference to avoid ambiguity mentioned in FreeCAD/FreeCAD#1619 Modified Expression/ExpressionModifier interface to support various link property API for link modification.
191 lines
14 KiB
Plaintext
191 lines
14 KiB
Plaintext
/* Parser for the FreeCAD Units language */
|
|
/* (c) 2010 Juergen Riegel LGPL */
|
|
/* (c) 2015 Eivind Kvedalen LGPL */
|
|
|
|
/* Represents the many different ways we can access our data */
|
|
|
|
%{
|
|
|
|
#define YYSTYPE App::ExpressionParser::semantic_type
|
|
|
|
std::stack<FunctionExpression::Function> functions; /**< Function identifier */
|
|
|
|
//#define YYSTYPE yystype
|
|
#define yyparse ExpressionParser_yyparse
|
|
#define yyerror ExpressionParser_yyerror
|
|
%}
|
|
|
|
/* Bison declarations. */
|
|
%token FUNC
|
|
%token ONE
|
|
%token NUM
|
|
%token IDENTIFIER
|
|
%token UNIT
|
|
%token INTEGER
|
|
%token CONSTANT
|
|
%token CELLADDRESS
|
|
%token EQ NEQ LT GT GTE LTE
|
|
%token STRING MINUSSIGN PROPERTY_REF
|
|
%token DOCUMENT OBJECT
|
|
%token EXPONENT
|
|
%type <arguments> args
|
|
%type <expr> input exp unit_exp cond
|
|
%type <quantity> UNIT
|
|
%type <string> STRING IDENTIFIER CELLADDRESS
|
|
%type <ivalue> INTEGER
|
|
%type <string> PROPERTY_REF
|
|
%type <fvalue> ONE
|
|
%type <fvalue> NUM
|
|
%type <constant> CONSTANT
|
|
%type <expr> num
|
|
%type <expr> range
|
|
%type <path> identifier
|
|
%type <components> path subpath
|
|
%type <func> FUNC
|
|
%type <string_or_identifier> document
|
|
%type <string_or_identifier> object
|
|
%type <ivalue> integer
|
|
%left ONE NUM INTEGER CONSTANT
|
|
%left EQ NEQ LT GT GTE LTE
|
|
%left '?' ':'
|
|
%left MINUSSIGN '+'
|
|
%left '*' '/'
|
|
%precedence NUM_AND_UNIT
|
|
%left '^' /* exponentiation */
|
|
%left EXPONENT
|
|
%left NEG /* negation--unary minus */
|
|
%left POS /* unary plus */
|
|
|
|
%destructor { delete $$; } exp cond unit_exp
|
|
%destructor { std::vector<Expression*>::const_iterator i = $$.begin(); while (i != $$.end()) { delete *i; ++i; } } args
|
|
|
|
%start input
|
|
|
|
%%
|
|
|
|
input: exp { ScanResult = $1; valueExpression = true; }
|
|
| unit_exp { ScanResult = $1; unitExpression = true; }
|
|
;
|
|
|
|
exp: num { $$ = $1; }
|
|
| num unit_exp %prec NUM_AND_UNIT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::UNIT, $2); }
|
|
| STRING { $$ = new StringExpression(DocumentObject, $1); }
|
|
| identifier { $$ = new VariableExpression(DocumentObject, $1); }
|
|
| MINUSSIGN exp %prec NEG { $$ = new OperatorExpression(DocumentObject, $2, OperatorExpression::NEG, new NumberExpression(DocumentObject, Quantity(-1))); }
|
|
| '+' exp %prec POS { $$ = new OperatorExpression(DocumentObject, $2, OperatorExpression::POS, new NumberExpression(DocumentObject, Quantity(1))); }
|
|
| exp '+' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::ADD, $3); }
|
|
| exp MINUSSIGN exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::SUB, $3); }
|
|
| exp '*' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MUL, $3); }
|
|
| exp '/' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); }
|
|
| exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); }
|
|
| exp '^' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, $3); }
|
|
| '(' exp ')' { $$ = $2; }
|
|
| FUNC args ')' { $$ = new FunctionExpression(DocumentObject, $1, $2); }
|
|
| cond '?' exp ':' exp { $$ = new ConditionalExpression(DocumentObject, $1, $3, $5); }
|
|
;
|
|
|
|
num: ONE { $$ = new NumberExpression(DocumentObject, Quantity($1)); }
|
|
| NUM { $$ = new NumberExpression(DocumentObject, Quantity($1)); }
|
|
| INTEGER { $$ = new NumberExpression(DocumentObject, Quantity((double)$1)); }
|
|
| CONSTANT { $$ = new ConstantExpression(DocumentObject, $1.name, Quantity($1.fvalue)); }
|
|
|
|
args: exp { $$.push_back($1); }
|
|
| range { $$.push_back($1); }
|
|
| args ',' exp { $1.push_back($3); $$ = $1; }
|
|
| args ';' exp { $1.push_back($3); $$ = $1; }
|
|
| args ',' range { $1.push_back($3); $$ = $1; }
|
|
| args ';' range { $1.push_back($3); $$ = $1; }
|
|
;
|
|
|
|
range: CELLADDRESS ':' CELLADDRESS { $$ = new RangeExpression(DocumentObject, $1, $3); }
|
|
| CELLADDRESS ':' IDENTIFIER { $$ = new RangeExpression(DocumentObject, $1, $3); }
|
|
| IDENTIFIER ':' CELLADDRESS { $$ = new RangeExpression(DocumentObject, $1, $3); }
|
|
| IDENTIFIER ':' IDENTIFIER { $$ = new RangeExpression(DocumentObject, $1, $3); }
|
|
;
|
|
|
|
cond: exp EQ exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::EQ, $3); }
|
|
| exp NEQ exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::NEQ, $3); }
|
|
| exp LT exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::LT, $3); }
|
|
| exp GT exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::GT, $3); }
|
|
| exp GTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::GTE, $3); }
|
|
| exp LTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::LTE, $3); }
|
|
;
|
|
|
|
unit_exp: UNIT { $$ = new UnitExpression(DocumentObject, $1.scaler, $1.unitStr ); }
|
|
| unit_exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); }
|
|
| unit_exp '*' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MUL, $3); }
|
|
| unit_exp '^' integer { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, new NumberExpression(DocumentObject, Quantity((double)$3))); }
|
|
| 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)))); }
|
|
| '(' unit_exp ')' { $$ = $2; }
|
|
;
|
|
|
|
identifier: path { /* Path to property within document object */
|
|
$$ = ObjectIdentifier(DocumentObject);
|
|
$$.addComponents($1);
|
|
$$.resolveAmbiguity();
|
|
}
|
|
| '.' path { /* Path to property of the current document object */
|
|
$$ = ObjectIdentifier(DocumentObject,true);
|
|
$$.setDocumentObjectName(DocumentObject);
|
|
$$.addComponents($2);
|
|
}
|
|
| object '.' path { /* Path to property within document object */
|
|
$$ = ObjectIdentifier(DocumentObject);
|
|
$1.checkImport(DocumentObject);
|
|
$$.addComponent(ObjectIdentifier::SimpleComponent($1));
|
|
$$.addComponents($3);
|
|
$$.resolveAmbiguity();
|
|
}
|
|
| document '#' path { /* Path to property from an external document, within a named document object */
|
|
$$ = ObjectIdentifier(DocumentObject);
|
|
$$.setDocumentName(std::move($1), true);
|
|
$$.addComponents($3);
|
|
$$.resolveAmbiguity();
|
|
}
|
|
| document '#' object '.' path { /* Path to property from an external document, within a named document object */
|
|
$$ = ObjectIdentifier(DocumentObject);
|
|
$$.setDocumentName(std::move($1), true);
|
|
$$.setDocumentObjectName(std::move($3), true);
|
|
$$.addComponents($5);
|
|
$$.resolveAmbiguity();
|
|
}
|
|
;
|
|
|
|
integer: INTEGER { $$ = $1; }
|
|
| ONE { $$ = $1; }
|
|
;
|
|
|
|
|
|
path: IDENTIFIER { $$.push_front(ObjectIdentifier::SimpleComponent($1)); }
|
|
| CELLADDRESS { $$.push_front(ObjectIdentifier::SimpleComponent($1)); }
|
|
| IDENTIFIER '[' integer ']' { $$.push_front(ObjectIdentifier::ArrayComponent($3)); $$.push_front(ObjectIdentifier::SimpleComponent($1); }
|
|
| IDENTIFIER '[' integer ']' '.' subpath { $6.push_front(ObjectIdentifier::ArrayComponent($3)); $$.push_front(ObjectIdentifier::SimpleComponent($1); $$ = $6; }
|
|
| IDENTIFIER '[' STRING ']' { $$.push_front(ObjectIdentifier::MapComponent(ObjectIdentifier::String($3, true))); }
|
|
| IDENTIFIER '[' IDENTIFIER ']' { $$.push_front(ObjectIdentifier::MapComponent($3)); $$.push_front(ObjectIdentifier::SimpleComponent($1); }
|
|
| IDENTIFIER '[' STRING ']' '.' subpath { $6.push_front(ObjectIdentifier::MapComponent(ObjectIdentifier::String($3, true))); $$.push_front(ObjectIdentifier::SimpleComponent($1); $$ = $6; }
|
|
| IDENTIFIER '[' IDENTIFIER ']' '.' subpath { $6.push_front(ObjectIdentifier::MapComponent($3)); $$.push_front(ObjectIdentifier::SimpleComponent($1); $$ = $6; }
|
|
| IDENTIFIER '.' subpath { $3.push_front(ObjectIdentifier::SimpleComponent($1)); $$ = $3; }
|
|
;
|
|
|
|
subpath: IDENTIFIER { $$.push_front(ObjectIdentifier::SimpleComponent($1)); }
|
|
| STRING { $$.push_front(ObjectIdentifier::SimpleComponent($1)); }
|
|
| CELLADDRESS { $$.push_front(ObjectIdentifier::SimpleComponent($1)); }
|
|
| IDENTIFIER '[' integer ']' { $$.push_front(ObjectIdentifier::ArrayComponent($3)); $$.push_front(ObjectIdentifier::SimpleComponent($1)); }
|
|
| IDENTIFIER '[' integer ']' '.' subpath { $6.push_front(ObjectIdentifier::ArrayComponent($3)); $$.push_front(ObjectIdentifier::SimpleComponent($1));$$ = $6; }
|
|
| IDENTIFIER '[' STRING ']' { $$.push_front(ObjectIdentifier::MapComponent(ObjectIdentifier::String($3, true))); $$.push_front(ObjectIdentifier::SimpleComponent($1)); }
|
|
| IDENTIFIER '[' IDENTIFIER ']' { $$.push_front(ObjectIdentifier::MapComponent($3)); $$.push_front(ObjectIdentifier::SimpleComponent($1)); }
|
|
| IDENTIFIER '[' STRING ']' '.' subpath { $6.push_front(ObjectIdentifier::MapComponent(ObjectIdentifier::String($3, true))); $$.push_front(ObjectIdentifier::SimpleComponent($1));$$ = $6; }
|
|
| IDENTIFIER '[' IDENTIFIER ']' '.' subpath { $6.push_front(ObjectIdentifier::MapComponent($3)); $$.push_front(ObjectIdentifier::SimpleComponent($1));$$ = $6; }
|
|
| IDENTIFIER '.' subpath { $3.push_front(ObjectIdentifier::SimpleComponent($1)); $$ = $3; }
|
|
;
|
|
|
|
document: STRING { $$ = ObjectIdentifier::String($1, true); }
|
|
| IDENTIFIER { $$ = ObjectIdentifier::String($1); }
|
|
;
|
|
|
|
object: STRING { $$ = ObjectIdentifier::String($1, true); }
|
|
| CELLADDRESS { $$ = ObjectIdentifier::String($1, true); }
|
|
;
|
|
|
|
%%
|