3. O3PRM project structure¶
The O3PRM language is made of compilation units that are placed into modules. It is possible to encode in a single file an entire project but it is not recommended. A package matches a specific file in which we we can find at least one compilation unit. The following is a sample O3PRM project:
File extensions must be used as an indicator of the file’s compilation unit
nature. The following extensions are allowed: .o3prmr
for queries,
o3prm
for everything else (types, classes, interfaces and systems). It is
good practice to name a file with the compilation unit it holds, for example
in computer.o3prm
should contain the definition for the Computer
class. If the file contains several compilation units, you should name the file
according to the unit with the highest order. For example, if you define types,
classes and a system in one file, you should use the system’s name.
3.1. Compilation units¶
There exist four different compilation units in the O3PRM language. A
compilation unit
declares a specific element in the modeling process and can either be: an
attribute’s type, a class, an interface, a system or even a query. Each
compilation unit can start with a header. Headers are the locations where
you declare import
statements.
<o3prm> ::= [<header>] <compilation_unit> [(<compilation_unit>)]
<header> ::= <import>
<compilation_unit> ::= <type_unit> |
<class_unit> |
<interface_unit> |
<system_unit>
3.2. Header syntax¶
Each compilation unit is declared in a module defined by the path from the
project’s root to the file’s name in which it is declared. Directory separators
are represented using dots. For example the file
fr/lip6/printers/types.o3prm
defines the namespace
fr.lip6.printers.types
.
Namespaces can be used to import all of the compilation units defined in them,
since many compilation units will need units defined in other files. In such
cases, we say that a given compilation unit has dependencies which are declared
using the import
keyword. The syntax is:
<import> ::= import <path> ";"
<path> ::= <word> [ ( "." <word> ) ]
A <word>
is an alphanumerical identifier. You can find its proper
definition in the full BNF.
An example:
import fr.lip6.printers.computer;
The O3PRM interpreter should use an environment variable to know which directory to lookup for resolving compilations units. You should check your O3PRM interpreter to know which environment variable is used.
A compilation unit can be accessed through two different names:
- Its simple name: the name given to it in the file where it is declared (for example
Computer
). - Its full name: defined by its namespace and its simple name (for example
fr.lip6.printers.Computer
).
In most cases, referring to a compilation unit using its simple name will work, you will need full names only to prevent name collisions/ambiguities. Name collisions happen when two compilation units have the same name but are declared in different namespaces. In such situations, the O3PRM interpreter cannot resolve the name and will raise an interpretation error.
Note that no matter how you refer to a compilation unit (either by its simple name or full name) you must always import it using the package complete name.
Finally, note that compilation units are case sensitive regardless of the operating system.