A simple number system

Haskell, 357 306 277 251 228 224 188 185 180 bytes

A token-based parser with an explicit stack. (%) takes a token stack and a character and either pushes (opcode,defaultnumber) or (0,number) for ({[<, or pops topmost numbers and one opcode and pushes the answer for )}]>. Opcodes are encoded by a ascii enumeration hack.

Kudos to @ChristianSievers for his great answer that I borrowed some ideas from.


s%c|elem c"([<{",g<-div(fromEnum c)25=(g,[0,0,1,-1,1]!!g):s|(a,(o,n):b)<-span((==0).fst)s=(0,[foldr1(flip$[(+),quot,(-),(*)]!!(o-1))$snd<$>a,n]!!(0^length a)):b

Now with less error-handling! Usage:

*Main> map (snd.head.foldl(%)[]) ["()","(()())","([][])","({}<>)","({}[])","[]","[[][]]","[()<>]","{()}","{([]<>)}"]

Thanks @ChristianSievers for saving 14+3 bytes!

Thanks @Zgarb for saving some+4 bytes!

PEG.js (ES6), 132 bytes

x=a:[([{<]b:x*[)\]}>]{var x='([<'.indexOf(a)
return~~eval(b.length?b.join(('+-/'[x]||'*')+' '):~-('10'[x]||2))}

Should be fixed now.


More readable:

  var x='([<'.indexOf(a)
  return ~~eval(
      b.join(('+-/'[x]||'*')+' ')

PEG.js is an extended version of Javascript specifically made for parsing. It's VERY strict, which is why I had to use var. In addition, there seems to be a bug with brackets inside strings, which bloated the code significantly.

To start, we define a rule x that matches any bracket a that may or may not contain multiple expressions that matches rule x.

For each match to rule x, we push a 0 to the array of the inner match b if b's length is 1.

If b's length > 0, then we find the index of a in ([< and get a character from +-/ using that index. If the result is undefined (meaning that a was {), then we turn the result into *. Finally, we tack on a space and join b with the result.

If b's length = 0, then we find the index of a in ([< and get a character from 10 using that index. If the result is undefined (meaning that a was { or <), then we turn the result into 2. Finally, we simply decrement.

At the end, we can just evaluate the expression and floor the result.

Python 2, 292 265 248 235 223 206 204 bytes

for n in')]}>':s=s.replace(n,'),')
for a in'(*x:sum(x)','[a=-1,*x:a-sum(x)','{*x:r(int.__mul__,x,1)','<a=1,*x:r(int.__div__,x,a)':s=s.replace(a[0],'(lambda %s)('%a[1:])
print eval(s)[0]

Replaces all brackets with a lambda that does what the bracket does, then evaluates the resulting Python code. Requires its input surrounded by quotes, like '[<><>([]{})]'.

This program stores the type of bracket as the first character in each string in the for, and everything after the keyword lambda as the rest. It then uses the first character to substitute; the rest of it is combined into a lambda like (lambda*x:sum(x))().

Try it on Ideone!