Scilab Bag Of Tricks: The Scilab-2.5.x IAQ (Infrequently Asked Questions) | ||
---|---|---|
Prev | Chapter 10. Complete 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 Section 4.3.
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 end
function 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') end
function 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 end
function 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, :)