| Scilab Bag Of Tricks: The Scilab-2.5 IAQ (Infrequently Asked Questions) | ||
|---|---|---|
| Prev | Chapter 9. Longer Examples | Next |
assoc.sci, prec.sci, and parser.sci are the scripts that determine the precedence and the associativity of the arithmetic Scilab operators. The results are used in the section called Operator Precedence And Associativity in Chapter 4.
function a = assoc(oper, typ)
// Return the associativity a of
// operator oper which accepts type typ.
// oper can be a matrix of operators.
//
// typ can be 'n' for numeric, or 'b' for boolean.
// If typ is omitted, numeric is assumed.
[nl, nr] = argn()
if nr == 1 then
typ = 'n'
end
select typ
case 'n' then
args = string([1.1 1.2 1.5])
deff('b = equal(x, y)', 'b = abs(x - y) < 1.2*%eps')
case 'b' then
args = string(['%f' '%t' '%f'])
deff('b = equal(x, y)', 'b = x == y')
else
error('unknown type ' + typ)
end
a = []
for op = oper
expr = '[' + args(1) + op
+ args(2) + op + args(3) + ',' ..
+ '(' + args(1) + op + args(2) + ')'
+ op + args(3) + ',' ..
+ args(1) + op + '(' + args(2)
+ op + args(3) + ')]'
//disp(expr)
r = evstr(expr)
//disp(r)
if equal(r(2), r(3)) then
a = [a 'non']
elseif equal(r(1), r(2)) then
a = [a 'left']
elseif equal(r(1), r(3)) then
a = [a 'right']
else
error('could not determine associativity')
end
endfunction p = prec(op1, op2)
// determine the relative precedence of operator op1 vs op2
// If operator op1 has a higher precedence than op2 then p = -1.
// In the opposite case p = 1. If both have the same precedence
// level p = 0
args = string([1.1 1.2 1.5])
deff('b = equal(x, y)', 'b = abs(x - y) < 1.2*%eps')
expr = '[' + args(1) + op1 + args(2) + op2 + args(3) + ',' ..
+ '(' + args(1) + op1 + args(2) + ')' + op2 + args(3) + ',' ..
+ args(1) + op1 + '(' + args(2) + op2 + args(3) + ')]'
//disp(expr)
r = evstr(expr)
//disp(r)
if equal(r(2), r(3)) then
p = 0
elseif equal(r(1), r(2)) then
p = -1
elseif equal(r(1), r(3)) then
p = 1
else
error('could not determine precedence level')
endfunction p = prec1(uop, op)
// determine what relative precedence the unary operator uop has
// with respect to operator op. The return values are like those
// of prec()
args = string([1.1 1.2])
//args = string([(1.1+0.9*%i) (1.2-0.8*%i)])
deff('b = equal(x, y)', 'b = abs(x - y) < 1.2*%eps')
expr = '[' + uop + args(1) + op + args(2) + ',' ..
+ '(' + uop + args(1) + ')' + op + args(2) + ']'
//disp(expr)
r = evstr(expr)
//disp(r)
if equal(r(1), r(2)) then
p = -1
else
p = 1
endfunction p = lprec(op1, op2)
// determine relative precedence of the
// logical operators op1 and op2
v = ['%f' '%t']
for i = 1:2
for j = 1:2
for k = 1:2
args = string([v(i) v(j) v(k)])
expr = '[' + args(1) + op1 + args(2) + op2 + args(3) + ',' ..
+ '(' + args(1) + op1 + args(2) + ')' + op2 + args(3) + ',' ..
+ args(1) + op1 + '(' + args(2) + op2 + args(3) + ')]'
//disp(expr)
r = evstr(expr)
//disp(r)
if r(2) == r(3) then
p = 0
elseif r(1) == r(2) then
p = -1
return
elseif r(1) == r(3) then
p = 1
return
else
error('could not determine precedence level')
end
end
end
end// determine properties of Scilab's parser:
// associativity and precedence level of operators
getf('assoc.sci');
getf('prec.sci');
numop1 = ['+' '-'];
numop2 = ['+' '-' '*' '/' '\' '^' '.*' './' '.\' '.^'];
logop1 = ['~'];
logop2 = ['&' '|'];
// inquire associativity
an = assoc(numop2, 'n');
ab = assoc(logop2, 'b');
// figure out the relative precedence of binary numeric operators
pm2 = [];
for i = numop2
row = [];
for j = numop2
row = [row prec(i, j)];
end
pm2 = [pm2; row];
end
[lev, idx] = sort( sum(pm2, 'r') );
lev = lev - min(lev) + 1; // minimum := 1
nop2 = numop2;
for op = numop1 // mark binary oparators that have a unary twin
patch = find(op == nop2);
nop2(patch) = op + '/2';
end
relp2 = [string(lev); nop2(idx); an(idx)]';
relp1 = [];
for i = numop1
row = [];
for j = numop2
row = [row, prec1(i, j)];
end
hop = numop2(find(row > 0.5)); // operators with higher precedence
minhop = 0;
for op = hop
minhop = max( minhop, find(relp2(:, 2) == op) );
end
// now minhop is the index of the lowest precedence binary operator
// that has a higher precedence than the unary operator i, or 0 if
// there is none
if minhop == 0
uop = evstr(relp2(1, 1)) + 1;
else
uop = evstr(relp2(minhop, 1)) - 1;
end
relp1 = [relp1; [string(uop), i+'/1', 'right']];
end
//relp1
// Merge unary operators into matrix of binary operators
relp = [relp1; relp2];
[dummy, idx] = sort(evstr(relp(:, 1)));
relp(idx, :)