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 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, :)