1. This is what my version of the program did:
#include <stdio.h> preprocessor command int built-in type main identifier ( punctuation void keyword ) punctuation { punctuation printf identifier ( punctuation "hello world\n" string ) punctuation ; punctuation return keyword 0 octal integer number ; punctuation cauliflower identifier ; punctuation "cauliflower" string ; punctuation /*cauliflower*/ comment /* if I do this then do you get it wrong? */ comment "if I do this then do you get it wrong?" string ; punctuation answer identifier = operator(s) 1 decimal integer number + operator(s) 2.0 floating point number * operator(s) 3 decimal integer number / operator(s) 4 decimal integer number - operator(s) 'i' character ; punctuation if keyword ( punctuation I_do_this identifier ) punctuation /*then*/ comment do_you identifier ( punctuation get identifier + operator(s) it identifier - operator(s) wrong identifier ) punctuation ? operator(s) or identifier : punctuation not identifier ; punctuation else keyword this_is identifier ( punctuation a identifier . operator(s) load identifier , punctuation of identifier -> operator(s) old identifier * operator(s) whatsit identifier ) punctuation ; punctuation does identifier < operator(s) this identifier >> operator(s) iffy identifier *= operator(s) expression identifier % operator(s) cause identifier | operator(s) problems identifier && operator(s) elsewhere identifier ; punctuation "a string" string ; punctuation not identifier - operator(s) a identifier - operator(s) string identifier ; punctuation "another string" string ; punctuation /* these are not valid operators */ comment a identifier # ???????? b identifier ; punctuation a identifier @ ???????? b identifier ; punctuation /* just recognise the individual operators these are made up from */comment a identifier : punctuation = operator(s) b identifier ; punctuation a identifier < operator(s) > operator(s) b identifier ; punctuation a identifier * operator(s) * operator(s) b identifier ; punctuation a identifier ~ operator(s) ~ operator(s) b identifier ; punctuation a identifier ^ operator(s) ^ operator(s) b identifier ; punctuation /* if you can do all the above, try "bigdata.c", or the following: */comment 012345 octal integer number ; punctuation 12345 decimal integer number ; punctuation 0x12345abc hexadecimal integer number ; punctuation 012345LU octal integer number ; punctuation 12345l decimal integer number ; punctuation 0x12345abcu hexadecimal integer number ; punctuation 123. floating point number ; punctuation 123.123 floating point number ; punctuation 123.e-1 floating point number ; punctuation 123.123E99 floating point number ; punctuation 123e+23 floating point number ; punctuation 123.e-1f floating point number ; punctuation 123.123E99l floating point number ; punctuation 123e+23F floating point number ; punctuation 123L decimal integer number ; punctuation 'a' character ; punctuation '\n' character ; punctuation '\'' character ; punctuation '\"' character ; punctuation '\\' character ; punctuation '\0' character ; punctuation '\01' character ; punctuation '\012' character ; punctuation '\xAB' character ; punctuation /* a comment */ comment not identifier - operator(s) a identifier - operator(s) comment identifier ; punctuation /* another comment */ comment } punctuation
2. This is a minor point, but you may find it interesting. ANSI C only includes unsigned numbers in its syntax, rather than signed numbers, because otherwise it can't tell the difference between
a= b - 1and
a= -1i.e. the latter expression consists of the operator "negate" acting on the integer value "1". This causes irritating problems if you try to write the most negative number possible e.g. on a 16-bit computer:
a= -32768as this is "negate" acting on "32768" which probably causes an overflow at compile-time! Instead, you have to write
a= 0x8000