Recursive descent parser: Difference between revisions

Content deleted Content added
Removed superfluous Pascal example, which, as a direct port of the C example, is very long without adding information.
Line 179:
expect(period);
}
</source>
 
===Pascal implementation===
 
What follows is an implementation of a recursive descent parser for the above language in [[Pascal (programming language)|Pascal]]. The parser reads in source code, and exits with an error message if the code fails to parse, exiting silently if the code parses correctly.
 
Notice how closely the predictive parser below mirrors the grammar above. There is a procedure for each nonterminal in the grammar. Parsing descends in a top-down manner, until the final nonterminal has been processed. The program fragment depends on a global variable, ''sym'', which contains the current symbol from the input, and the function ''nextsym'', which updates ''sym'' when called.
 
The implementations of the functions ''nextsym'' and ''error'' are omitted for simplicity.
 
<source lang="pascal">
// Modern Pascal implementation (www.ModernPascal.com)
// C example ported to Pascal by Ozz Nixon
 
{$S-}
 
type
SYMBOL = (ident, number, lparen, rparen, times, slash, plus,
minus, eql, neq, lss, leq, gtr, geq, callsym, beginsym, semicolon,
endsym, ifsym, whilesym, becomes, thensym, dosym, constsym, comma,
varsym, procsym, period, oddsym);
 
var
sym:SYMBOL;
 
procedure expression; forward;
 
procedure nextsym;
begin
// you implement //
end;
 
procedure error(const msg:String);
begin
// you implement //
end;
 
function accept(S:Symbol):boolean;
begin
if sym=s then begin
nextsym();
Result:=True;
end
else Result:=False;
end;
 
function expect(S:Symbol):boolean;
begin
Result:=accept(s);
if not result then error('Expect: unexpected symbol');
end;
 
procedure factor;
begin
if (accept(ident)) then begin
//
end
else if (accept(number)) then begin
//
end
else if (accept(lparen)) then begin
expression();
expect(rparen);
end
else begin
error('factor: syntax error');
nextsym();
end;
end;
 
procedure term;
begin
factor();
while (sym=times) or (sym=slash) do begin
nextsym();
factor();
end;
end;
 
procedure expression;
begin
if (sym=plus) or (sym=minus) then nextsym();
term();
while (sym=plus) or (sym=minus) do begin
nextsym();
term();
end;
end;
 
procedure condition;
begin
if (accept(oddsym)) then begin
expression();
end
else begin
expression();
if (sym=eql) or (sym=neq) or (sym=lss) or (sym=leq) or (sym=gtr) or (sym=geq) then begin
nextsym();
expression();
end
else begin
error('condition: invalid operator');
nextsym();
end;
end;
end;
 
procedure statement;
begin
if (accept(ident)) then begin
expect(becomes);
expression();
end
else if (accept(callsym)) then begin
expect(ident);
end
else if (accept(beginsym)) then begin
repeat
statement();
until not (accept(semicolon));
expect(endsym);
end
else if (accept(ifsym)) then begin
condition();
expect(thensym);
statement();
end
else if (accept(whilesym)) then begin
condition();
expect(dosym);
statement();
end
else begin
error('statement: syntax error');
nextsym();
end;
end;
 
procedure block;
begin
if (accept(constsym)) then begin
repeat
expect(ident);
expect(eql);
expect(number);
until not (accept(comma));
expect(semicolon);
end;
if (accept(varsym)) then begin
repeat
expect(ident);
until not (accept(comma));
expect(semicolon);
end;
while (accept(procsym)) do begin
expect(ident);
expect(semicolon);
block();
expect(semicolon);
end;
statement();
end;
 
begin
nextsym();
block();
expect(period);
end;
</source>