I don't get how to intuitively come up with an example for an ambiguous grammar.
Let's take as an example this grammar:
Declaration ::= Type D ;
Type ::= "int" | "char"
D ::= "*" D
| D "[" number "]"
| D "(" Type ")"
| "(" D ")"
| name
I am told outright that this grammar is ambiguous. What is expected of me is to find one example that proves that it is. What I'm interested is what is the thought process that allows you to find an example. Our teacher just gave us one example that would show that we would obtain two different derivation tree like:
int *foo[5]; has two derivation tree
Declaration Declaration
/ | \ / | \
Type D ; Type D ;
| / \ | / \____
int * D int / \ \ \
/ \____ D [ 5 ]
/ \ \ \ / \
D [ 5 ] * D
| |
foo foo
However I have no idea how he thought to himself that int*foo[5] would be the example before doing the trees. It all boils down to how they did it without trial and error?
How to make that grammar unambiguous? I was also given the task to make the above grammar unambiguous. However I don't know yet again what is the intuition behind making it unambiguous.
They gave us this solution:
Declaration ::= Type D ;
Type ::= "int" | "char"
D ::= "*" D
| "(" D ")" D'
| name D'
D' ::= "[" number "]" D'
| "(" Type ")" D'
| empty <== empty string
There must be a pattern in all of this. What it is? What is the general method to solve this type of problem regardless of which grammar is given?