RosettaCodeData/Task/Tokenize-a-string-with-esca.../AppleScript/tokenize-a-string-with-esca...

92 lines
2.3 KiB
AppleScript

------------------ TOKENIZE WITH ESCAPING ----------------
-- tokenize :: String -> Character -> Character -> [String]
on tokenize(str, delimChar, chrEsc)
script charParse
-- Record: {esc:Bool, token:String, tokens:[String]}
-- charParse :: Record -> Character -> Record
on |λ|(a, x)
set blnEsc to esc of a
set blnEscChar to ((not blnEsc) and (x = chrEsc))
if ((not blnEsc) and (x = delimChar)) then
set k to ""
set ks to (tokens of a) & token of a
else
set k to (token of a) & cond(blnEscChar, "", x)
set ks to tokens of (a)
end if
{esc:blnEscChar, token:k, tokens:ks}
end |λ|
end script
set recParse to foldl(charParse, ¬
{esc:false, token:"", tokens:[]}, splitOn("", str))
tokens of recParse & token of recParse
end tokenize
--------------------------- TEST -------------------------
on run
script numberedLine
on |λ|(a, s)
set iLine to lineNum of a
{lineNum:iLine + 1, report:report of a & iLine & ":" & tab & s & linefeed}
end |λ|
end script
report of foldl(numberedLine, {lineNum:1, report:""}, ¬
tokenize("one^|uno||three^^^^|four^^^|^cuatro|", "|", "^"))
end run
-------------------- GENERIC FUNCTIONS -------------------
-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
tell mReturn(f)
set v to startValue
set lng to length of xs
repeat with i from 1 to lng
set v to |λ|(v, item i of xs, i, xs)
end repeat
return v
end tell
end foldl
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
if class of f is script then
f
else
script
property |λ| : f
end script
end if
end mReturn
-- splitOn :: String -> String -> [String]
on splitOn(pat, src)
set {dlm, my text item delimiters} to ¬
{my text item delimiters, pat}
set xs to text items of src
set my text item delimiters to dlm
return xs
end splitOn
-- cond :: Bool -> a -> a -> a
on cond(bool, f, g)
if bool then
f
else
g
end if
end cond