4 ms·
You seem to be talking about the preprocessor, not C itself, and I'm not sure that anything you say about it is true (the preprocessor is complicated). Certainl
by zabzonk 5y ago
You seem to be talking about the preprocessor, not C itself, and I'm not sure that anything you say about it is true (the preprocessor is complicated). Certainly, your first example won't compile without warnings for any sensible GCC options.
- tom_ 5y agoA better example of C's context-sensitive grammar might be the expression "(T)*x", which parses differently depending on whether T names a type or a value.
- yakubin 5y agoThat's a good example, but of a different thing. My examples show that the input is lexed differently based on what part of AST is being produced at a given point. Your example shows that input is parsed into different ASTs based on information from the type system. I.e my examples show that in C the lexer can't be separated from the parser, and your example shows that the parser can't be separated from the type system.
- yakubin 5y ago> You seem to be talking about the preprocessor, not C itself, and I'm not sure that anything you say about it is true (the preprocessor is complicated). The preprocessor is part of the language. Both in literal sense and in real-world. All C programs use the preprocessor. You need to deal with it. Also, the grammar of the preprocessor is intertwined with C proper due to "#if" directives. The expression on the right hand side of an "#if" is parsed according to the grammar of C proper. > I'm not sure that anything you say about it is true (the preprocessor is complicated). You can run the examples under compilers and verify. Also, the part about it being context-sensitive (with regard to tokenization in #include directives vs everywhere else) is explicitly noted in the standard. Nothing controversial here. > Certainly, your first example won't compile without warnings for any sensible GCC options. Compiles just fine without any warnings with GCC with options -Wall -Wextra.
- barrkel 5y agoThe constant expressions that #if understands are a very restricted subset of C. It's best thought of as a small grammar inlined into the preprocessor rather than intermingled with the C parser, since the expressions can only evaluate preprocessor definitions and not any C declarations. I've written several C-style preprocessors. They can be fiddly to write, but you shouldn't think of them as lexing to the same lexemes as a C parser needs. You can take a lot of shortcuts there. Things like '<' and '>' being overloaded is quite common, even in lexers. You see it with nested templates / generics in C++, Java, C# etc. There are simple tricks for dealing with the ambiguity between '>>' vs '>' '>' in 'T<U<V>>'. (FWIW, having written some of those preprocessors, I think they're a bad idea. It's notable that other languages haven't copied the idea, other than C++ which inherited it.)