RosettaCodeData/Task/S-expressions/APL/s-expressions.apl
2023-07-01 13:44:08 -04:00

62 lines
2.6 KiB
APL
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

sexp{
wspace' ',⎕TC ⍝ whitespace is space, tab, cr, lf
⍝ turn string into number if possible
num{
0=: ⍝ empty = nope
()'-¯':-1 ⍝ negative?
(1+.='.').⎕D,'.': ⍝ number: all digits and 0 or 1 points
⍝ otherwise, nope.
}
⍝ tokenize (0=brackets, 1=strings, 2=atoms)
tok{
d(~\wspace)/ ⍝ ignore leading whitespace
d'':d ⍝ empty input = empty output
s1d r1d ⍝ start and rest
s'()':(0,s),r ⍝ brackets: just the bracket
sb\~('"'=r)'\'¯1r ⍝ strings: up to first " not preceded by \
sd(1sd'"')/sdsb/r ⍝ without escape characters
s='"':(1,sd),1(~sb)/r
atm\~dwspace,'()"' ⍝ atom: up to next whitespace, () or "
(2,atm/d),(~atm)/d
}
⍝ build structure from tokens
build{
0=: ⍝ empty input = done
typ tok ⍝ current token and type
rst1 ⍝ rest of tokens
tok,'(':(,0 l)rl rrst ⍝ open bracket: go down a level
tok,')': rst ⍝ close bracket: go up a level
typ=1:(,1 tok)rst ⍝ string: type 1
0nnum tok:(,2(,n))rst ⍝ number: type 2
(,3 tok)rst ⍝ symbol: type 3
}
⍝ check that a string was passed in
(''0)1:⎕SIGNAL('EN'11)('Message' 'Input must be a char vector')
⍝ check that all strings are closed
quot('"'=)'\'¯1
02|+/quot:⎕SIGNAL('EN'11)('Message' 'Open string')
⍝ check that all brackets match (except those in strings)
nest+\+1 ¯1×[1]'()'.=(~2|+\quot)/
(0¯1nest)0<.nest:⎕SIGNAL('EN'11)('Message' 'Mismatched parentheses')
build tok
}
pretty{
⍝ Prettyprinter for parsed S-expressions
NL⎕tc[2]
{
typ itm
typ=3:itm,NL ⍝ Atom
typ=2:(itm),NL ⍝ Number
typ=1:('"',('"'⎕R'\\"'itm),'"'),NL ⍝ String
typ=0:'(',NL,('^'⎕R' ' itm),')',NL ⍝ List
}¨
}