Re: Parsing w/ operator precedence

Chris F Clark <cfc@world.std.com>24 Jan 2002 15:02:18 -0500

From comp.compilers

Related articles
Re: Parsing w/ operator precedence cfc@world.std.com (Chris F Clark) (2002-01-24)
RE: Parsing w/ operator precedence qjackson@shaw.ca (Quinn Tyler Jackson) (2002-10-18)
| List of all articles for this month |

 From: Chris F Clark Newsgroups: comp.theory,comp.lang.c++,comp.compilers Date: 24 Jan 2002 15:02:18 -0500 Organization: The World Public Access UNIX, Brookline, MA References: Keywords: parse, LL(1) Posted-Date: 24 Jan 2002 15:02:18 EST

What you are trying to do is called writing a "recursive descent
parser". It is not as hard as it sounds, given a proper LL1 grammar
for the expressions you wish to parse. However, writing a proper LL1
grammar is somewhat difficult until you've versed yourself in the
theory. The naive grammar one naturally writes to express expressions
is not an LL1 grammar. The problems you are encountering are because
you are attempting to start from a naive grammar.

The naive grammar looks something like (in Yacc notation):
E: E * E; // E is expression
E: E / E;
E: E + E;
E: E - E;
E: ( E );
E: number;

A proper LL1 grammar looks more like:
E: F E1; // F is factor
E1: * E; // E1 is "rest of expression"
E1: / E;
E1: ; // this is an empty rule
// for the case when nothing follows the factor
F: T F1; // T is term
F1: + F; // F1 is "rest of factor"
F1: - F;
F1: ;
T: ( E );
T: number;

The result is five mutually recursive routines (E, E1, F, F1, and T)
that create the parse tree. Note the resulting parse tree does not
look like the one that matches the naive grammar. Note, I will not go
into more detail, because I am not an LL parsing expert.

I would recommend you find yourself a textbook on compiler
construction that covers the topic. I'm certain you can find some
recommendations if you look at the comp.compilers FAQ. Most parsing
questions are best addressed in that newsgroup.

Also, aside from the learning experience, I do not recommend
writing parsers by hand. It seems like a trivial task, but the
resulting parsers often fail to implement the language the author
intended.

Finally, if you want a parse tree that matches your naive grammar, I
would recommend you use an LR parser generator. Most of them
(e.g. all the yacc derivatives), allow the naive grammar when
accompanied by "precedence" directives.

Hope this helps,
-Chris

*****************************************************************************
Chris Clark Internet : compres@world.std.com
Compiler Resources, Inc. Web Site : http://world.std.com/~compres
3 Proctor Street voice : (508) 435-5016
Hopkinton, MA 01748 USA fax : (508) 435-4847 (24 hours)
------------------------------------------------------------------------------

Post a followup to this message