Skip to content
Marios Papachristou edited this page Apr 18, 2020 · 1 revision

Parser

The second layer of the compiler front-end is the parser module. The parser module is responsible for processing the tokens supplied by the lexer and build the syntax tree. Each rule, which has a BNF form of

<non_terminal> ::= rule

is represented (in SLY) with the following

class MyParser(sly.Parser):

	@_('rule')
	def non_terminal(self, p):
		return AST_Node(args)

The @_ decorator specifies the rule in a string and then, the parsed object is stored in p. SLY performs LALR(1) parsing under the hood for parsing the input. So the program

program collatz;

var x : integer;

begin
  x := 6;
  while x > 1 do
  begin
    writeInteger(x);
    if x mod 2 = 0 then x := x div 2
    else x := 3 * x + 1;
  end;

end.

Translates to the following AST

$ pclc.py examples/pos/collatz.pcl --pipeline lex parse pprint | grep class
<class 'pcl.ast.Program'>
 <class 'pcl.ast.Body'>
  <class 'pcl.ast.VarList'>
    <class 'pcl.ast.Var'>
      <class 'pcl.ast.Type'>
  <class 'pcl.ast.Block'>
    <class 'pcl.ast.SetExpression'>
      <class 'pcl.ast.NameLValue'>
      <class 'pcl.ast.IntegerConst'>
    <class 'pcl.ast.While'>
      <class 'pcl.ast.Block'>
        <class 'pcl.ast.Call'>
          <class 'pcl.ast.NameLValue'>
        <class 'pcl.ast.If'>
          <class 'pcl.ast.SetExpression'>
            <class 'pcl.ast.NameLValue'>
            <class 'pcl.ast.ArOp'>
              <class 'pcl.ast.NameLValue'>
              <class 'pcl.ast.IntegerConst'>
          <class 'pcl.ast.CompOp'>
            <class 'pcl.ast.ArOp'>
              <class 'pcl.ast.NameLValue'>
              <class 'pcl.ast.IntegerConst'>
            <class 'pcl.ast.IntegerConst'>
          <class 'pcl.ast.SetExpression'>
            <class 'pcl.ast.NameLValue'>
            <class 'pcl.ast.ArOp'>
              <class 'pcl.ast.ArOp'>
                <class 'pcl.ast.IntegerConst'>
                <class 'pcl.ast.NameLValue'>
              <class 'pcl.ast.IntegerConst'>
        <class 'pcl.ast.Empty'>
      <class 'pcl.ast.CompOp'>
        <class 'pcl.ast.NameLValue'>
        <class 'pcl.ast.IntegerConst'>
    <class 'pcl.ast.Empty'>

Where pcl.ast.* are the the various AST nodes. We have followed an object oriented design, and invoke inheritance in order to develop a meaningful and elegant AST.

Clone this wiki locally