Challenge: 
Winner?: 
No
Code Snippet: 
remstart
Maths parser!  (,), *, /, +, -, p[i], e, s[in], c[os], t[an], sq[r]t, a[b]s
by qwe
remend

REM types
type equations
v as float
o as string
endtype

REM arrays
dim e(256) as equations

REM global variables
global error_msg$ = ""
global answer# = 0.0
global option_display_steps = 1
global x_value# = 0.0

REM cut straight to plotter
`gosub graphing

gosub clear
REM MAIN DO LOOP
do
   ink rgb(0,255,128),0
   previous_equation$ = equation$
   input "Enter equation:    ", equation$
   if equation$ = "" then equation$ = previous_equation$

   if equation$ = "help" then gosub help          : equation$ = "no solve"
   if equation$ = "plot" then use_same_stats = 0 : gosub graphing : equation$ = "no solve"
   if equation$ = "clear" then gosub clear       :  equation$ = "no solve"
   if equation$ <> "no solve"
      error_msg$ = ""
      answer# = get_answer("("+equation$+")", 0)
      ink rgb(0,255,255),0
      print "The answer is :    " + str$(answer#)
      ink rgb(255,0,0),0
      if error_msg$ <> "" then print error_msg$
      print
   endif
loop
end

clear:
CLS
REM instructions
ink rgb(255,64,64),0
print "Maths parser by qwe"
print "Handles (, ), *, /, +, -, !, [p]i, [e], [s]in, [c]os, [t]an, sq[r]t, a[b]s, [E]"
ink rgb(255,255,128),0
print "Type 'help' for help"
print "Type 'plot' for graphing"
print "Type 'clear' to clean screen"
print "Type in an equation to solve it.  Use '`' for negative symbol"
print
return

help:
   ink rgb(255,128,255),0
   print "Type in an equation and press enter to see the answer"
   print "Valid characters are: (, ), +, -, *, /, ^, !"
   print "'p' is treated as pi, 'e' is treated as e, '`' is the negative symbol"
   print "'s' 'c' 't' and 'r' are treated as sine, cosine, tangent, and square root"
   print " - They can be entered as r(#), r(equation), or r# ( e.g. r(4), r(3+1), r4 )"
   print "'a' is treated as the previous answer, 'b' as absolute value, 'E' as sci. not."
   print
   print "'help' brings up this menu. 'plot' brings up the graphing utility"
   print
return

function get_answer(e$, option_replace_x)
   REM set variables
   length = len(e$)
   array_count = 0
   REM clear array
   for i = 0 to 255
      e(i).o = ""
      e(i).v = 0.0
   next i
   REM translate string equation into array
   for i = 1 to length
      s$ = mid$(e$, i)

      if s$="(" or s$=")" or s$="+" or s$="-" or s$="*" or s$="/" or s$="^" or s$="p" or s$ = "e" or s$ = "s" or s$ = "c" or s$ = "t" or s$ = "r" or s$ = "a" or s$ = "b" or s$ = "x" or s$ = "!" or s$ = "E"
         if add_value$ = ""
         else
            e(array_count).v = val(add_value$)
            add_value$ = ""
            inc array_count
         endif

         e(array_count).o = s$
         inc array_count
      else
         if s$ = "`" then s$ = "-"
         add_value$ = add_value$ + s$
         if mid$(e$, i+1) = "(" and add_value$ = "-" then add_value$ = "-1"
      endif
   next i
   REM special features
   add_implicit_multiplications()
   set_pi_and_e_values()
   if option_replace_x = 1 then set_x_value()
   add_implicit_a()
   uh_oh = check_for_brackets_error()

   if uh_oh = 1 then exitfunction 0.0

   REM find out how many bracketed sections there are
   for i = 0 to 255
      if e(i).o = "(" then total_brackets = total_brackets + 1
   next i
   REM solve each level of brackets
   if total_brackets > 0
      for lvl = total_brackets to 1 step -1
         display_equation_array()
         length = solve_level(lvl)
      next lvl
   endif
   REM give answer, store answer in global variable
   localanswer#=e(0).v
   answer#=e(0).v
endfunction localanswer#

function display_equation_array()
   ink rgb(192,192,192),0
   done=0
   pos = 0

   repeat
      `see what brakcet level computer is at
      if e(pos).o = "(" then inc bracket_level
      if e(pos).o = ")" then dec bracket_level

      `once reaches last bracket, no more no more
      if bracket_level = 0 then done = 1

      `add each array element to string
      if e(pos).o = ""
         display$ = display$ + str$(e(pos).v)
      else
         display$ = display$ + e(pos).o
      endif

      inc pos
   until done=1

   `take off first and last brackets
   length = len(display$)
   display$ = left$(display$, length-1)
   display$ = right$(display$, length-2)
   `display string
   if option_display_steps = 1
      print display$
   endif
endfunction

function solve_level(lvl)
   for i = 0 to 255
      if e(i).o = "(" then inc count_brackets
      `when computer comes to specified level
      if count_brackets = lvl
         `do operations
         solve_factorial(i)
         solve_sci_not(i)

         solve_special(i, "s")
         solve_special(i, "c")
         solve_special(i, "t")
         solve_special(i, "r")
         solve_special(i, "b")

         solve_segment(i, "^", "{")
         solve_segment(i, "*", "/")
         solve_segment(i, "-", "+")
         `now the segment is simplified to one value
         `now we can eliminate brackets around this value
         e(i).v = e(i+1).v
         e(i).o = ""
         eliminate_slot(i+1)
         eliminate_slot(i+1)

         dec count_brackets
      endif
   next i
endfunction length

function solve_sci_not(i)
   pos = i
   repeat
      `increase position along array and get its operator value
      inc pos
      s$ = e(pos).o
      `if operator is what we want, perform operation and pull out previous and next slots
      if e(pos).o = "E"
         e(pos).v = e(pos-1).v * (10.0 ^ e(pos+1).v)
         e(pos).o = ""
         eliminate_slot(pos+1)
         eliminate_slot(pos-1)
         dec pos
      endif
   until s$ = ")"
endfunction

function solve_factorial(i)
   pos = i
   repeat
      `increase position along array and get its operator value
      inc pos
      s$ = e(pos).o
      `if operator is what we want, perform operation and pull out previous and next slots
      if e(pos).o = "!"
         e(pos).v = factorial(e(pos-1).v)
         e(pos).o = ""
         eliminate_slot(pos-1)
         dec pos
      endif
   until s$ = ")"
endfunction

function factorial(num#)
   ans# = 1.0
   for i = 1 to num#
      ans# = ans# * i
   next i
endfunction ans#

function solve_special(i, o$)
   pos = i
   repeat
      `increase position along array and get its operator value
      inc pos
      s$ = e(pos).o
      `if operator is what we want, perform operation and pull out previous and next slots
      if e(pos).o = o$
         if o$ = "s" then e(pos).v = sin(e(pos+1).v)
         if o$ = "c" then e(pos).v = cos(e(pos+1).v)
         if o$ = "t" then e(pos).v = tan(e(pos+1).v)
         if o$ = "r" then e(pos).v = sqrt(e(pos+1).v)
         if o$ = "b" then e(pos).v = abs(e(pos+1).v)

         eliminate_slot(pos+1)
         e(pos).o = ""
      endif
   until s$ = ")"
endfunction

function solve_segment(i, oa$, ob$)
   pos = i
   repeat
      `increase position along array and get its operator value
      inc pos
      s$ = e(pos).o
      `if operator is what we want, perform operation and pull out previous and next slots
      if e(pos).o = oa$ or e(pos).o = ob$
         if e(pos).o = "^" then e(pos).v = e(pos-1).v ^ e(pos+1).v
         if e(pos).o = "*" then e(pos).v = e(pos-1).v * e(pos+1).v
         if e(pos).o = "/" then e(pos).v = e(pos-1).v / e(pos+1).v
         if e(pos).o = "+" then e(pos).v = e(pos-1).v + e(pos+1).v
         if e(pos).o = "-" then e(pos).v = e(pos-1).v - e(pos+1).v

         if e(pos).o = "/" and e(pos+1).v = 0 then error_msg$ = "Error: Divide by zero"

         e(pos).o = ""
         eliminate_slot(pos+1)
         eliminate_slot(pos-1)
         dec pos `position along array is dec'd because previous position was just pulled out
      endif
   until s$ = ")"
endfunction

function add_slot(pos_add, add$)
   for pos = 255 to pos_add step -1
      e(pos).o = e(pos-1).o
      e(pos).v = e(pos-1).v
   next pos
   e(pos_add).o = add$
   e(pos_add).v = 0.0
endfunction

function eliminate_slot(pos_remove)
   for pos = pos_remove to 254
      e(pos).o = e(pos+1).o
      e(pos).v = e(pos+1).v
   next pos
endfunction

function set_pi_and_e_values()
   for i = 0 to 255
      if e(i).o = "p" then e(i).o = "": e(i).v = 3.1415927
      if e(i).o = "e" then e(i).o = "": e(i).v = 2.7182818
      if e(i).o = "a" then e(i).o = "": e(i).v = answer#
   next i
endfunction

function set_x_value()
   for i = 0 to 255
      if e(i).o = "x" then e(i).o = "": e(i).v = x_value#
   next i
endfunction

function add_implicit_a()
   if e(1).o = "+" or e(1).o = "-" or e(1).o = "*" or e(1).o = "/" or e(1).o = "^"
      add_slot(1, "a")
   endif
   set_pi_and_e_values()
endfunction

function add_implicit_multiplications()
   for i = 1 to 255
      if e(i).o = "(" or e(i).o = "s" or e(i).o = "c" or e(i).o = "t" or e(i).o = "r" or e(i).o = "p" or e(i).o = "b" or e(i).o = "a" or e(i).o = "e" or e(i).o = "x"
         if e(i-1).o = "" or e(i-1).o = ")" or e(i-1).o = "!" or e(i-1).o = "p" or e(i-1).o = "e" or e(i-1).o = "a" or e(i-1).o = "x"
            add_slot(i, "*")
         endif
      endif
      if e(i).o = ")" or e(i).o = "!"
         if e(i+1).o = "" or e(i).o = "s" or e(i).o = "c" or e(i).o = "t" or e(i).o = "r" or e(i).o = "p" or e(i).o = "b" or e(i).o = "a" or e(i).o = "e" or e(i).o = "x"
            add_slot(i+1, "*")
         endif
      endif
      if e(i).o = ""
         if e(i-1).o = "p" or e(i-1).o = "e" or e(i-1).o = "a" or e(i-1).o = ")" or e(i-1).o = "x"
            add_slot(i, "*")
         endif
      endif
   next i
endfunction

function check_for_brackets_error()
   for i = 0 to 255
      if e(i).o = "(" and e(i+1).o = ")"  then error_msg$ = "Error: empty brackets" : uh_oh = 1
   next i

   for i = 0 to 255
      if e(i).o = "(" then inc count_start_brackets
      if e(i).o = ")" then inc count_end_brackets
   next i
   if count_start_brackets <> count_end_brackets then error_msg$ = "Error: Start brackets don't match end brackets" : uh_oh = 1
endfunction uh_oh

function emptybox(xa,ya,xb,yb)
   line xa,ya,xa,yb
   line xa,yb,xb,yb
   line xb,yb,xb,ya
   line xb,ya,xa,ya
endfunction

graphing:
   CLS
   REM Get window stats
   if use_same_stats = 0
      ink rgb(128,255,128),0
      print "Press enter 7 times to leave default and just enter equation"
      print
      ink rgb(255,255,128),0
      print "Default window size is 400 pixels"
      print
      ink rgb(192,192,128),0
      input "Enter window x size (pixels): ", x_pixel_size : if x_pixel_size = 0 then x_pixel_size = 400
      input "Enter window y size (pixels): ", y_pixel_size : if y_pixel_size = 0 then y_pixel_size = 400
      print
      ink rgb(255,255,128),0
      print "Default value for window x/y unit size is 20 (-10 to 10) on each axis"
      print
      ink rgb(192,192,128),0
      input "Enter window X size in units: ", x_max# : x_max# = x_max# / 2.0 : if x_max# = 0 then x_max# = 10
      input "Enter window Y size in units: ", y_max# : y_max# = y_max# / 2.0 : if y_max# = 0 then y_max# = 10
      print
      input "Enter x grid value (enter for none): ", grid_x#
      input "Enter y grid value (enter for none): ", grid_y#
      print
      input "Connect dots of grid? (0 or 1): ", option_connect
      print
   endif
   ink rgb(128,255,128),0
   input "Enter equation: ", equation$
   CLS

   sync on

   REM get some variables
   x_min# = -1 * x_max#
   y_min# = -1 * y_max#
   total_x_unit_size# = abs(x_min#) + x_max#
   total_y_unit_size# = abs(y_min#) + y_max#
   option_display_steps = 0
   winxpos = 320 - x_pixel_size/2
   winypos = 240 - y_pixel_size/2

   REM draw window
   if grid_x# > 0.001
      `draw x grid
      ink rgb(64,64,64),0
      x_ratio# = grid_x# / total_x_unit_size#
      x_interval# = x_ratio# * (x_pixel_size + 0.0)
      current_x# = 0.0
      repeat
         line int(current_x#) + winxpos, 0 + winypos, int(current_x#) + winxpos, y_pixel_size + winypos
         inc current_x#, x_interval#
      until int(current_x#) > x_pixel_size
   endif
   if grid_y# > 0.001
      `draw y grid
      ink rgb(64,64,64),0
      y_ratio# = grid_y# / total_y_unit_size#
      y_interval# = y_ratio# * (y_pixel_size + 0.0)
      current_y# = 0.0
      repeat
         line 0 + winxpos, int(current_y#) + winypos, x_pixel_size + winxpos, int(current_y#) + winypos
         inc current_y#, y_interval#
      until int(current_y#) > y_pixel_size
   endif
   `draw border
   ink rgb(255,255,255),0
   emptybox(0 + winxpos,0 + winypos,x_pixel_size + winxpos,y_pixel_size + winypos)
   `draw x and y axis
   ink rgb(192,192,192),0
   line 0 + winxpos, y_pixel_size/2 + winypos, x_pixel_size + winxpos, y_pixel_size/2 + winypos
   line x_pixel_size/2 + winxpos, 0 + winypos, x_pixel_size/2 + winxpos, y_pixel_size + winypos
   `get plot stats to display
   length_msg$ = str$(x_min#) + " <-> " + str$(x_max#)
   height_msg$ = str$(y_min#) + " <-> " + str$(y_max#)

   error_msg$ = ""
   previous_x = 0
   previous_y = 0
   REM Draw each x,y coordinate
   for x_pixel = 1 to x_pixel_size
      `find which x value in units we're to solve for
      x_unit# = (x_pixel + 0.0) / (x_pixel_size + 0.0)
      x_unit# = x_unit# * (total_x_unit_size# + 0.0)
      x_unit# = x_unit# + (x_min# + 0.0)

      `find y value in units
      x_value# = x_unit#
      y_unit# = get_answer("("+equation$+")", 1)

      `find y value in pixels
      y_pixel# = y_unit# * -1.0
      y_pixel# = y_pixel# / (total_y_unit_size#)
      y_pixel# = y_pixel# * (y_pixel_size + 0.0)
      y_pixel# = y_pixel# + ((y_pixel_size + 0.0) / 2.0)

      y_pixel = y_pixel#
      `draw point
      if x_pixel = 1 then previous_x = x_pixel: previous_y = y_pixel
      if y_pixel < y_pixel_size
         if option_connect
            ink rgb(255,255,128),0
            line x_pixel + winxpos, y_pixel + winypos, previous_x + winxpos, previous_y + winypos
         else
            dot x_pixel + winxpos, y_pixel + winypos, rgb(255,255,128)
         endif
      endif

      previous_x = x_pixel
      previous_y = y_pixel
   next x
   ` cover up line if it went outside of graph
   ink rgb(32,32,32),0
   box 0, y_pixel_size + winypos + 1, 640, 480
   box 0, 0, 640, winypos
   box 0, 0, winxpos, 480
   box winxpos + x_pixel_size + 1, 0, 640, 480
   ` show graph stats
   ink rgb(128,255,128),0
   center text x_pixel_size/2 + winxpos, y_pixel_size + winypos, length_msg$
   center text x_pixel_size + 50 + winxpos, y_pixel_size/2 + winypos, height_msg$
   ink rgb(255,255,255),0
   center text x_pixel_size/2 + winxpos, y_pixel_size + 50 + winypos, equation$

   ink rgb(255,64,64),0
   if error_msg$ <> "" then center text x_pixel_size/2 + winxpos, y_pixel_size + 100 + winypos, error_msg$

   ink rgb(0,255,255),0
   center text x_pixel_size/2 + winxpos, winypos - 40, "[RShift] returns to equation solver"
   center text x_pixel_size/2 + winxpos, winypos - 28, "[\] runs grapher again"
   center text x_pixel_size/2 + winxpos, winypos - 16, "[Backspace] runs grapher keeping same window stats"

   sync
   sync off

   done=0
   redo_grapher=0
   use_same_stats=0
   repeat
      if keystate(54) then done=1
      if keystate(43) then done=1: redo_grapher=1
      if keystate(14) then done=1: redo_grapher=1: use_same_stats=1
   until done=1
   if redo_grapher then gosub graphing
   if redo_grapher_same_stats then gosub graphing
   option_display_steps = 1
   gosub clear
return