The traditional theories about parsing and their implementations in tools like yacc, lex, antlr, etc. are not that important in practice. I also used them in some university courses, but after I encountered parsing problems in practice it seemed easier to just implement a recursive descent parser in the host language.
First, you have to learn the DSL's of these tools (which are non-trivial in detail). Second you have to integrate them into your toolchain. Third - and that is my biggest complaint - you have to connect the Parser combinator's AST to your domain AST. The last thing is pretty amusing as I consider it the main purpose of a parser.
In practice (hopefully after evaluating the need for a custom data format as it might be possible to hijack existing languages and standards) I either use a combinator-parser (if FP available) or an ad-hoc recursive descent parser. Maybe I consider a lexer but the representation of tokens is also a non-trivial decision.
Yes, there are always too many ideas to explore and too less time. However if you want to look into a static typed functional language I would go with Haskell as it tries harder to exploit a type system to do useful work (although there are even more sophisticated ways to do programming, i.e. by writing proofs (~= programs) in proof-systems, e.g. coq, Isabelle, etc.).
I was introduced to OCaml at my University, but switched later to Haskell and it seemed simpler too me. Furthermore Haskell's ecosystem seems to be more major (or maybe just more vocal?).
> It has no syntax (of its own) in that it hijacks s-expression syntax instead. When you want to write Lisp code, you actually write some data structures in the s-expression data format, like when writing some data in JSON or XML. Then a Lisp interpreter or compiler uses an s-expression parser to read that data structure into memory, and operates on that.
My point is that the s-expression format has to be defined (obviously), e.g. you enclose lists in '(' and ')' characters, space symbols separate tokens, etc. In my world these rules are consequences of a defined syntax and saying there is no syntax is just wrong. The reader parses at some point a byte sequence and builds an AST. That Lisp/Scheme has such a simple syntax is a powerful feature of the language but saying it has no syntax just contributes to the belief of misinformed people that Lisp is some kind of strange Voodoo-language which is a bad thing as it is a powerful tool.
I am a fan of Scheme but never got that statement. Why do people say Scheme/Lisp has no syntax? I mean clearly it has a _simple_ syntax, i.e. an expression is either an atom (an identifier, a number, a lambda expression, etc.) or a list of expressions, denoated by "(expr0 expr1 ... exprN). I would say it has a simple, well-thought and powerful syntax.
I am not so sure with that. Say, your program is used in a shell script and is invoked badly - you might want to print its usage then. If you exit normally your shell script might break weirdly but if you exit with error it's easier to spot the reason of failure.
On the other hand you made me thinking and probably you should have three code passes per default:
[0] normal behaviour (exit 0)
[1] bad arguments (exit EINVAL)
[2] --usage (print to stdout but but exit != 0)?
Anyway I am not sure if it makes sense to declare "usage" as normal behaviour.
First, you have to learn the DSL's of these tools (which are non-trivial in detail). Second you have to integrate them into your toolchain. Third - and that is my biggest complaint - you have to connect the Parser combinator's AST to your domain AST. The last thing is pretty amusing as I consider it the main purpose of a parser.
In practice (hopefully after evaluating the need for a custom data format as it might be possible to hijack existing languages and standards) I either use a combinator-parser (if FP available) or an ad-hoc recursive descent parser. Maybe I consider a lexer but the representation of tokens is also a non-trivial decision.