===
Variables
===

var
  a: b;
  a, b: c;
  a: b = c;

---

(root
  (declVars
    (kVar)
    (declVar (identifier)
      (type (typeref (identifier))))
    (declVar
      (identifier)
      (identifier)
      (type (typeref (identifier))))
    (declVar
      (identifier)
      (type (typeref (identifier)))
      (defaultValue (kEq) (identifier)))))

===
Constants
===

const
  a = b;
  a: b = c;

resourcestring
  a = b;

---

(root
  (declConsts
    (kConst)
    (declConst (identifier)
      (defaultValue (kEq) (identifier)))
    (declConst
      (identifier)
      (type (typeref (identifier)))
      (defaultValue (kEq) (identifier))))
  (declConsts
    (kResourcestring)
    (declConst (identifier)
      (defaultValue (kEq) (identifier)))))

===
Typedefs
===

type
  a = b;
  a = (b, c);
  a = array of b;
  a = array [0..1] of b;
  a = set of b;
  a = set of (b, c);
  a = string[1];
  a = class;
  a = class(b);
  a = class of b;
  a = interface;
  a = interface(b);
  a = file;
  a = file of b;

---

(root
  (declTypes
    (kType)
    (declType (identifier) (kEq)
      (type (typeref (identifier))))
    (declType (identifier) (kEq)
      (type
        (declEnum
          (declEnumValue (identifier))
          (declEnumValue (identifier)))))
    (declType (identifier) (kEq)
      (type
        (declArray (kArray) (kOf) (type (typeref (identifier))))))
    (declType (identifier) (kEq)
      (type
        (declArray (kArray) (range (literalNumber) (literalNumber)) (kOf)
          (type
            (typeref (identifier))))))
    (declType (identifier) (kEq)
      (type
        (declSet (kSet) (kOf)
          (type
            (typeref (identifier))))))
    (declType (identifier) (kEq)
      (type
        (declSet (kSet) (kOf)
          (type
            (declEnum
              (declEnumValue (identifier))
              (declEnumValue (identifier)))))))
    (declType (identifier) (kEq)
      (type
        (declString (kString) (literalNumber))))
    (declType (identifier) (kEq)
      (declClass (kClass)))
    (declType (identifier) (kEq)
      (declClass (kClass)
        (typeref (identifier))))
    (declType (identifier) (kEq)
      (type
        (declMetaClass (kClass) (kOf) (typeref (identifier)))))
    (declType (identifier) (kEq)
      (declIntf (kInterface)))
    (declType (identifier) (kEq)
      (declIntf (kInterface)
        (typeref (identifier))))
    (declType (identifier) (kEq)
      (type
        (declFile (kFile))))
    (declType (identifier) (kEq)
      (type
        (declFile (kFile) (kOf)
          (type
            (typeref (identifier))))))))


===
Procedure references
===

type
  a = procedure;
  a = procedure(b: c);
  a = function: b;
  a = function(b: c): d;

  a = procedure of object;
  a = procedure(b:c) of object;
  a = function: b of object;
  a = function(b: c): d of object;

---

(root
  (declTypes (kType)
    (declType (identifier) (kEq)
      (type
        (declProcRef (kProcedure))))
    (declType (identifier) (kEq)
      (type
        (declProcRef (kProcedure)
          (declArgs
            (declArg
              (identifier)
              (type (typeref (identifier))))))))
    (declType (identifier) (kEq)
      (type
        (declProcRef (kFunction)
          (typeref (identifier)))))
    (declType (identifier) (kEq)
      (type
        (declProcRef (kFunction)
          (declArgs
            (declArg
              (identifier)
              (type (typeref (identifier)))))
          (typeref (identifier)))))
    (declType (identifier) (kEq)
      (type
        (declProcRef (kProcedure) (kOf) (kObject))))
    (declType (identifier) (kEq)
      (type
        (declProcRef (kProcedure)
          (declArgs
            (declArg
              (identifier)
              (type (typeref (identifier)))))
          (kOf) (kObject))))
    (declType (identifier) (kEq)
      (type
        (declProcRef (kFunction)
          (typeref (identifier))
          (kOf) (kObject))))
    (declType (identifier) (kEq)
      (type
        (declProcRef (kFunction)
          (declArgs
            (declArg
              (identifier)
              (type (typeref (identifier)))))
          (typeref (identifier))
          (kOf) (kObject))))))

===
Forward declarations
===

procedure a; forward;
procedure a(b: c); forward;
procedure a(b, c: d; e: f); forward;

function a: b; forward;
function a(b: c): d; forward;
function a(b, c: d; e: f): g; forward;

---

(root
  (declProc (kProcedure) (identifier) (kForward))
  (declProc (kProcedure) (identifier)
    (declArgs
      (declArg (identifier) (type (typeref (identifier)))))
    (kForward))
  (declProc (kProcedure) (identifier)
    (declArgs
      (declArg (identifier) (identifier) (type (typeref (identifier))))
      (declArg (identifier) (type (typeref (identifier)))))
    (kForward))

  (declProc (kFunction) (identifier) (typeref (identifier)) (kForward))
  (declProc (kFunction) (identifier)
    (declArgs
      (declArg (identifier) (type (typeref (identifier)))))
    (typeref (identifier))
    (kForward))
  (declProc (kFunction) (identifier)
    (declArgs
      (declArg (identifier) (identifier) (type (typeref (identifier))))
      (declArg (identifier) (type (typeref (identifier)))))
    (typeref (identifier))
    (kForward)))


===
Structures
===

type
  a = class
  end;

  a = record
  end;

  a = object
  end;

  a = interface
  end;

  a = interface
    ['3d298d62-6d73-46a9-8267-24e4b3176cec']
  end;

---

(root
  (declTypes (kType)
    (declType (identifier) (kEq) (declClass (kClass) (kEnd)))
    (declType (identifier) (kEq) (declClass (kRecord) (kEnd)))
    (declType (identifier) (kEq) (declClass (kObject) (kEnd)))
    (declType (identifier) (kEq) (declIntf (kInterface) (kEnd)))
    (declType (identifier) (kEq) (declIntf (kInterface) (guid (literalString)) (kEnd)))))


===
Inheritance
===

type
  a = class(a,b)
  end;

  a = interface(a,b)
  end;

---

(root
   (declTypes (kType)
     (declType (identifier) (kEq)
       (declClass (kClass)
         (typeref (identifier))
         (typeref (identifier))
         (kEnd)))
     (declType (identifier) (kEq)
       (declIntf (kInterface)
         (typeref (identifier))
         (typeref (identifier))
         (kEnd)))))
===
Members
===

type
  a = class
    b, c: d;
    e: f;
    constructor d;
    destructor e;
    procedure f;
    function g: h;
  end;

---

(root
  (declTypes (kType)
    (declType (identifier) (kEq)
      (declClass (kClass)
        (declField (identifier) (identifier) (type (typeref (identifier))))
        (declField (identifier) (type (typeref (identifier))))
        (declProc (kConstructor) (identifier))
        (declProc (kDestructor) (identifier))
        (declProc (kProcedure) (identifier))
        (declProc (kFunction) (identifier) (typeref (identifier)))
        (kEnd)))))

===
Visibility
===

type
  a = class
    c: d;
    procedure e;
  private
    f: g;
    procedure h;
  protected
    i: j;
    procedure k;
  public
    l: m;
    procedure n;
  published
    o: p;
    procedure q;
  end;

  a = class
  strict private
  private
  strict protected
  protected
  public
  published
  end;

---

(root
  (declTypes
    (kType)
    (declType (identifier) (kEq)
      (declClass (kClass)
        (declField (identifier) (type (typeref (identifier))))
        (declProc (kProcedure) (identifier))
        (declSection (kPrivate)
          (declField (identifier) (type (typeref (identifier))))
          (declProc (kProcedure) (identifier)))
        (declSection (kProtected)
          (declField (identifier) (type (typeref (identifier))))
          (declProc (kProcedure) (identifier)))
        (declSection (kPublic)
          (declField (identifier) (type (typeref (identifier))))
          (declProc (kProcedure) (identifier)))
        (declSection (kPublished)
          (declField (identifier) (type (typeref (identifier))))
          (declProc (kProcedure) (identifier)))
        (kEnd)))
    (declType (identifier) (kEq)
      (declClass (kClass)
        (declSection (kStrict) (kPrivate))
        (declSection (kPrivate))
        (declSection (kStrict) (kProtected))
        (declSection (kProtected))
        (declSection (kPublic))
        (declSection (kPublished))
        (kEnd)))))

===
Nested declarations
===

type
  a = class
  type
    b = class
    end;
    c = d;
  var
    e: f;
  const
    g = h;
  public
    constructor i;
  end;

---

(root
  (declTypes (kType)
    (declType (identifier) (kEq)
      (declClass (kClass)
        (declTypes (kType)
          (declType (identifier) (kEq)
            (declClass
              (kClass)
              (kEnd)))
          (declType (identifier) (kEq)
            (type (typeref (identifier)))))
        (declVars (kVar)
          (declVar (identifier) (type (typeref (identifier)))))
        (declConsts (kConst)
          (declConst (identifier) (defaultValue (kEq) (identifier))))
        (declSection (kPublic)
          (declProc (kConstructor) (identifier)))
        (kEnd)))))

===
Class members
===

type
  a = class
    class procedure b;
    class var
      c: d;
      e: f;
  end;

---

(root
  (declTypes (kType)
    (declType (identifier) (kEq)
      (declClass (kClass)
        (declProc (kClass) (kProcedure) (identifier))
        (declVars (kClass) (kVar)
          (declVar (identifier) (type (typeref (identifier))))
          (declVar (identifier) (type (typeref (identifier)))))
        (kEnd)))))

===
Properties
===

type
  a = class
    property b: c read d write f;
    property b: c read d;
    property b: c write d;

    property b: c read d write f default g;
    property b: c read d write f index g;
    property b: c read d write f stored g;

    property b[c, d: e; f: g]: h read i write j;
    property b[c: d]: e read f write g; default;
  end;

---

(root
  (declTypes
    (kType)
    (declType (identifier) (kEq)
      (declClass (kClass)
        (declProp (kProperty) (identifier)
          (type (typeref (identifier)))
          (kRead) (identifier)
          (kWrite) (identifier))
        (declProp (kProperty) (identifier)
          (type (typeref (identifier)))
          (kRead) (identifier))
        (declProp (kProperty) (identifier)
          (type (typeref (identifier)))
          (kWrite) (identifier))
        (declProp (kProperty) (identifier)
          (type (typeref (identifier)))
          (kRead) (identifier)
          (kWrite) (identifier)
          (kDefault) (identifier))
        (declProp (kProperty) (identifier)
          (type (typeref (identifier)))
          (kRead) (identifier)
          (kWrite) (identifier)
          (kIndex) (identifier))
        (declProp (kProperty) (identifier)
          (type (typeref (identifier)))
          (kRead) (identifier)
          (kWrite) (identifier)
          (kStored) (identifier))
        (declProp (kProperty) (identifier)
          (declPropArgs
            (declArg (identifier) (identifier) (type (typeref (identifier))))
            (declArg (identifier) (type (typeref (identifier)))))
          (type (typeref (identifier)))
          (kRead) (identifier)
          (kWrite) (identifier))
        (declProp (kProperty) (identifier)
          (declPropArgs
            (declArg (identifier) (type (typeref (identifier)))))
          (type (typeref (identifier)))
          (kRead) (identifier)
          (kWrite) (identifier)
          (procAttribute (kDefault)))
        (kEnd)))))

===
Variant Records
===

type
  a = record
    b: c;
    case d of
    0: (e: f);
    1: (g, h: i; j: k);
  end;

  a = record
    b: c;
    case d: e of
    0: (f: g);
    1: (h: i);
  end;

  a = record
    b: c;
    case d of
    0: (e: f;
      case g of
      0: (h: i);
      1: (j: k);
    );
    1: (case l of
      0: (m: n);
      1: (o: p);
    );
  end;

---

(root
  (declTypes (kType)
    (declType (identifier) (kEq)
      (declClass (kRecord)
        (declField (identifier) (type (typeref (identifier))))
        (declVariant (kCase) (typeref (identifier)) (kOf)
          (declVariantClause
            (caseLabel
              (literalNumber))
            (declField
              (identifier)
              (type (typeref (identifier)))))
          (declVariantClause
            (caseLabel
              (literalNumber))
            (declField
              (identifier)
              (identifier)
              (type (typeref (identifier))))
            (declField
              (identifier)
              (type (typeref (identifier))))))
        (kEnd)))
    (declType (identifier) (kEq)
      (declClass (kRecord)
        (declField (identifier) (type (typeref (identifier))))
        (declVariant (kCase) (identifier) (typeref (identifier)) (kOf)
          (declVariantClause
            (caseLabel
              (literalNumber))
            (declField
              (identifier)
              (type (typeref (identifier)))))
          (declVariantClause
            (caseLabel
              (literalNumber))
            (declField
              (identifier)
              (type (typeref (identifier))))))
        (kEnd)))
    (declType (identifier) (kEq)
      (declClass (kRecord)
        (declField (identifier) (type (typeref (identifier))))
        (declVariant (kCase) (typeref (identifier)) (kOf)
          (declVariantClause
            (caseLabel
              (literalNumber))
            (declField
              (identifier)
              (type (typeref (identifier))))
            (declVariant (kCase) (typeref (identifier)) (kOf)
              (declVariantClause
                (caseLabel
                  (literalNumber))
                (declField
                  (identifier)
                  (type (typeref (identifier)))))
              (declVariantClause
                (caseLabel
                  (literalNumber))
                (declField
                  (identifier)
                  (type (typeref (identifier)))))))
          (declVariantClause
            (caseLabel
              (literalNumber))
            (declVariant (kCase) (typeref (identifier)) (kOf)
              (declVariantClause
                (caseLabel
                  (literalNumber))
                (declField
                  (identifier)
                  (type (typeref (identifier)))))
              (declVariantClause
                (caseLabel
                  (literalNumber))
                (declField
                  (identifier)
                  (type (typeref (identifier))))))))
        (kEnd)))))

===
Operator overloads
===

type
  a = record
    operator +(b, c: a): a;
    operator Subtract(b, c: a): a;
  end;

---

(root
  (declTypes (kType)
    (declType (identifier) (kEq)
      (declClass (kRecord)
        (declProc (kOperator) (operatorName (kAdd))
          (declArgs
            (declArg
              (identifier)
              (identifier)
              (type (typeref (identifier)))))
          (type (typeref (identifier))))
        (declProc (kOperator) (identifier)
          (declArgs
            (declArg
              (identifier)
              (identifier)
              (type (typeref (identifier)))))
          (type (typeref (identifier))))
        (kEnd)))))

===
Inline type declarations
===

var
  a: array of b;
  a: string[b];
  a: file of b;
  a: file;
  a: set of b;
  a: set of (b, c);

procedure a(b: array of c; d: array of const; var e: string[4]);
begin
end;

---

(root
  (declVars (kVar)
    (declVar
      (identifier)
      (type (declArray (kArray) (kOf) (type (typeref (identifier))))))
    (declVar
      (identifier)
      (type (declString (kString) (identifier))))
    (declVar
      (identifier)
      (type (declFile (kFile) (kOf) (type (typeref (identifier))))))
    (declVar
      (identifier)
      (type (declFile (kFile))))
    (declVar
      (identifier)
      (type (declSet (kSet) (kOf) (type (typeref (identifier))))))
    (declVar
      (identifier)
      (type
        (declSet
          (kSet)
          (kOf)
          (type
            (declEnum
              (declEnumValue
                (identifier))
              (declEnumValue
                (identifier))))))))
  (defProc
    (declProc (kProcedure) (identifier)
      (declArgs
        (declArg
          (identifier)
          (type (declArray (kArray) (kOf) (type (typeref (identifier))))))
        (declArg
          (identifier)
          (type (declArray (kArray) (kOf) (type (typeref (identifier))))))
        (declArg
          (kVar)
          (identifier)
          (type (declString (kString) (literalNumber))))))
    (block
      (kBegin)
      (kEnd))))
