The new Interpreter functionality in version 10 looks like it has the potential to make parsing custom data formats very easy. I'm trying to create a CSV parser.
Requirements:
- Rows are delimited by newlines, columns are delimited by commas.
- Entries can be numbers, strings (everything that's quoted or can't be interpreted as a number is a string).
- Commas in quoted strings must be ignored.
- Empty elements are allowed, e.g. this row contains three empty elements:
,,. They're delimited by two commas. These can be parsed to eitherNullor"".
My actual problem doesn't have requirement 3. I put in more requirements in the hopes to make the question more generally useful, and I meant to accept answers that satisfy only a subset of these. (Perhaps this was misguided.) In the meantime Carlo's answer explains that requirement 3. can't be met.
Test data:
,"one","2"
"a",1,2
"b",3,"4c"
"c",5,x
"d",6,"seven, eight"
Or ready to paste Mathematica string:
csv = ",\"one\",\"2\"\n\"a\",1,2\n\"b\",3,\"4c\"\n\"c\",5,x\n\"d\",6,\"seven,eight\""
Parsed result should MatchQ this pattern:
{{Null | "" | Missing[___], "one", "2"},
{"a", 1, 2},
{"b", 3, "4c"},
{"c", 5, "x"},
{"d", 6, "seven, eight"}}
How close can we get to this result, using Interpreter?
Here's a first try:
int = Interpreter[
DelimitedSequence[
DelimitedSequence[
Restricted["String", "\"" ~~ ___ ~~ "\""] | "Number" | "String",
","
],
"\n"
]
]
int[csv]
What it gets wrong:
- fails on point 4. (this is actually important for me)
- fails on point 3.
- doesn't unquote strings
It may not be possible to implement all the features I request using Interpreter, but how close can we get? How much time and effort can Interpreter save when attacking this problem? Preferably it should be possible to offload most of the processing to interpreter and reach the desired result by adding minimal pre and/or post-processing.

Interpreterbut notInterpreter["CSV"]@str:) – C. E. Aug 07 '14 at 17:46Import[..., "CSV"]: Some problems:4cis interpreted as currency and converted to the number4instead of being read as"4c". I can fix this with"CurrencyTokens" -> None. Then"2"is again read as the number2, not a string, which is again a problem. I thought it would be better to explicitly restrict what data types to interpret and how. – Szabolcs Aug 07 '14 at 17:53Interpreterwas meant for this actually. If that's the case then I better not push it with this application and remove this question. However, if there's a good solution usingSemanticImportand ifSemanticImportdoesn't require an internet connection (does it?) then it would be better to give an answer using aSemanticImportsolution, mention thatInterpreteris not for this, and keep the question. – Szabolcs Aug 07 '14 at 17:57Interpreter[DelimitedSequence[StringReplace[#, "\"" ~~ a___ ~~ "\"" :> a] & | "Number" | "String", ","]]["\"a\",1,2,c"]– Carlo Aug 07 '14 at 18:05Interpreter[StringReplace[#, "\"" ~~ a___ ~~ "\"" :> a] & | "String"][""]. Is it a bug or am I misunderstanding how it should work?Interpreter["String"][""]doesn't fail, nor doesInterpreter[StringReplace[#, "\"" ~~ a___ ~~ "\"" :> a] &][""]. – Szabolcs Aug 07 '14 at 18:42Missing["NoInput"]so we try the second that isMissing["NoInput"]as well. Since we considered the first equivalent to the Failure, we can't treat the second as good. – Carlo Aug 07 '14 at 18:53Interpreter["Number"]is just too slow to be able to use it to implement parsers for different file formats. Please see here. Is there a chance that performance will be improved for 10.0.1 or 10.0.2? – Szabolcs Aug 09 '14 at 15:35