Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Expression evaluator
#31
Well, I fixed things here and there and added support for parentheses. It wasn't that hard. I had problems with the part I had already coded 'cause it read the expressions from left to right... (silly me: recursion works upside down when it is NOT FINAL!!). I've written my own INSTR string which searches from END to BEGINNING.

Parentheses processing takes 22 lines Sad

Code:
DECLARE FUNCTION instrRev% (st1$, st2$)
DECLARE FUNCTION eval% (cmd$)
CLS
PRINT eval%("3+(-3*4+(3-4*(4+3)))")
PRINT
PRINT 3 + (-3 * 4 + (3 - 4 * (4 + 3)))

FUNCTION eval% (cmd$)
   ' Preprocess parentheses **********************************************
   Init% = 1
   DO
      a% = INSTR(Init%, cmd$, "(")
      IF a% <> 0 THEN
         Init% = a% + 1: np% = 1: Ps% = Init%: Res$ = ""
         DO
            IF Ps% > LEN(cmd$) THEN ' Unbalanced Parentheses!
               Res$ = "0": Ps% = Init% + 1
               EXIT DO
            END IF
            m$ = MID$(cmd$, Ps%, 1)
            IF m$ = ")" AND np% = 1 THEN EXIT DO
            Res$ = Res$ + m$
            Ps% = Ps% + 1
            IF m$ = "(" THEN np% = np% + 1
            IF m$ = ")" THEN np% = np% - 1
         LOOP
         r% = eval%(Res$)
         cmd$ = LEFT$(cmd$, Init% - 2) + STR$(r%) + RIGHT$(cmd$, LEN(cmd$) - Ps%)
      END IF
   LOOP WHILE a% <> 0
   ' *********************************************************************
  
   cmd$ = LTRIM$(RTRIM$(cmd$))

   a% = instrRev%(cmd$, "+")
   b% = instrRev%(cmd$, "-")

   IF a% = 0 AND b% = 0 THEN
      a% = instrRev%(cmd$, "*")
      b% = instrRev%(cmd$, "/")
      IF a% = 0 AND b% = 0 THEN
         Res% = VAL(cmd$)
      ELSE
         IF a% > b% THEN
            Res% = eval%(LEFT$(cmd$, a% - 1)) * eval%(RIGHT$(cmd$, LEN(cmd$) - a%))
         ELSE
            Res% = eval%(LEFT$(cmd$, b% - 1)) / eval%(RIGHT$(cmd$, LEN(cmd$) - b%))
         END IF
      END IF
   ELSE
      ' Detect Unary "-" and remove:
      IF b% > 1 THEN
         lp$ = RTRIM$(LEFT$(cmd$, b% - 1))
         IF RIGHT$(lp$, 1) <= "0" OR RIGHT$(lp$, 1) >= "9" THEN b% = 0
      END IF
      IF a% > b% THEN
         Res% = eval%(LEFT$(cmd$, a% - 1)) + eval%(RIGHT$(cmd$, LEN(cmd$) - a%))
      ELSE
         Res% = eval%(LEFT$(cmd$, b% - 1)) - eval%(RIGHT$(cmd$, LEN(cmd$) - b%))
      END IF
   END IF
   eval% = Res%
END FUNCTION

FUNCTION instrRev% (st1$, st2$)
   Res% = 0
   FOR i% = LEN(st1$) TO 1 STEP -1
      IF MID$(st1$, i%, 1) = st2$ THEN Res% = i%: EXIT FOR
   NEXT i%
   instrRev% = Res%
END FUNCTION
SCUMM (the band) on Myspace!
ComputerEmuzone Games Studio
underBASIC, homegrown musicians
[img]http://www.ojodepez-fanzine.net/almacen/yoghourtslover.png[/i
Reply
#32
in qb code, this is what one gets:

Code:
DECLARE FUNCTION reduce.string$ (string1$)
DEFINT A-Z
CLS
PRINT reduce.string$("5 + 5 * 13")

FUNCTION reduce.string$ (string1$)

string1$ = "(" + string1$ + ")"
DO
read.loc = 1
start.p = 0
op$ = ""
string2$ = ""
string3$ = ""
op.exists = 0
num1$ = ""
num2$ = ""
num3$ = ""
st$ = ""
i = 0
j = 0
string1a$ = ""
string1b$ = ""

'get the location of the innermost parentheses

DO
start.p = INSTR(read.loc, string1$, "(")
IF start.p = 0 THEN EXIT DO
read.loc = start.p + 1
LOOP

'find the end of the parentheses-enclosed statement.
end.loc = INSTR(read.loc, string1$, ")")

'removing the innermost ( ), save everything before as string2, everything after as string3, and extract the parentheses-enclosed statement as string1.

string2$ = MID$(string1$, 1, read.loc - 2)
IF LEN(string1$) - end.loc > 0 THEN string3$ = MID$(string1$, 1 + end.loc, LEN(string1$) - end.loc) ELSE string3$ = ""
string1$ = MID$(string1$, read.loc, end.loc - read.loc)

'find an operand, starting from the left and going in the order: /, *, -, +
DO
op.exists = INSTR(string1$, "/ "): IF op.exists THEN op$ = "/": GOTO ex1
op.exists = INSTR(string1$, "* "): IF op.exists THEN op$ = "*": GOTO ex1
op.exists = INSTR(string1$, "- "): IF op.exists THEN op$ = "-": GOTO ex1
op.exists = INSTR(string1$, "+ "): IF op.exists THEN op$ = "+" ELSE EXIT DO
ex1:
'operate on the two numbers left and right of the operand.
'PRINT string2$ + "(" + string1$ + ")" + string3$
num1$ = "": num2$ = ""
i = op.exists - 2
DO
st$ = MID$(string1$, i, 1)
IF INSTR("-0123456789/", st$) <> 0 THEN
num2$ = st$ + num2$
ELSE
EXIT DO
END IF
i = i - 1
IF i = 0 THEN EXIT DO
LOOP

j = i: i = op.exists + 2
DO
st$ = MID$(string1$, i, 1)
IF INSTR("-0123456789/", st$) <> 0 THEN
num1$ = num1$ + st$
ELSE
i = i - 1
EXIT DO
END IF
IF i = LEN(string1$) THEN EXIT DO
i = i + 1
LOOP

SELECT CASE op$
CASE "+": num3$ = LTRIM$(STR$(VAL(num1$) + VAL(num2$)))
CASE "-": num3$ = LTRIM$(STR$(VAL(num1$) - VAL(num2$)))
CASE "*": num3$ = LTRIM$(STR$(VAL(num1$) * VAL(num2$)))
CASE "*": num3$ = LTRIM$(STR$(VAL(num2$) / VAL(num1$)))
END SELECT

string1a$ = MID$(string1$, 1, j)
string1b$ = MID$(string1$, i + 1, LEN(string1$) - i)
string1$ = string1a$ + num3$ + string1b$

LOOP

'now set the value of the function
string1$ = string2$ + string1$ + string3$
IF INSTR(string1$, " ") = 0 THEN EXIT DO
LOOP
reduce.string$ = string1$
END FUNCTION
Peace cannot be obtained without war. Why? If there is already peace, it is unnecessary for war. If there is no peace, there is already war."

Visit www.neobasic.net to see rubbish in all its finest.
Reply
#33
Ok guys, this is a working version of Agamemnus' original idea. You complie this program once. It generates a one line program called eee.bas which it compiles and runs. I have a batch file called COMPILE which it invokes to compile the eee.bas program. You can make it a bit more fancy, but you can't get any simpler.
Code:
rem EXPRESSION EVALUATOR --- LET BASIC DO THE WORK.
INPUT "Enter expression to evaluate ";e$
open "eee.bas" for output as #1
open "eee.exe" for output as #2  Â´create so can kill.
print #1,"print "+e$
print #2,"xxx"
close
kill "eee.exe"           'In case of compile error.
shell "COMPILE eee"
cls
run "eee"
Q.E.D.
*****
Reply
#34
A little bit slow, isn't it? Big Grin
SCUMM (the band) on Myspace!
ComputerEmuzone Games Studio
underBASIC, homegrown musicians
[img]http://www.ojodepez-fanzine.net/almacen/yoghourtslover.png[/i
Reply
#35
Very funny, Nathan.
*****
Reply
#36
Cool na_th_an, but it doesnt work with: 2 * -3

And aga, yours works with 2 * -3, but doesnt work with 2+(3), it says the answer is (2 + 3), but if you put that back into the function it simplifies it again, so repedatively your one pretty much works perfectly as far as i can see Smile
Reply
#37
Nexinarius, that's because I erroneously added an EXIT DO right before the last LOOP. It shouldn't be there.
Peace cannot be obtained without war. Why? If there is already peace, it is unnecessary for war. If there is no peace, there is already war."

Visit www.neobasic.net to see rubbish in all its finest.
Reply
#38
Quote:Cool na_th_an, but it doesnt work with: 2 * -3

And aga, yours works with 2 * -3, but doesnt work with 2+(3), it says the answer is (2 + 3), but if you put that back into the function it simplifies it again, so repedatively your one pretty much works perfectly as far as i can see Smile

You're right. I forgot a case.
I can fix that, but I'll do it tomorrow Smile
SCUMM (the band) on Myspace!
ComputerEmuzone Games Studio
underBASIC, homegrown musicians
[img]http://www.ojodepez-fanzine.net/almacen/yoghourtslover.png[/i
Reply
#39
@aga: o ok.

edit: i removed it, and it didnt seem to fix it.
Reply
#40
Yes it did.

The function only works with spaces. 5+5 won't work right. (notice qb works with spaces too, BUT it also reformats 5+5 into 5 + 5)

However, my program doesn't reformat. That should be the job of the input statement. Smile
Peace cannot be obtained without war. Why? If there is already peace, it is unnecessary for war. If there is no peace, there is already war."

Visit www.neobasic.net to see rubbish in all its finest.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)