LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 04-07-2011, 03:39 PM   #1
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
Removing Left Recursion


First of all, I'm still a but confused about the standard way of removing it for left-associative operators:

http://stackoverflow.com/questions/2...left-recursion

Especially about how to construct an AST from it by executing a peice of code for every nonterminal matched. And I'm still not totally convinced that it will be left-associative, I just barely understand it.

Also, how would you remove left-recursion for something like this:

Code:
expr ::= expr "(" param_list ")"
       | other stuff...
?
 
Old 04-09-2011, 12:14 AM   #2
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by MTK358 View Post
First of all, I'm still a but confused about the standard way of removing it for left-associative operators:

http://stackoverflow.com/questions/2...left-recursion

Especially about how to construct an AST from it by executing a peice of code for every nonterminal matched. And I'm still not totally convinced that it will be left-associative, I just barely understand it.

Also, how would you remove left-recursion for something like this:

Code:
expr ::= expr "(" param_list ")"
       | other stuff...
?
Back to the past:

Code:
no_parenthesis_expr OPTIONALLY_FOLLOWED_BY arg_list_in_parenthesis
.
 
1 members found this post helpful.
Old 04-09-2011, 07:21 AM   #3
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443

Original Poster
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
Quote:
Originally Posted by Sergei Steshenko View Post
Back to the past:

Code:
no_parenthesis_expr OPTIONALLY_FOLLOWED_BY arg_list_in_parenthesis
.
That kind of makes sense, but what about calling the result of a function, like this:

Code:
my_function()()
?
 
Old 04-09-2011, 09:31 AM   #4
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by MTK358 View Post
That kind of makes sense, but what about calling the result of a function, like this:

Code:
my_function()()
?
Regarding the items in red - how about

Code:
list_of_arg_lists_in_parenthesis
?

And since the suggested construct is list, the list itself doesn't require recursion, but, of course, the list elements do.

For lists in my parser-generator engine I had a REPEATED_ITEMS construct whose members were other language items, i.e. for my engine I would write

Code:
REPEATED_ITEMS(arg_list_in_parenthesis)
.
 
Old 04-09-2011, 09:42 AM   #5
wizard211990
LQ Newbie
 
Registered: Apr 2011
Posts: 9

Rep: Reputation: 0
Smile

Quote:
Originally Posted by Sergei Steshenko View Post
Regarding the items in red - how about

Code:
list_of_arg_lists_in_parenthesis
?

And since the suggested construct is list, the list itself doesn't require recursion, but, of course, the list elements do.

For lists in my parser-generator engine I had a REPEATED_ITEMS construct whose members were other language items, i.e. for my engine I would write

Code:
REPEATED_ITEMS(arg_list_in_parenthesis)
.
Yes!!!
 
0 members found this post helpful.
Old 04-09-2011, 09:44 AM   #6
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443

Original Poster
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
Maybe it's OK, but it doesn't follow the way the language is supposed to work (any expression can be called, including but not limited to functions).

I guess you can make the list_of_arg_lists make an AST that calls the expr_without_parens and then calls the result of the previous call with the args in the next list, but it seems like there should be a better way.

---------- Post added 2011-04-09 at 10:45 ----------

Quote:
Originally Posted by wizard211990 View Post
Yes!!!
What do you mean?
 
Old 04-09-2011, 10:51 AM   #7
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by MTK358 View Post
Maybe it's OK, but it doesn't follow the way the language is supposed to work (any expression can be called, including but not limited to functions).
...
And how does my proposed solution interfere with "the way the language is supposed to work" ?

Or, in other words, what prevents nodes in the AST from knowing who their parents are ?
 
Old 04-09-2011, 11:48 AM   #8
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443

Original Poster
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
Quote:
Originally Posted by Sergei Steshenko View Post
And how does my proposed solution interfere with "the way the language is supposed to work" ?

Or, in other words, what prevents nodes in the AST from knowing who their parents are ?
I thought there could be a more elegant way. Anyway, is this right:

Code:
call_param_list_list ::= OPAREN call_param CPAREN {OPAREN call_param CPAREN}

call ::= no_call_expr call_param_list_list

expr ::= no_call_expr
       | call
       
no_call_expr ::= <other stuff>
 
Old 05-11-2011, 02:13 PM   #9
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443

Original Poster
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
This reply is a bit late since I figured it out a long time ago, but I thought I would say how I did it:

I used loops instead of recursion. It's much simpler, very intuitive, and infix operators can easily be made left-associative. The only disadvantage that I see is that it's impossible to describe in BNF.

Here's an example:

Code:
expr = expr2 (("+" | "-") expr2)*
expr2 = expr3 (("*" | "/") expr3)*
expr3 = expr4 ("^" expr3)?
expr4 = (NUMBER | "(" expr ")")
expr and expr2 are left-associative, and expr3 is right-associative.


And it's very nice not to depend on Lex/YACC (or any other parser-generator tool, for that matter) anymore. It's much easier to interface to, gives detailed syntax error information, and it's designed so that multiple instances of it can run at the same time in different threads if I ever need that. And of course, I got a much better understanding of parsers.

Last edited by MTK358; 05-11-2011 at 02:25 PM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
manually removing the .vdi files left over after removing VirtualBox adityavpratap Linux - General 2 10-24-2010 12:04 PM
PowerDNS recursion rozilla Linux - Server 1 10-25-2008 06:25 PM
Recursion and its culture Bassy General 3 06-19-2007 04:39 PM
Recursion in C hubabuba Programming 12 10-03-2005 07:46 AM
tar: '--no-recursion' option doesn't prevent recursion Earl Parker II Slackware 12 08-17-2004 02:49 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 05:31 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration