133 Source Files and Declarations

Predica has two top-level file grammars. _component_.predica is a component manifest: it marks the component root and has an optional component declaration followed by an optional releases block. Each release entry has a fixed name field and date field, followed by zero or more component release dependencies.

An ordinary .predica source file has a prologue followed by declarations and then optional program statements. Its prologue consists of an optional component declaration, an optional @dynamic directive, and zero or more file-scoped using declarations, in that order.

A using declaration belongs to an ordinary source-file prologue. Once a program variable, update statement, procedure call, or expression statement appears, no further declarations may appear in that file.

Grammar in EBNF


(************** Program **************)

Program =
      ComponentManifestFile
    | SourceFile;

ComponentManifestFile =
    [ ComponentDeclaration ],
    [ ComponentReleasesBlock ];

SourceFile =
    SourceFilePrologue,
    TypeDefinitions,
    { Statement };

SourceFilePrologue =
    [ ComponentDeclaration ],
    [ DynamicModeDeclaration ],
    { UsingDeclaration };

(* ComponentManifestFile is the grammar for _component_.predica.
   SourceFile is the grammar for ordinary .predica source files.
   UsingDeclaration is permitted only in SourceFilePrologue, not inside a namespace. *)

ComponentDeclaration =
    "component", QualifiedComponentName, ";";

ComponentReleasesBlock =
    "releases",
    "{",
        { ComponentReleaseEntry, [ "," ] },
    "}";

ComponentReleaseEntry =
    IntegerLiteral,
    ":",
    "{",
        "name", ":", StringLiteral,
        ",",
        "date", ":", ComponentReleaseDate,
        { ",", ComponentReleaseDependency },
        [ "," ],
    "}";

ComponentReleaseDate =
    "(", IntegerLiteral, ",", Identifier, ",", IntegerLiteral, ")";

ComponentReleaseDependency =
    QualifiedComponentName,
    ":",
    IntegerLiteral;

DynamicModeDeclaration =
    "@", "dynamic", "=", BooleanLiteral, ";";

UsingDeclaration =
    "using",
    QualifiedComponentName,
    [ ( "as", ComponentName ) | SelectedImportList ],
    ";";

SelectedImportList =
    "{",
        SelectedImport, { ",", SelectedImport },
    "}";

SelectedImport =
    QualifiedImportName, [ "as", Identifier ];

QualifiedImportName =
    Identifier, { ".", Identifier };

(************** Metadata **************)

MetaData =
    MetaDataItem, { MetaDataItem };

MetaDataItem =
    "@", Identifier, [ "(", [ ExpressionList ], ")" ];

(************** Names **************)

(* Qualified names used in references *)
QualifiedNamespaceName  = NamespaceName, { ".", NamespaceName };
QualifiedComponentName = QualifiedNamespaceName;
QualifiedTypeName  = [ComponentName, "."], TypeName;

(* Unqualified names, typically used in definitions. These are also used for aliases *)
NamespaceName  = Identifier;
TypeName       = Identifier;
AttributeName  = Identifier;
GlobalVarName  = Identifier;
ComponentName  = Identifier;