Afficher la pageAnciennes révisionsLiens de retourHaut de page Cette page est en lecture seule. Vous pouvez afficher le texte source, mais ne pourrez pas le modifier. Contactez votre administrateur si vous pensez qu'il s'agit d'une erreur. ===== Calculatrice ===== Travaille en RPN : empiler les nombres et effectuer les opérations.\\ **/!\** nécessite les module ''lex'' ''random'' ''conv''\\ Téléchargement du {{https://lanisys.fr/wp/calc.wp|binaire wp}} (clic-droit et //Enregistrer le lien sous...//)\\ <code wlang calc.w> ; Calculatrice RPN begin sub displayStack(stack) declare size, one, minusOne, elem let size = dcount(stack) if size = 0 then echonl "<empty stack>" return endif let one = 1 let minusOne = neg(one) foreach elem in size, one, minusOne echonl format(elem, @right, '0', 2):'> ':format(stack{elem}, @right, ' ', 20) endfor except endsub ; declare rules, crules, Rule ; lex rules and compiled rules, Rule (pour echapper # 2 fois => #23#32#33) let crules = '' let rules = 'integer: int ' let rules{2} = 'fractionnal: frac ' let rules{3} = 'absolute: abs ' let rules{4} = 'negation: neg ' let rules{5} = 'round0: round0 ' let rules{6} = 'round1: round1 ' let rules{7} = 'round2: round2 ' let rules{8} = 'round3: round3 ' let rules{9} = 'round4: round4 ' let rules{10} = 'random: rnd ; random ' let rules{11} = 'varsys: @ (1,*,a-z) ' let rules{12} = 'number: (0,1,#23#32#332D) (1,13,0-9) . (0,5,0-9) ' ; corriger le double 'escape' car - est un car reserve lex (- => #2D => #23#32#33#23#33#32#23#34#34) car sinon compil/assembleur decode mal le - let rules{13} = 'integernumber: (0,1,#23#32#332D) (1,13,0-9) ' let rules{14} = 'minus: (1,1,#23#32#332D) ; - ' let rules{15} = 'plus: (1,1,#2B) ; + ' let rules{16} = 'multiply: (1,1,#2A) ; * ' let rules{17} = 'divide: (1,1,#2F) ; / ' let rules{18} = 'integerdivide: (1,1,#5C) ; \ ' let rules{19} = 'modulus: (1,1,#25) ; % ' let rules{20} = 'quit: quit ' let rules{21} = 'dup: dup ' let rules{22} = 'pop: pop ' let rules{23} = 'clear: clear ' let rules{24} = 'space: (1,1,#23#32#3320) ' let rules{25} = 'squareroot: sqrt ' let rules{26} = 'exponent: exp ' let rules{27} = 'other: (1,1,#23#32#3300-#23#32#33FF)' let rules = change(rules, @fm, @lf) part 1 let Rule = {} invoke lex&compile(rules, crules, Rule) part 2 ; todo mettre la sub qui suit dans le module lex (? pbm il faut 4/5 params) declare tok let tok = {} sub getToken(tokenList, tokenIndex, tokenNumber, value) let tokenNumber = tokenList{2, tokenIndex} if tokenNumber # '' then declare hexa let hexa = '' let hexa = tokenList{1, tokenIndex} invoke conv&fromHexa(hexa, value) endif ; si besoin invoke lex&getToken(tokenList, tokenIndex, tok) except endsub ; echonl "wcalc => + - * / \ % int frac abs neg sqrt exp rnd round0 round1 round2 round3 round4 @pi pop dup clear quit" ; declare value, stack, token, ind, ruleNumber, ruleValue let value = '' let token = '' let stack = '' loop do displayStack(stack) echo 'wcalc: ' let value = '' input value invoke lex&analyze(crules, value, token) ; ----------------------------------------------- ; token{1/2/3} en MV : chaine hexa, no token, ordinal_position let ind = 0 let ruleValue = '' let ruleNumber = 0 loop let ind = ind + 1 do getToken(token, ind, ruleNumber, ruleValue) breakon ruleNumber = '' continueon ruleNumber = Rule.space ; if ruleNumber = Rule.other then echonl 'Syntax error' break; ; ----------------------------------------------- elseif ruleNumber = Rule.dup then if dcount(stack) < 1 then echonl "Stack underflow error" else let stack = insert(stack, stack{1}, 1) endif ; ----------------------------------------------- elseif ruleNumber = Rule.pop then if dcount(stack) < 1 then echonl "Stack underflow error" else let stack = remove(stack, 1) endif ; ----------------------------------------------- elseif ruleNumber = Rule.clear then let stack = '' ; ----------------------------------------------- elseif ruleNumber = Rule.number or ruleNumber = Rule.integernumber then if dcount(stack) > 15 then echonl "Stack full error" else let stack = insert(stack, ruleValue, 1) endif ; ----------------------------------------------- elseif ruleNumber = Rule.random then if dcount(stack) > 15 then echonl "Stack full error" else declare rnd let rnd = 0 invoke random&get(rnd) let stack = insert(stack, rnd, 1) endif ; ----------------------------------------------- elseif ruleNumber = Rule.varsys then if dcount(stack) > 15 then echonl "Stack full error" else if ruleValue = '@pi' then let stack = insert(stack, @pi, 1) else echonl "Unknown constant" endif endif ; ----------------------------------------------- elseif ruleNumber = Rule.plus then if dcount(stack) < 2 then echonl "Stack underflow error" else let stack{2} = stack{2} + stack{1} let stack = remove(stack, 1) endif ; ----------------------------------------------- elseif ruleNumber = Rule.minus then if dcount(stack) < 2 then echonl "Stack underflow error" else let stack{2} = stack{2} - stack{1} let stack = remove(stack, 1) endif ; ----------------------------------------------- elseif ruleNumber = Rule.divide then if dcount(stack) < 2 then echonl "Stack underflow error" elseif stack{1} = 0 then echonl "Division by zero error" else let stack{2} = stack{2} / stack{1} let stack = remove(stack, 1) endif ; ----------------------------------------------- elseif ruleNumber = Rule.integerdivide then if dcount(stack) < 2 then echonl "Stack underflow error" elseif stack{1} = 0 then echonl "Division by zero error" else let stack{2} = stack{2} \ stack{1} let stack = remove(stack, 1) endif ; ----------------------------------------------- elseif ruleNumber = Rule.modulus then if dcount(stack) < 2 then echonl "Stack underflow error" elseif stack{1} = 0 then echonl "Division by zero error" else let stack{2} = stack{2} % stack{1} let stack = remove(stack, 1) endif ; ----------------------------------------------- elseif ruleNumber = Rule.multiply then if dcount(stack) < 2 then echonl "Stack underflow error" else let stack{2} = stack{2} * stack{1} let stack = remove(stack, 1) endif ; ----------------------------------------------- elseif ruleNumber = Rule.exponent then if dcount(stack) < 2 then echonl "Stack underflow error" else let stack{2} = exp(stack{2}, stack{1}) let stack = remove(stack, 1) endif ; ----------------------------------------------- elseif ruleNumber = Rule.squareroot then if dcount(stack) < 1 then echonl "Stack underflow error" else let stack{1} = sqrt(stack{1}) endif ; ----------------------------------------------- elseif ruleNumber = Rule.negation then if dcount(stack) < 1 then echonl "Stack underflow error" else let stack{1} = neg(stack{1}) endif ; ----------------------------------------------- elseif ruleNumber = Rule.integer then if dcount(stack) < 1 then echonl "Stack underflow error" else let stack{1} = int(stack{1}) endif ; ----------------------------------------------- elseif ruleNumber = Rule.fractionnal then if dcount(stack) < 1 then echonl "Stack underflow error" else let stack{1} = frac(stack{1}) endif ; ----------------------------------------------- elseif ruleNumber = Rule.absolute then if dcount(stack) < 1 then echonl "Stack underflow error" else let stack{1} = abs(stack{1}) endif ; ----------------------------------------------- elseif ruleNumber = Rule.round0 then if dcount(stack) < 1 then echonl "Stack underflow error" else let stack{1} = round(stack{1}, 0) endif ; ----------------------------------------------- elseif ruleNumber = Rule.round1 then if dcount(stack) < 1 then echonl "Stack underflow error" else let stack{1} = round(stack{1}, 1) endif ; ----------------------------------------------- elseif ruleNumber = Rule.round2 then if dcount(stack) < 1 then echonl "Stack underflow error" else let stack{1} = round(stack{1}, 2) endif ; ----------------------------------------------- elseif ruleNumber = Rule.round3 then if dcount(stack) < 1 then echonl "Stack underflow error" else let stack{1} = round(stack{1}, 3) endif ; ----------------------------------------------- elseif ruleNumber = Rule.round4 then if dcount(stack) < 1 then echonl "Stack underflow error" else let stack{1} = round(stack{1}, 4) endif endif ; ----------------------------------------------- breakon ruleNumber = Rule.quit endloop breakon ruleNumber = Rule.quit endloop echonl "Bye :)" except echonl "Exception line ":@exceptline if @part = 1 then declare err let err = 0 invoke lex&error(err) echonl "lex error : ":err endif end </code> sample/calc.txt Dernière modification : 2026/04/03 19:51de root