Correct way to derive parse trees, for a given input, to show ambiguity.
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Whenever `malloc` returns something, it is an array. Whenever `strcpy` or `memcpy` is called, it is is a copy between arrays. To tell the truth, C doesn't have string type, it uses character-arrays instead.
Wished (& could see also) if could show by some simple means (like, printf()) the way in which the malloc() returns memory space, and all these are connected in one array; for some given input, say 'ABCD'.
Added debug-prints into stmt_list,
now here I idendeted the debug lines to show to recursion:
Code:
stmt_list: input='ABCD'
stmt_list: input='BCD'
stmt_list: input='CD'
stmt_list: input='D'
stmt_list: input='D', first='D' rest=''(array of 0 characters)
now I'll merge them into another array of 1 characters
the result is 'D'
stmt_list: input='CD', first='C' rest='D'(array of 1 characters)
now I'll merge them into another array of 2 characters
the result is 'CD'
stmt_list: input='BCD', first='B' rest='CD'(array of 2 characters)
now I'll merge them into another array of 3 characters
the result is 'BCD'
stmt_list: input='ABCD', first='A' rest='BCD'(array of 3 characters)
now I'll merge them into another array of 4 characters
the result is 'ABCD'
ABCD interpreted as left associative: (((A).B).C).D
ABCD interpreted as right associative: A.(B.(C.(D)))
Also remember the terminating zero: is marks the end of the characters. That's why we allocate one more byte every time.
Indeed, it is universally explained in parsing literature. Have you read those and tried to understand what they are telling you? How would another example from myself be any different? See post #41, from which:
But this problem, like so many in the parsing realm, is inherent in the concept of top-down parsing, not just an implementation detail. As such, it is best understood conceptually rather than as a code example.
Top-down parsing begins with the input string and the start symbol, then performs predictions by replacing the leading non-terminal in each alternative until the left-most symbol in each prediction is a terminal. At that point it matches those terminals with the left-most end of the (remaining) input string, removes those that match into the parse tree and discards the rest of the predictions, then continues with the next leading non-terminals until it reaches the end of the input string.
The problem with left-recursion in this scenario is that you can never reach a set of predictions in which all left-most symbols are terminals. For example (adapted from Dick Grune):
Code:
Grammar: S -> Sb | a
Input string: ab
Deriving predictions...
Parse Tree | Prediction
_______________|________________
| S
...
S | Sb
S | a
...
SS | Sbb
SS | ab
S | a
...
SSS | Sbbb
SS | ab
S | a
...
ad infinitum...
You can never get rid of the leading non-terminal in all predictions, so you can never move to the match phase.
The infinite progression is present in the concept of a top-down parser, not only recursive implementations where it manifests as infinite recursion.
Trying to see it as code alone will not lead to understanding.
Please tell how to interpret the line #22:
Code:
if((parseptr-parse)>=(MAXPARSE - 1))
and the initialization condition, in the for loop, on line #70:
That initializes the pointer to the end of the parse string. Should be one less actually, but writing the NULL terminator has null effect so no harm done, and is safe for zero length string (indx was originally an int index into array, modified for posting here, oops).
Naive top-down recursive parser cannot handle left recursion ( e.g. A -> A - B ), because if it tried, the recursion would never end.
A real-life program can work on modified rules ( e.g. A -> B - A ), create some data-structure (typically a tree) as a temporay result, then transform the data-structure to get the correct representation, e.g:
That initializes the pointer to the end of the parse string. Should be one less actually, but writing the NULL terminator has null effect so no harm done, and is safe for zero length string (indx was originally an int index into array, modified for posting here, oops).
Okay, the variable: parse, would give the start location of the character array. Would need to add just: len(parse)-1.
Though am unclear, what you mean by : writing the NULL terminator has null effect...
Request some details on your statement regarding the insufficient complexity of the program, in order to show the infinite loop problem, for left-recursive grammar.
This can be used by me to elaborate to class as well, the need for the given program.
Am in process of understanding code, so if you feel that would acquire the knowledge on understanding the program, then no issues; though see no hope for that.
Also, why the function prototype declaration on line #32, 33, 34 is repeated on line #44, 45, 46; is unclear.
Now back to your perpetual request: I most certainly won't add infinite recursion into the program, do that yourself. You have been given examples, e.g. in post #45
Please learn the current state of the program by heart.
Updated example in blog post renames loop pointer and corrects offset.
Quote:
Originally Posted by ajiten
Okay, the variable: parse, would give the start location of the character array. Would need to add just: len(parse)-1.
Though am unclear, what you mean by : writing the NULL terminator has null effect...
It doesn't support signs yet (+3, -5), which might also be interesting, e.g wether -3^2 is (-3)^2 or -(3^2) (I support the latter, but have heard arguments about it.)
Now back to your perpetual request: I most certainly won't add infinite recursion into the program, do that yourself. You have been given examples, e.g. in post #45
Please learn the current state of the program by heart.
Sorry, due to internal examn. was too busy for few days, as couldn't adjust to different tt.
Please tell why the struct LexData, is empty, as how an empty datatype can be a parameter, as well as a return data type, as on the lines #40-42.
Have read here, but couldn't find something relevant. Any hint will work, in kicking in the right direction.
This is called `opaque type`. It's not important in this little program, but in multi-file projects it is useful: implementation can be separated from the specification.
Line 38 declares 'struct LexData' then the definition is in lines 434-440
In a bigger project, lines 415-501 would be in a separated file called `lex.c`
This is called `opaque type`. It's not important in this little program, but in multi-file projects it is useful: implementation can be separated from the specification.
Line 38 declares 'struct LexData' then the definition is in lines 434-440
In a bigger project, lines 415-501 would be in a separated file called `lex.c`
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.