Object Pascal Grammar

Overview

This is the current grammar for the Object Pascal parser in Browse and Doc It. It doesn’t support the latest language enhancements (supports up to circa Delphi 2006) but I hope to update it very soon with the following features:

  • RTTI Attributes;
  • Generics;
  • Anonymous Methods.

Grammar

/**

  Browse and Doc It Object Pascal Grammar

  @Version 1.0
  @Date    02 Sep 2011
  @Author  David Hoyle

  @usesemicolon

**/
<Goal>                    ::= ( <Program> | <Package> | <Library> | <Unit> );

<Program>                 ::= [ 'PROGRAM' <Ident> [ '(' <IdentList> ')' ] ';' ]
                              <ProgramBlock> '.';

<Unit>                    ::= 'UNIT' <Ident> [ <PortabilityDirective> ] ';'
                              <InterfaceSection>
                              <ImplementationSection>
                              <InitSection> '.';

<Package>                 ::= 'PACKAGE' <Ident> ';'
                              [ <RequiresClause> ]
                              [ <ContainsClause> ]
                              'END' '.';

<Library>                 ::= 'LIBRARY' <Ident> ';'
                              <ProgramBlock> '.';

<ProgramBlock>            ::= [ <UsesClause> ]
                              <Block>;

<UsesClause>              ::= 'USES' <IdentList> ';';

<PortabilityDirective>    ::= 'PLATFORM' | 'DEPRECATED' <String> | 'LIBRARY';

<InterfaceSection>        ::= 'INTERFACE'
                              [ <UsesClause> ]
                              [ <InterfaceDecl> ];

<InterfaceDecl>           ::= ( <ConstSection>     |
                                <ResStringSection> |
                                <TypeSection>      |
                                <VarSection>       |
                                <ThreadVarSection> |
                                <ExportedHeading>  |
                                <ExportsStmt> )*;

<ExportedHeading>         ::= ( <ProcedureHeading> | <FunctionHeading> ) ';' [ <Directive> ];

<ImplementationSection>   ::= 'IMPLEMENTATION'
                              [ <UsesClause> ]
                              ( [ <DeclSection> ] | [ <ExportsStmt> ] )*;

<Block>                   ::= [ <DeclSection> ]
                              [ <ExportsStmt> ]
                              <CompoundStmt>
                              [ <ExportsStmt> ];

<ExportsStmt>             ::= 'EXPORTS' <ExportsItem> [ ',' <ExportsItem> ]*;

<ExportsItem>             ::= <Ident> [ 'NAME' | 'INDEX' "'" <ConstExpr> "'" ]
                                      [ 'INDEX' | 'NAME' "'" <ConstExpr> "'" ];

<DeclSection>             ::= ( <LabelDeclSection> |
                                <ConstSection>     |
                                <ResStringSection> |
                                <TypeSection>      |
                                <VarSection>       |
                                <ThreadVarSection> |
                                <ProcedureDeclSection> )*;

<LabelDeclSection>        ::= 'LABEL' <LabelId>;

<ConstSection>            ::= 'CONST' ( <ConstantDecl> ';' )*;

<ConstantDecl>            ::= <Ident> ( '=' <ConstExpr> | ':' <TypeID> '=' <TypedConstant> ) [ <PortabilityDirective> ];

<ResStringSection>        ::= 'RESOURCESTRING' ( <ResourceStringDecl> ';' )*;

<ResourceStringDecl>      ::= <Ident> '=' <ConstExpr>;

<TypeSection>             ::= 'TYPE' ( <TypeDecl> ';' )*;

<TypeDecl>                ::= <Ident> '=' [ 'TYPE' ] ( <Type> | <RestrictedType> ) [ <PortabilityDirective> ];

<TypedConstant>           ::= ( <ConstExpr> | <ArrayConstant> | <RecordConstant> );

<ArrayConstant>           ::= '(' ( <TypedConstant> [ ',' <TypedConstant> ]* ) ')';

<RecordConstant>          ::= '(' ( <RecordFieldConstant> [ ';' <RecordFieldConstant> ]* ) ')';

<RecordFieldConstant>     ::= <Ident> ':' <TypedConstant>;

<Type>                    ::= <TypeID>        |
                              <SimpleType>    |
                              <StrucType>     |
                              <PointerType>   |
                              <StringType>    |
                              <ProcedureType> |
                              <VariantType>   |
                              <ClassRefType>;

<RestrictedType>          ::= <ObjectType> | <ClassType> | <InterfaceType>;

<ClassRefType>            ::= 'CLASS' 'OF' <TypeID>;

<SimpleType>              ::= ( <OrdinalType> | <RealType> );

<RealType>                ::= 'REAL48' | 'REAL' | 'SINGLE' | 'DOUBLE' |
                              'EXTENDED' | 'CURRENCY' | 'COMP';

<OrdinalType>             ::= ( <SubrangeType> | <EnumeratedType> | <OrdIdent> );

<OrdIdent>                ::= 'SHORTINT' | 'SMALLINT' | 'INTEGER' | 'BYTE' |
                              'LONGINT' | 'INT64' | 'WORD' | 'BOOLEAN' | 'CHAR' |
                              'WIDECHAR' | 'LONGWORD' | 'PCHAR';

<VariantType>             ::= 'VARIANT' | 'OLEVARIANT';

<SubrangeType>            ::= <ConstExpr> '..' <ConstExpr>;

<EnumeratedType>          ::= '(' ( <EnumerateTypeElement> [ ',' <EnumerateTypeElement> ]* ) ')';

<EnumerateTypeElement>    ::= <Ident> [ '=' <ConstExpr> ];

<StringType>              ::= 'STRING'     |
                              'ANSISTRING' |
                              'WIDESTRING' |
                              'STRING' '[' <ConstExpr> ']';

<StrucType>               ::= [ 'PACKED' ] ( <ArrayType> | <SetType> | <FileType> | <RecType> [ 'PACKED' ] );

<ArrayType>               ::= 'ARRAY' [ '[' <OrdinalType> [ ',' <OrdinalType> ]* ']'] 'OF' <Type> [ <PortabilityDirective> ];

<RecType>                 ::= 'RECORD'
                              (
                                [ <ClassVisibility> ]
                                [ <FieldList> ]
                                [ <ClassMethodList> ]
                                [ <ClassPropertyList> ]
                                [ <TypeSection> ]
                                [ <ConstSection> ]
                                [ <VarSection> ]
                                [ <ClassVarSection> ]
                              )*
                              'END' [ <PortabilityDirective> ];

<FieldList>               ::= ( <FieldDecl> [ ';' <FieldDecl> ]* ) [ <VariantSection> ] [';'];

<FieldDecl>               ::= <IdentList> ':' <Type> [ <PortabilityDirective> ];

<VariantSection>          ::= ( 'CASE' [ <Ident> ':' ] <TypeID> 'OF' <RecVariant> ';' )*;

<RecVariant>              ::= ( <ConstExpr> ',' )* ':' '(' [ <FieldList> ] ')';

<SetType>                 ::= 'SET' 'OF' <OrdinalType> [ <PortabilityDirective> ];

<FileType>                ::= 'FILE' [ 'OF' <TypeID> ] [ <PortabilityDirective> ];

<PointerType>             ::= '^' <TypeID> [ <PortabilityDirective> ];

<ProcedureType>           ::= ( <ProcedureHeading> | <FunctionHeading> ) [ 'OF' 'OBJECT' ];

<VarSection>              ::= 'VAR' ( <VarDecl> ';' )*;

<ThreadVarSection>        ::= 'THREADVAR' ( <ThreadVarDecl> ';' )*;

<ClassVarSection>         ::= 'CLASS' 'VAR' ( <VarDecl> ';' )*;

<VarDecl>                 ::= <IdentList> ':' <Type> [ ( 'ABSOLUTE' ( <Ident> | <ConstExpr> ) ) | '=' <ConstExpr> ] [ <PortabilityDirective> ];

//: This must be a string constant expression.
<ThreadVarDecl>           ::= <IdentList> ':' <Type> [ ( 'ABSOLUTE' ( <Ident> | <ConstExpr> ) ) | '=' <ConstExpr> ] [ <PortabilityDirective> ];

<Expression>              ::= <SimpleExpression> [ <RelOp> <SimpleExpression> ]*;

<SimpleExpression>        ::= [ '+' | '-' ] <Term> [ <AddOp> <Term> ]*;

<Term>                    ::= <Factor> [ <MulOp> <Factor> ]*;

<Factor>                  ::= <Designator> [ '(' <ExprList> ')' ] |
                              '@' <Designator>                    |
                              <Number>                            |
                              <String>                            |
                              'NIL'                               |
                              '(' <Expression> ')'                |
                              'NOT' <Factor>                      |
                              'INHERITED' [ <Designator> ]        |
                              <SetConstructor>                    |
                              <TypeID> '(' <Expression> ')';

//: = not processed in a Constant Expression.
<RelOp>                   ::= '>' | '<' | '<=' | '>=' | '<>' | 'IN' | 'IS' |
                              'AS' | '=';

<AddOp>                   ::= '+' | '-' | 'OR' | 'XOR';

<MulOp>                   ::= '*' | '/' | 'DIV' | 'MOD' | 'AND' | 'SHL' | 'SHR';

<Designator>              ::= <QualID> [ '.' <Ident> | '[' <ExprList> ']' | '^']*;

<SetConstructor>          ::= '[' [ <SetElement> ( ',' <SetElement> )* ] ']';

<SetElement>              ::= <Expression> [ '..' <Expression> ];

<ExprList>                ::= <Expression> ( ',' <Expression> )*;

<Statement>               ::= [ <LabelId> ':' ] [ <SimpleStatement> | <StructStmt> ];

<StmtList>                ::= <Statement> ( ';' <Statement> )*;

<SimpleStatement>         ::= <Designator> [ '(' <ExprList> ')' ] |
                              <Designator> ':=' <Expression>      |
                              'INHERITED'                         |
                              'GOTO' <LabelId>                    |
                              '(' <Expression> ')'                |
                              '(' <Expression> ')' /* used to handle typecasts. */;

<StructStmt>              ::= <CompoundStmt>    |
                              <ConditionalStmt> |
                              <LoopStmt>        |
                              <WithStmt>        |
                              <TryExceptStmt>   |
                              <TryFinallyStmt>  |
                              <RaiseStmt>       |
                              <AssemblerStmt>;

<CompoundStmt>            ::= 'BEGIN' <StmtList> 'END';

<ConditionalStmt>         ::= <IfStmt> | <CaseStmt>;

<IfStmt>                  ::= 'IF' <Expression> 'THEN' <Statement> [ 'ELSE' <Statement> ];

<CaseStmt>                ::= 'CASE' <Expression> 'OF' <CaseSelector> ( ';' <CaseSelector> )* [ 'ELSE' <Statement> ] [';'] 'END';

<CaseSelector>            ::= <CaseLabel> ( ',' <CaseLabel> )* ':' <Statement>;

<CaseLabel>               ::= <ConstExpr> [ '..' <ConstExpr> ];

<LoopStmt>                ::= <RepeatStmt> | <WhileStmt> | <ForStmt>;

<RepeatStmt>              ::= 'REPEAT' <Statement> 'UNTIL' <Expression>;

<WhileStmt>               ::= 'WHILE' <Expression> 'DO' <Statement>;

<ForStmt>                 ::= 'FOR' <QualID> ':=' <Expression> ( 'TO' | 'DOWNTO' ) <Expression> 'DO' <Statement> |
                              'FOR' <QualID> 'IN' <Expression> 'DO';

<WithStmt>                ::= 'WITH' <IdentList> 'DO' <Statement>;

<TryExceptStmt>           ::= 'TRY'
                                 <Statement>
                              'EXCEPT'
                                <ExceptionBlock>
                              'END';

<ExceptionBlock>          ::= [ 'ON' [ <Ident> ':' ] <TypeID> 'DO' <Statement> ]*
                              [ 'ELSE' <Statement> ];

<TryFinallyStmt>          ::= 'TRY'
                                <Statement>
                              'FINALLY'
                                <Statement>
                              'END';

<RaiseStmt>               ::= 'RAISE' [ <object> ] [ 'AT' <address> ];

<AssemblerStmt>           ::= 'ASM'
                                <AssemblerLanguage>
                              'END';

<ProcedureDeclSection>    ::= <ProcedureDecl>   |
                              <FunctionDecl>    |
                              <ConstructorDecl> |
                              <DestructorDecl>  |
                              <OperatorDecl>;

<ProcedureDecl>           ::= <ProcedureHeading> ';' [ <Directive> ] [ <PortabilityDirective> ] <Block> ';';

<FunctionDecl>            ::= <FunctionHeading> ';' [ <Directive> ] [ <PortabilityDirective> ] <Block> ';';

<ConstructorDecl>         ::= <ConstructorHeading> ';' [ <Directive> ] [ <PortabilityDirective> ] <Block> ';';

<DestructorDecl>          ::= <DestructorHeading> ';' [ <Directive> ] [ <PortabilityDirective> ] <Block> ';';

<OperatorDecl>            ::= <FunctionHeading> ';' [ <Directive> ] [ <PortabilityDirective> ] <Block> ';';

<FunctionHeading>         ::= 'FUNCTION' <Ident> [ <FormalParameters> ] ':' ( <SimpleType> | 'STRING' );

<ProcedureHeading>        ::= 'PROCEDURE' <Ident> [ <FormalParameters> ];

<OperatorHeading>         ::= 'OPERATOR' <Ident> [ <FormalParameters> ] ':' ( <SimpleType> | 'STRING' );

<FormalParameters>        ::= '(' [ <FormalParam> (';' <FormalParam> )* ] ')';

<FormalParam>             ::= [ 'VAR' | 'CONST' | 'OUT' ] <Parameter>;

<Parameter>               ::= <IdentList> [ ':' ( [ 'ARRAY' 'OF' ] <SimpleType> | 'STRING' | 'FILE' ) ] |
                              <Ident> ':' <SimpleType> '=' <ConstExpr>;

<Directive>               ::= 'ABSTRACT' | 'ASSEMBLER' | 'CDECL' |
                              'DISPID' <ConstExpr> | 'DYNAMIC' | 'EXPORT' |
                              'EXTERNAL' <ConstExpr> ( <ExportsSpecifier> ) |
                              'FAR' | 'FINAL' | 'FORWARD' | 'INLINE' | 'LOCAL' |
                              'MESSAGE' <ConstExpr> | 'NEAR' | 'OVERLOAD' |
                              'OVERRIDE' | 'PASCAL' | 'REGISTER' | 'REINTRODUCE' |
                              'SAFECALL' | 'STDCALL' | 'VARARGS' | 'VIRTUAL';

<ObjectType>              ::= 'OBJECT'
                              (
                                [ <ObjHeritage> ]
                                [ <ObjFieldList> ]
                                [ <MethodList> ]
                               )*
                              'END';

<ObjHeritage>             ::= '(' <QualID> ')';

<MethodList>              ::= ( <MethodHeading> [';' 'VIRTUAL' ] ( <MethodHeading> [';' 'VIRTUAL' ] ';' )* );

<MethodHeading>           ::= <ProcedureHeading>   |
                              <FunctionHeading>    |
                              <ConstructorHeading> |
                              <DestructorHeading>  |
                              <OperatorHeading>;

<ConstructorHeading>      ::= 'CONSTRUCTOR' <Ident> [ <FormalParameters> ];

<DestructorHeading>       ::= 'DESTRUCTOR' <Ident> [ <FormalParameters> ];

<ObjFieldList>            ::= ( <IdentList> ':' <Type> ( <IdentList> ':' <Type> ';' )* );

<InitSection>             ::= 'INITIALIZATION' <StmtList>
                              [ 'FINALIZATION' <StmtList> ] 'END' |
                              'BEGIN' <StmtList> 'END'            |
                              'END';

<ClassType>               ::= 'CLASS' [ 'ABSTRACT' | 'SEALED' ] [ 'HELPER' ] [ <ClassHeritage> ] [ 'FOR' <ClassTypeIdentifierName> ]
                              (
                                [ <ClassVisibility> ]
                                [ <ClassFieldList> ]
                                [ <ClassMethodList> ]
                                [ <ClassPropertyList> ]
                                [ <TypeSection> ]
                                [ <ConstSection> ]
                                [ <VarSection> ]
                                [ <ClassVarSection> ]
                              )*
                              'END';

<ClassHeritage>           ::= '(' <IdentList> ')';

<ClassVisibility>         ::= [ [ 'STRICT' ] 'PUBLIC'    |
                                [ 'STRICT' ] 'PROTECTED' |
                                'PRIVATE'                |
                                'PUBLISHED' ];

<ClassFieldList>          ::= ( <ClassVisibility>  <ObjFieldList> ( ';' <ObjFieldList> )* );

<ClassMethodList>         ::= ( <ClassVisibility>  <MethodList> ( ';' <MethodList> )* );

<ClassPropertyList>       ::= ( <ClassVisibility> <PropertyList> ( ';' <PropertyList> )* );

<PropertyList>            ::= 'PROPERTY' <Ident> [ <PropertyInterface> ] [ <PropertySpecifiers> ] [ <PortabilityDirective> ];

<PropertyInterface>       ::= [ <PropertyParameterList> ] ':' <Ident>;

<PropertyParameterList>   ::= '[' ( <IdentList> ':' <TypeID> [ ';' <IdentList> ':' <TypeID> ]* ) ']';

<PropertySpecifiers>      ::= [ 'INDEX' <ConstExpr> ]
                              [ 'READ' <Ident> ]
                              [ 'WRITE' <Ident> ]
                              [ 'STORED' ( <Ident> | <ConstExpr> ) ]
                              [ ( 'DEFAULT' <ConstExpr> ) | 'NODEFAULT' ]
                              [ 'IMPLEMENTS' <TypeID> ];

<InterfaceType>           ::= 'INTERFACE'
                              (
                                [ <InterfaceHeritage> ]
                                [ <ClassMethodList> ]
                                [ <ClassPropertyList> ]
                              )*
                              'END';

<InterfaceHeritage>       ::= '(' <IdentList> ')';

<RequiresClause>          ::= 'REQUIRES' <IdentList> ';';

<ContainsClause>          ::= 'CONTAINS' <IdentList> ';';

<IdentList>               ::= <Ident> ( ',' <Ident> )*;

<QualID>                  ::= ( [ <UnitId> '.'] )* <Ident>;

<TypeID>                  ::= [ <UnitId> '.'] <Ident>;

<Ident>                   ::= <Identifier>;

<ConstExpr>               ::= ? An expression which evaluates to a constant at compilation time ?;

<UnitId>                  ::= <Identifier>;

<LabelId>                 ::= <Identifier>;

<Number>                  ::= ? number ?;

<String>                  ::= ? string ?;

<ClassTypeIdentifierName> ::= <Identifier>;

<Identifier>              ::= <AlphaChar> ( <AlphaChar> | <NumericChar> )*;

<AlphaChar>               ::= 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' |
                              'I' | 'J' | 'K' | 'L' | 'M' | 'M' | 'O' | 'P' |
                              'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' |
                              'Y' | 'Z';

<NumericChar>             ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' |
                              '8' | '9';

<address>                 ::= '$' <HexNumber> <HexNumber>*;

<HexNumber>               ::= <NumericChar> | 'A' | 'B' | 'C' | 'D' | 'E' | 'F';

<object>                  ::= <Identifier>;

<ExportsSpecifier>        ::= ? Unknown ?;

<AssemblerLanguage>       ::= ? 80x86 32bit Assembly Language ?;