<module>:
    unit <ident> ; <module-body>

<module-body>:
    /* nothing */
    interface <interface-clause-list> <module-body>
    implementation <implementation-clause-list> <module-body>

<inteface-clause-list>:
    /* nothing */
    <interface-clause>
    <interface-clause> <interface-clause-list>

<inteface-clause>:
    <uses-clause>
    <const-def>
    <type-def>
    <var-def>
    <function-decl>

<implementation-clause-list>:
    /* nothing */
    <implementation-clause>
    <implementation-clause> <implementation-clause-list>

<implementation-clause>:
    <uses-clause>
    <const-def>
    <type-def>
    <var-def>
    <function-decl>
    <function-def>

<uses-clause>:
    uses <ident-list> ;

<const-def>:
    const <ident> = <constant value> ;    /* auto-typed */
    const <ident> : <type> = <constant value> ;

<type-def>:
    type <ident> = <type> ;

<var-def>:
    var <ident-list> : <type> ;

<novar-def>:
    <ident-list> : <type> ;

<ident-list>:
    <ident>
    <ident> <ident-list>

<function-decl>:
    function <ident> : <type> ;
    function <ident> ( <param-list> ) : <type> ;

<function-def>:
    <function-decl> <block>

<block>:
    { <statement-list> }

<type>:
    <simple-type>
    class { <class-innards> }
    struct { <struct-innards> }
    union { <struct-innards> }
    enum { <enum-innards> }
    pointer to <type>
    array [ <opt-dim-list> ] of <type>
    set of <type>
    function ( <param-list> ) : <type>

<simple-type>:
    void
    bool
    char
    uchar
    short
    ushort
    long
    ulong
    real
    string
    label

<class-innards>:
    /* nothing */
    private : <class-innards>
    public : <class-innards>
    <const-def>  <class-innards>
    <type-def>   <class-innards>
    <novar-def>  <class-innards>
    <function-decl>  <class-innards>  /* A class method */

<struct-innards>:
    /* nothing */
    <novar-def> <struct-innards>

<enum-innards>:
    <enum-ident>
    <enum-ident> , <enum-innards>

<enum-ident>:
    <ident>
    <ident> = <const-expr> 

<param-list>:
    <ident-list> : <type>
    <ident-list> : <type> ; <param-list>

<opt-dim-list>:
    /* nothing */
    <dim-list>

<dim-list>:
    <int-range>
    <intConst>        /* range: 0..<intConst>-1 */
    <int-range> , <dim-list>
    <intConst> , <dim-list>

<int-range>:
    <intConst> .. <intConst>

<intConst>:
    <integer>
    <enum const>
    <const var>        // defined with 'const' earlier

<statement-list>:
    /* nothing */
    <labeled statement> <statement-list>

<labeled statement>:
    <statement>
    label <ident> : <labeled-statment>

<statement>:
    <const-def>
    <type-def>
    <var-def>
    <label-fwd-decl>
    <goto statement>
    <with statement>
    <if-statement>
    <switch statement>
    <for statement>
    <while statement>
    <do-while statement>
    <expr> ;

<label-fwd-decl>:
    label <ident> ;

<goto statement>:
    break ;
    break <label> ;
    continue ;
    continue <label> ;
    goto <label> ;

<with statement>:
    with <expr> do <block>
    
<if-statement>:
    if ( <expr> ) <block>
    if ( <expr> ) <block> else <block>

<switch statement>:
    switch ( <expr> ) { <switch-innards> }

<switch-innards>:
    /* nothing */
    <case-label-list> <block> <switch-innards>

<case-label-list>:
    <case-label>
    <case-label> <case-label-list>

<case-label>:
    default :
    case <constant expr> :
    case <constant expr-list> :
    case <constant expr> .. <constant expr> :

<for statement>:
    for ( <expr>; <expr>; <expr> ) <block>

<while statement>:
    while ( <expr> ) <block>

<do-while statement>:
    do <block> while ( <expr> )

<expr>:
    <inum>
    <rnum>
    <literal-char>
    <literal-string>
    <ident>
    <expr> <binOp> <expr>
    <unaryOp> <expr>
    @ <expr>
    <expr> ^
    <expr> . <ident>
    <expr> [ <expr> ]
    ( <expr> )
    <fncCall>
    new <type>
    delete <expr>
    new [ <expr> ] <type>
    delete [] <expr>
    <expr> ++
    <expr> --
    ++ <expr>
    -- <expr>

<const-expr>:
    <inum>
    <rnum>
    <literal-char>
    <literal-string>
    <const-ident>
    <const-expr> <binOp> <const-expr>
    <unaryOp> <const-expr>
    @ <const-expr>
    <const-expr> ^
    <const-expr> . <ident>
    <const-expr> [ <const-expr> ]
    ( <const-expr> )

<fncCall>:
    <func-ident>
    <func-ident> ( <expr-list> )

<expr-list>:
    <expr>
    <expr> , <expr-list>

---------
Precedence:
    Literals        17
    x[y]            17   left-ass
    f()             17   left-ass
    .               17   left-ass
    ++, --  (post)  17   left-ass

    ++, -- (pre)    15   right
    sizeof          15   right
    ~               15   right
    not             15   right
    - + (unary)     15   right
    @               15   right
    ^               15   right

    * / %           13   left
    + - (binary)    12   left
    << >>           11   left

    < > <= >=       10   left
    == !=            9   left

    &                8   left
    # (bit-xor)      7   left
    |                6   left

    and              5   left
    xor              4   left
    or               3   left

    = += -= *=...    2   right

<expr>:
    <assign-expr>

<assign-expr>:
    <or-expr>        /* Can derive unary_expr! */
    <unary-expr> <assignOp> <assign-expr>

    This is the reason why pascal does not allow assignment anywhere?
    It is not LL(1), as <or-expr> can derive <unary-expr>?

// What would this imply?
<assign-expr>:
    <or-expr>        /* Can derive unary_expr! */
    <or-expr> <assignOp> <assign-expr>

    x or y = x or m = 5;

    (x or y) = ((x or m) = 5)

    Then, we could independently check that left-argument was an l-value.
----------------
<or-expr>:
    <and-expr> <or-expr-LR>

<or-expr-LR>:
    /* nothing */
    or <or-expr-LR>
    xor <or-expr-LR>

<and-expr>:
    <bitor-expr> <and-expr-LR>

<and-expr-LR>:
    /* nothing */
    and <and-expr-LR>

<bitor-expr>:
    <bitxor-expr> <bitor-expr-LR>

<bitor-expr-LR>:
    /* nothing */
    | <bitor-expr-LR>

<bitxor-expr>:
    <bitand-expr>
    <bitxor-expr> # <bitand-expr>

<bitand-expr>:
    <equal-expr>
    <bitand-expr> & <equal-expr>

<equal-expr>:
    <rel-expr>
    <equal-expr> <equalOp> <rel-expr>

<rel-expr>:
    <shift-expr>
    <rel-expr> <relOp> <shift-expr>

<shift-expr>:
    <add-expr>
    <shift-expr> <shiftOp> <add-expr>

<add-expr>:
    <mult-expr>
    <add-expr> <addOp> <mult-expr>

<mult-expr>:
    <unary-expr>
    <mult-expr> <multOp> <unary-expr>

<unary-expr>:
    <sizeof-expr>
    - <unary-expr>
    + <unary-expr>
    not <unary-expr>
    ~ <unary-expr>
    @ <unary-expr>
    ++ <unary-expr>
    -- <unary-expr>
    <postfix-expr>

<postfix-expr>:
    <primary-expr>
    <postfix-expr> [ <expr> ]
    <postfix-expr> . <ident>
    <postfix-expr> ( <expr-list> )
    <postfix-expr> ++
    <postfix-expr> --
    <postfix-expr> ^

<sizeof-expr>:
    sizeof ( <type> )
    sizeof ( <expr> )

<primary-expr>:
    <ident>
    <constant>
    ( <expr> )

------
    <expr> <binOp> <expr>
    <unaryOp> <expr>
    @ <expr>
    <expr> ^
    <expr> . <ident>
    <expr> [ <expr> ]
    ( <expr> )
    <fncCall>
    new <type>
    delete <expr>
    new [ <expr> ] <type>
    delete [] <expr>
    <expr> ++
    <expr> --
    ++ <expr>
    -- <expr>

Go back up to the Meme page.