3 ms·
It is comparatively hard to parse, being context sensitive (need to keep track of types) as well as requiring an implementation of the preprocessor, which has a
by jstimpfle 4y ago
It is comparatively hard to parse, being context sensitive (need to keep track of types) as well as requiring an implementation of the preprocessor, which has arcane enough rules that most programmers don't really know them.
Also, there are a number of historic syntax quirks that a conforming compiler, at least pre-C23, has to understand. For example, function declaration that lacks return value specification (implicit int) or parameters.
- bcrl 4y agoHave you actually written a C parser? I will grant that C++ is incredibly hard, but C is relatively straightforward. Types are not at all difficult to parse in C, and the pre-processor isn't all that complex either when you have the spec in front of you. If you think it's hard, you probably didn't have the right documentation. I picked up the book "The Annotated ANSI C Standard" by Herbert Schildt sometime back in ~1993, and it made writing a recursive descent parser almost trivial. That book made C syntax actually make sense in a way that the K&R book and other introductory C books didn't.
- jstimpfle 4y ago> Types are not at all difficult to parse in C I haven't written a C parser, but a number of other parsers. I can confidently say that C syntax, as a result of historical development, ended up in a place where it is much more annoying to parse than a properly designed language with a LL(1) syntax. If your parser can parse the following, I both congratulate you for your persistence and ridicule you for the statement that this is "not at all difficult". C syntax is annoying at the very least. typedef struct Foo Foo; void xx(void) { typedef int Bar; Bar x; } void foo(int, int, int); void bar(Foo Foo, int, int Bar); baz(Bar, y, z) Foo *Bar; int y; double z; { return 1; } I don't know what exactly is required from a conforming C compiler, but this is successfully compiled by gcc -std=c89. The preprocessor, don't get me started. The D author, who is active on HN, has both stated that parsers are less than 0.1% of the work in a compiler, and also that the C preprocessor is terrible and he required multiple or many attempts, I think spread over multiple years, to get it right.
- bcrl 4y agoThe way I handled it fell out as a result of how tokens were parsed. The token would be hashed, and that hash would be used to check if the token was a keyword in one hash table, then the same hash used to check in a symbol table. That made classification easy and low cost. I don't think it's hard in practice if you use the right approach. More complex from a theory point of view, sure. I am serious when I say that the Annotated ANSI C Standard book made this easy to understand. Without that book, parsing C types certainly did not make a lot of sense to me either. It can be found here: https://www.amazon.com/Annotated-ANSI-Standard-Programming-Languages-C/dp/0078819520/ https://www.amazon.com/Annotated-ANSI-Standard-Programming-L...
- int_19h 4y agoIt's "hard" compared to, say, Pascal, which has a grammar that's intentionally LL(1). The fact that parsing declarators is context-dependent in particular, requiring you to maintain and consult a symbol table at that point (before you even have an AST) already to determine whether a given identifier is a type or not, is a minor annoyance, but an annoyance nevertheless.
- bcrl 4y agoMore complex from a theory view, but not hard. You need a symbol table regardless, and symbols tables are most decidedly not "hard" to implement. Sure, it's a layering violation, but that's how we were forced to write efficient code back when computing resources were scarce 30+ years ago. An entire C compiler and integrated development environment was only a couple of hundred KB of executable on computers back in the 1980s under MS-DOS and on the Amiga.