Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive descent parser questions

I have two questions about how to write a recursive descent parser:

The first is what when you have a nonterminal that can match one of a few different nonterminals? How do you check which way is correct?

Second, how do you build an AST? Using YACC, I can just write a piece of code to execute for every instance of a nonterminal and it has special variables which refer to the "values" of the rules. How do you do a similar thing in a recursive descent parser?

like image 411
mtk358 Avatar asked Mar 25 '11 18:03

mtk358


People also ask

What is recursive descent parser example?

It is a kind of Top-Down Parser. A top-down parser builds the parse tree from the top to down, starting with the start non-terminal.

What is the problem with recursive descent parser?

The main limitation of recursive descent parsing (and top-down parsing algorithms in general) is that they only work on grammars with certain properties. For example, if a grammar contains any left recursion, recursive descent parsing doesn't work.

Is recursive descent parser?

Recursive descent is a top-down parsing technique that constructs the parse tree from the top and the input is read from left to right. It uses procedures for every terminal and non- terminal entity. This parsing technique recursively parses the input to make a parse tree, which may or may not require back-tracking.

What language does this recursive descent parser recognize?

According to "Recursive descent parser" on Wikipedia, recursive descent without backtracking (a.k.a. predictive parsing) is only possible for LL(k) grammars.


2 Answers

  1. You try them in order, then backtrack on failure. Or you prove that your language is in LL(k) and look at most k symbols ahead.
  2. For each successful parse of a rule, you construct an object from the result of subrules.

E.g.,

class ASTNode {
  public:
    virtual int eval() = 0;
    virtual ~ASTNode() = 0;
};

// construct this when parsing an integer literal
class Value : ASTNode {
    int v;
  public:
    Value(int v_) : v(v_) {}
    virtual int eval() { return v; }
    virtual ~Value() {}
};

// construct this when parsing "x+y"
class Addition : ASTNode {
    ASTNode *left, *right;
  public:
    Addition(ASTNode *l, ASTNode *r) : left(l), right(r) {}
    virtual int eval() { return l->eval() + r->eval(); }
    virtual ~Addition() { delete left; delete right; }
};
like image 169
Fred Foo Avatar answered Oct 16 '22 08:10

Fred Foo


Or a leasson in how to give yourself a stroke in one easy leasson.

The first is what when you have a nonterminal that can match one of a few different nonterminals? How do you check which way is correct?

You need to look ahead in the stream and make a decision. Its hard to do backtracking on a RDC.

An easier solution is to design your grammar so that it does not need to look ahead (hard).

Second, how do you build an AST?

The return value from the function call is the tree for everything that was parsed by the call. You wrap all the sub calls into another dynamically allocated object and return that.

like image 26
Martin York Avatar answered Oct 16 '22 09:10

Martin York