Skip to content

Commit

Permalink
fix function_handle parenthese precedence
Browse files Browse the repository at this point in the history
  • Loading branch information
Nelson-numerical-software committed Nov 2, 2023
1 parent 96720e6 commit f4f76c1
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 47 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

- axis limits recalculate with `hggroup`.
- `axes` forces focus on current axe.
- function_handle parenthese precedence.

## 0.7.10 (2023-10-27)

Expand Down
4 changes: 2 additions & 2 deletions modules/function_handle/tests/test_function_anonymous.m
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
%=============================================================================
F = @(c) (integral(@(x) (x .^ 2 + c*x + 1),0,1));
R = func2str(F);
REF = '@(c)integral(@(x)x.^2+c*x+1,0,1)';
REF = '@(c)integral(@(x)(((x.^2)+(c*x))+1),0,1)';
assert_isequal(R, REF);
%=============================================================================
myfunction = @(x,y) (x^2 + y^2 + x*y);
Expand All @@ -101,6 +101,6 @@
%=============================================================================
F = @(x,y) ndgrid((-x:x/c:x),(-y:y/c:y));
R = func2str(F);
REF = '@(x,y)ndgrid(-x:x/c:x,-y:y/c:y)';
REF = '@(x,y)ndgrid(-x:(x/c):x,-y:(y/c):y)';
assert_isequal(R, REF);
%=============================================================================
3 changes: 2 additions & 1 deletion modules/function_handle/tests/test_str2func.m
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
str = '@(x)7*x-13';
fh = str2func(str);
R = func2str(fh);
assert_isequal(R, str)
REF = '@(x)(7*x)-13'
assert_isequal(R, REF)
assert_isequal(fh(3), 8)
%=============================================================================
str = '@(x)7*x-13+a';
Expand Down
4 changes: 2 additions & 2 deletions modules/hdf5/tests/test_savenh5_function_handle.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
%=============================================================================
A = 1;
B = 2;
C = @(x) x + A + B;
C = @(x) (x + A) + B;
%=============================================================================
savenh5(test_h5save_file, 'C');
R = h5readatt(test_h5save_file, '/C', 'NELSON_class');
Expand All @@ -27,7 +27,7 @@
R = h5read(test_h5save_file, '/C/is_function_handle');
assert_isequal(R, uint8(0));
R = h5read(test_h5save_file, '/C/function_handle');
assert_isequal(char(R), 'x+A+B');
assert_isequal(char(R), '(x+A)+B');
R = h5read(test_h5save_file, '/C/arguments/0');
assert_isequal(char(R), 'x');
%=============================================================================
Expand Down
145 changes: 103 additions & 42 deletions modules/interpreter/src/cpp/AbstractSyntaxTreeHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ static std::unordered_map<int, std::string> keywords = { { NLS_KEYWORD_BREAK, "b
{ NLS_KEYWORD_ENDFUNCTION, "endfunction" } };
//=============================================================================
static std::string
expression(AbstractSyntaxTreePtr expr)
expression(AbstractSyntaxTreePtr expr, bool firstLevel)
{
if (expr == nullptr) {
return "";
Expand All @@ -37,9 +37,9 @@ expression(AbstractSyntaxTreePtr expr)
switch (expr->type) {
case id_node: {
if (expr->down) {
res = expr->text + expression(expr->down);
res = expr->text + expression(expr->down, false);
} else {
res = expr->text + expression(expr->right);
res = expr->text + expression(expr->right, false);
}
} break;
case const_character_array_node: {
Expand Down Expand Up @@ -75,24 +75,25 @@ expression(AbstractSyntaxTreePtr expr)
switch (expr->opNum) {
case OP_COLON: {
if ((expr->down != nullptr) && (expr->down->opNum == (OP_COLON))) {
res = expression(expr->down->down) + ":" + expression(expr->down->down->right) + ":"
+ expression(expr->down->right);
res = expression(expr->down->down, false) + ":"
+ expression(expr->down->down->right, false) + ":"
+ expression(expr->down->right, false);
} else {
res = expression(expr->down) + ":" + expression(expr->down->right);
res = expression(expr->down, false) + ":" + expression(expr->down->right, false);
}
} break;
case OP_SEMICOLON: {
if (expr->right != nullptr) {
std::string left = expression(expr->down);
std::string right = expression(expr->right);
std::string left = expression(expr->down, false);
std::string right = expression(expr->right, false);
if (right.empty()) {
res = left;
} else {
res = left + ";" + right;
}
} else {
std::string left = expression(expr->down);
std::string right = expression(expr->down->right);
std::string left = expression(expr->down, false);
std::string right = expression(expr->down->right, false);
if (right.empty()) {
res = left;
} else {
Expand All @@ -107,16 +108,16 @@ expression(AbstractSyntaxTreePtr expr)
res = "{}";
} break;
case OP_BRACKETS: {
res = "[" + expression(expr->down) + "]";
res = "[" + expression(expr->down, false) + "]";
} break;
case OP_BRACES: {
res = "{" + expression(expr->down) + "}";
res = "{" + expression(expr->down, false) + "}";
} break;
case OP_PARENS: {
res = "(";
expr = expr->down;
while (expr != nullptr) {
res = res + expression(expr) + ",";
res = res + expression(expr, false) + ",";
expr = expr->right;
}
if (StringHelpers::ends_with(res, ",")) {
Expand All @@ -125,82 +126,142 @@ expression(AbstractSyntaxTreePtr expr)
res = res + ")";
} break;
case OP_PLUS: {
res = expression(expr->down) + "+" + expression(expr->down->right);
res = expression(expr->down, false) + "+" + expression(expr->down->right, false);
if (!firstLevel) {
res = "(" + res + ")";
}
} break;
case OP_SUBTRACT: {
res = expression(expr->down) + "-" + expression(expr->down->right);
res = expression(expr->down, false) + "-" + expression(expr->down->right, false);
if (!firstLevel) {
res = "(" + res + ")";
}
} break;
case OP_TIMES: {
res = expression(expr->down) + "*" + expression(expr->down->right);
res = expression(expr->down, false) + "*" + expression(expr->down->right, false);
if (!firstLevel) {
res = "(" + res + ")";
}
} break;
case OP_SOR: {
res = expression(expr->down) + "||" + expression(expr->down->right);
res = expression(expr->down, false) + "||" + expression(expr->down->right, false);
if (!firstLevel) {
res = "(" + res + ")";
}
} break;
case OP_OR: {
res = expression(expr->down) + "|" + expression(expr->down->right);
res = expression(expr->down, false) + "|" + expression(expr->down->right, false);
if (!firstLevel) {
res = "(" + res + ")";
}
} break;
case OP_SAND: {
res = expression(expr->down) + "&&" + expression(expr->down->right);
res = expression(expr->down, false) + "&&" + expression(expr->down->right, false);
if (!firstLevel) {
res = "(" + res + ")";
}
} break;
case OP_AND: {
res = expression(expr->down) + "&" + expression(expr->down->right);
res = expression(expr->down, false) + "&" + expression(expr->down->right, false);
if (!firstLevel) {
res = "(" + res + ")";
}
} break;
case OP_LT: {
res = expression(expr->down) + "<" + expression(expr->down->right);
res = expression(expr->down, false) + "<" + expression(expr->down->right, false);
if (!firstLevel) {
res = "(" + res + ")";
}
} break;
case OP_LEQ: {
res = expression(expr->down) + "<=" + expression(expr->down->right);
res = expression(expr->down, false) + "<=" + expression(expr->down->right, false);
if (!firstLevel) {
res = "(" + res + ")";
}
} break;
case OP_GT: {
res = expression(expr->down) + ">" + expression(expr->down->right);
res = expression(expr->down, false) + ">" + expression(expr->down->right, false);
if (!firstLevel) {
res = "(" + res + ")";
}
} break;
case OP_GEQ: {
res = expression(expr->down) + ">=" + expression(expr->down->right);
res = expression(expr->down, false) + ">=" + expression(expr->down->right, false);
if (!firstLevel) {
res = "(" + res + ")";
}
} break;
case OP_EQ: {
res = expression(expr->down) + "==" + expression(expr->down->right);
res = expression(expr->down, false) + "==" + expression(expr->down->right, false);
if (!firstLevel) {
res = "(" + res + ")";
}
} break;
case OP_NEQ: {
res = expression(expr->down) + "~=" + expression(expr->down->right);
res = expression(expr->down, false) + "~=" + expression(expr->down->right, false);
if (!firstLevel) {
res = "(" + res + ")";
}
} break;
case OP_DOT_TIMES: {
res = expression(expr->down) + ".*" + expression(expr->down->right);
res = expression(expr->down, false) + ".*" + expression(expr->down->right, false);
if (!firstLevel) {
res = "(" + res + ")";
}
} break;
case OP_UPLUS: {
res = "+" + expression(expr->down);
res = "+" + expression(expr->down, false);
} break;
case OP_UMINUS: {
res = "-" + expression(expr->down);
res = "-" + expression(expr->down, false);
} break;
case OP_NOT: {
res = "~" + expression(expr->down);
res = "~" + expression(expr->down, false);
} break;
case OP_TRANSPOSE: {
res = expression(expr->down) + "'";
res = expression(expr->down, false) + "'";
} break;
case OP_DOT_TRANSPOSE: {
res = expression(expr->down) + ".'";
res = expression(expr->down, false) + ".'";
} break;
case OP_RHS: {
res = expression(expr->down);
res = expression(expr->down, false);
} break;
case OP_RDIV: {
res = expression(expr->down) + "/" + expression(expr->down->right);
res = expression(expr->down, false) + "/" + expression(expr->down->right, false);
if (!firstLevel) {
res = "(" + res + ")";
}
} break;
case OP_LDIV: {
res = expression(expr->down) + "\\" + expression(expr->down->right);
res = expression(expr->down, false) + "\\" + expression(expr->down->right, false);
if (!firstLevel) {
res = "(" + res + ")";
}
} break;
case OP_DOT_RDIV: {
res = expression(expr->down) + "./" + expression(expr->down->right);
res = expression(expr->down, false) + "./" + expression(expr->down->right, false);
if (!firstLevel) {
res = "(" + res + ")";
}
} break;
case OP_DOT_LDIV: {
res = expression(expr->down) + ".\\" + expression(expr->down->right);
res = expression(expr->down, false) + ".\\" + expression(expr->down->right, false);
if (!firstLevel) {
res = "(" + res + ")";
}
} break;
case OP_POWER: {
res = expression(expr->down) + ".^" + expression(expr->down->right);
res = expression(expr->down, false) + ".^" + expression(expr->down->right, false);
if (!firstLevel) {
res = "(" + res + ")";
}
} break;
case OP_MPOWER: {
res = expression(expr->down) + "^" + expression(expr->down->right);
res = expression(expr->down, false) + "^" + expression(expr->down->right, false);
if (!firstLevel) {
res = "(" + res + ")";
}
} break;
case OP_FUNCTION_HANDLE_ANONYMOUS: {
res = "@(";
Expand All @@ -219,7 +280,7 @@ expression(AbstractSyntaxTreePtr expr)
}
res = res + ")";
}
res = res + expression(expr);
res = res + expression(expr, false);
} break;
case OP_FUNCTION_HANDLE_NAMED: {
res = res + "@";
Expand All @@ -235,8 +296,8 @@ expression(AbstractSyntaxTreePtr expr)
std::string
AbstractSyntaxTree::toString()
{
return expression(this);
return expression(this, true);
}
//=============================================================================
} // namespace Nelson
//=============================================================================
//=============================================================================

0 comments on commit f4f76c1

Please sign in to comment.