From Newsgroup: comp.compilers
Christopher F Clark <
christopher.f.clark@compiler-resources.com> wrote or quoted:
While I agree with our esteemed moderator's point about aesthetics, it
is worth noting that Wirth intentionally made Pascal easy to parse.
Thus, the Pascal declaration notation was designed to be parsed with a
one pass compiler.
Wirth famously created another language that is even easier to
parse, viz. "PL/0" for his 1976 book "Compilerbau", which then
became "Oberon-0" for his 1996 book "Compiler Construction".
C's notation does
have the nice aspect that declaration syntax matches usage.
For readers who might not know those rules:
| Parsing C Declarations
|
| To parse any C declaration by hand, follow the "Clockwise/Spiral Rule"
| (or Right-Left Rule). Always start at the identifier and move outward
| using this strict operator precedence:
|
| Precedence Rules
|
| 1. Groupings: Parentheses ( . . . ) surrounding a modifier
|
| 2. Post-fix operators (Right): Array subscripts [] and function
| parameters ()
|
| 3. Pre-fix operators (Left): Pointer stars *
|
| Step-by-Step Algorithm
|
| 1. Locate the identifier (the variable or function name). Say: "__ is
| a . . . ". When parsing an abstract declarator (e.g., inside a
| cast like "(int (*)[10])" or sizeof), find the location where the
| identifier would normally be placed.
|
| 2. Look to the right of the current position.
|
| - If [], say: "array of . . . " and move past it.
|
| - If (), say: "function returning . . . " and move past it.
|
| 3. Look to the left of the current position.
|
| - If *, say: "pointer to . . . " and move past it.
|
| - If a type qualifier (const, volatile), apply it to the element
| to the left.
|
| 4. Encountering Parentheses: If you hit a closing parenthesis ) on
| the right, you must consume all modifiers to the left until you
| hit the matching opening parenthesis (. Then, step outside the
| parentheses and repeat from Step 2.
|
| 5. Final Base Type: When the identifier and all modifiers are
| consumed, read the leftmost base type (e.g., int, char).
|
| Quick Reference Table
|
| Operator Reading Direction Meaning
| ---------- ------------------- ------------------------
| name Start here "name is a . . . "
| [N] Right " . . . array of N . . . "
| () Right " . . . function returning . . . "
| * Left " . . . pointer to . . . "
| const Left " . . . constant . . . "
Lines marked with "| " come from my editing, where I start by writing
prompts for the chatbot and then edit the generated texts and format
them for Usenet. The chatbots might make mistakes and misrepresent
or invent facts.
For example, in "(int const *(*(*)( ))[ ])", we insert the "virtual
identifier" "_" to get "(int const *(*(*_)())[ ])". So we now have
"pointer to" and what remains is "(int const *(*_())[ ])"; this gives
"function returning a pointer to", and "(int const *_[ ])" gives
"array of pointers to constant ints". So it's, "pointer to function
returning a pointer to an array of pointers to constant ints".
From:
ram@zedat.fu-berlin.de (Stefan Ram)
--- Synchronet 3.22a-Linux NewsLink 1.2