Appendix I: The Syntax of p1 Modula-2

The following EBNF grammar describes the lexical structure and syntax of p1 Modula-2. It is based on the ISO standard 105143-1; extensions according to IS 10514-2 and 10514-3 are shown in italics; p1 specific extensions to the standard are underlined.

To improve clarity and intelligibility, some of the productions comprise nothing more than the definition of a synonym that indicates more about the semantic purpose of an item, e.g.
  type_identifier = qualified_identifier

I.1 Lexical Structure

quoted_string="'" {character other than "'"} "'" | '"' {character other than '"'} '"' .
dereferencing_operator="^" | "@" .
character_number_literal=octalDigit {octalDigit} "C" .
catenate_symbol="+" .
whole_number_literal=digit {digit} | octalDigit {octalDigit} "B" | digit {hexDigit} "H" .
case_separator="|" | "!" .
identifier=(letter | "_") {(letter | "_") | digit} .
real_literal=digit {digit} "." {digit} [scaleFactor] .
bcd_literal=digit {digit} "." {digit} "$" .
left_brace="{" | "(:" .
right_brace="}" | ":)" .
left_bracket="[" | "(!" .
right_bracket="]" | "!)" .
letter= "a" .. "z" | "A" .. "Z" | "_" | "$" .
scaleFactor="E" ["+" | "-"] digit {digit} .
hexDigit=digit | "A" | "B" | "C" | "D" | "E" | "F" .
digit=octalDigit | "8" | "9" .
octalDigit="0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" .

I.2 Syntax

compilation_unit=program_module | definition_module | implementation_module | generic_definition_module | generic_implementation_module | refining_definition_module | refining_implementation_module .
program_module=[ "UNSAFEGUARDED" ] "MODULE" module_identifier [ protection ] ";" import_lists module_block module_identifier "." .
module_identifier=identifier .
protection=left_bracket constant_expression right_bracket .
constant_expression=expression .
definition_module=[ "UNSAFEGUARDED" ] "DEFINITION" "MODULE" module_identifier ";" import_lists definitions "END" module_identifier "." .
implementation_module=[ "UNSAFEGUARDED" ] "IMPLEMENTATION" "MODULE" module_identifier [ protection ] ";" import_lists module_block module_identifier "." .
generic_definition_module="GENERIC" "DEFINITION" "MODULE" module_identifier [ formal_module_parameters ] ";" import_lists definitions "END" module_identifier "." .
generic_implementation_module="GENERIC" "IMPLEMENTATION" "MODULE" module_identifier [ interrupt_protection ] [ formal_module_parameters ] ";" import_lists module_block module_identifier "." .
refining_definition_module=[ "UNSAFEGUARDED" ] "DEFINITION" "MODULE" module_identifier "=" generic_separate_module_identifier [ actual_module_parameters ] ";" "END" module_identifier "." .
refining_implementation_module=[ "UNSAFEGUARDED" ] "IMPLEMENTATION" "MODULE" module_identifier "=" generic_separate_module_identifier [ actual_module_parameters ] ";" "END" module_identifier "." .
generic_separate_module_identifier=identifier .
formal_module_parameters="(" formal_module_parameter { ";" formal_module_parameter } ")" .
formal_module_parameter=constant_value_parameter_specification | type_parameter_specification .
constant_value_parameter_specification=identifier_list ":" formal_type .
type_parameter_specification=identifier_list ":" "TYPE" .
actual_module_parameters="(" actual_module_parameter { "," actual_module_parameter } ")" .
actual_module_parameter=constant_expression | type_parameter .
module_block=declarations [ module_body ] "END" .
module_body="BEGIN" statement_sequence ["EXCEPT" statement_sequence ] [ "FINALLY" statement_sequence ["EXCEPT" statement_sequence ] ] .
import_lists={ import_list } .
import_list=simple_import | unqualified_import | complete_import .
simple_import="IMPORT" module_identifier_list ";" .
module_identifier_list=identifier_list .
unqualified_import="FROM" module_identifier "IMPORT" identifier_list ";" .
complete_import="FROM" module_identifier "IMPORT" "*" [ "EXCEPT" identifier_list ] ";" .
export_list=unqualified_export | qualified_export .
unqualified_export="EXPORT" identifier_list .
qualified_export="EXPORT" "QUALIFIED" identifier_list .
definitions={ definition } .
definition="CONST" { constant_declaration ";" } | "TYPE" { type_definition ";" } | "VAR" { variable_declaration ";" } | procedure_heading ";" | class_definition ";" | trap_procedure_heading ";" .
type_definition=type_declaration | opaque_type_definition .
procedure_heading=proper_procedure_heading | function_procedure_heading .
class_definition=[ "TRACED" ] [ "ABSTRACT"] "CLASS" class_identifier ";" ( class_definition_body | "FORWARD" ) .
class_definition_body=[ inherit_clause ] [ reveal_list ] { component_definition } "END" class_identifier .
class_identifier=identifier .
component_definition="CONST" { constant_declaration ";" } | "TYPE" { type_definition ";" } | "VAR" { variable_declaration ";" } | method_definition ";" .
method_definition=[ "ABSTRACT" | "OVERRIDE" ] procedure_heading .
trap_procedure_heading=proper_trap_procedure_heading | function_trap_procedure_heading .
opaque_type_definition=identifier .
declarations={ declaration } .
declaration="CONST" { constant_declaration ";" } | "TYPE" { type_declaration ";" } | "VAR" { variable_declaration ";" } | procedure_declaration ";" | module_declaration ";" | class_declaration ";" | trap_procedure_heading ";" .
constant_declaration=identifier "=" constant_expression .
type_declaration=identifier "=" type .
variable_declaration=variable_identifier_list ":" type .
variable_identifier_list=identifier [ machine_address ] { "," identifier [ machine_address ] } .
machine_address=left_bracket value_of_machine_address_or_address_type right_bracket .
value_of_machine_address_or_address_type=constant_expression .
class_declaration=[ "TRACED" ] [ "ABSTRACT"] "CLASS" class_identifier ";" ( class_declaration_body | "FORWARD" ) .
class_declaration_body=[ inherit_clause ] [ reveal_list ] { component_declaration } [ class_body ] "END" class_identifier .
component_declaration="CONST" { constant_declaration ";" } | "TYPE" { type_declaration ";" } | "VAR" { variable_declaration ";" } | method_declaration ";" .
method_declaration=[ "OVERRIDE" ] procedure_declaration | "ABSTRACT" procedure_heading .
class_body=module_body .
reveal_list="REVEAL" revealed_component { "," revealed_component } ";" .
revealed_component=identifier | "READONLY" class_variable_identifier .
class_variable_identifier=identifier .
inherit_clause="INHERIT" class_type_identifier ";" .
class_type_identifier=type_identifier .
type=type_identifier | new_type .
type_identifier=qualified_identifier .
new_type=enumeration_type | subrange_type | set_type | pointer_type | procedure_type | array_type | record_type | vector_type .
enumeration_type="(" identifier_list ")" .
identifier_list=identifier { "," identifier } .
subrange_type=[ range_type ] left_bracket constant_expression ".." constant_expression right_bracket .
range_type=ordinal_type_identifier .
set_type="SET" "OF" base_type .
base_type=ordinal_type .
ordinal_type=ordinal_type_identifier | enumeration_type | subrange_type .
ordinal_type_identifier=type_identifier .
pointer_type="POINTER" "TO" [ dynamic_array_type | bound_type ] .
bound_type=type .
dynamic_array_type="ARRAY" "OF" { "ARRAY" "OF" } type .
procedure_type=proper_procedure_type | function_procedure_type .
proper_procedure_type="PROCEDURE" [ formal_parameter_type_list ] .
function_procedure_type="PROCEDURE" formal_parameter_type_list function_result_type .
function_result_type=":" type_identifier .
formal_parameter_type_list="(" [ formal_parameter_type {"," formal_parameter_type } ] ")" .
formal_parameter_type=variable_formal_type | value_formal_type .
variable_formal_type="VAR" formal_type .
value_formal_type=formal_type .
formal_type=type_identifier | open_array_formal_type .
open_array_formal_type="ARRAY" "OF" { "ARRAY" "OF" } type_identifier .
array_type="ARRAY" index_type { "," index_type" } "OF" component_type .
index_type=ordinal_type .
component_type=type .
record_type="RECORD" [ field_list ] "END" .
field_list=fields { ";" fields } .
fields=fixed_fields | variant_fields .
fixed_fields=identifier_list ":" type .
variant_fields="CASE" [ tag_identifier ] ":" tag_type "OF" variant_list "END" .
tag_identifier=ordinal_type_identifier .
tag_type=ordinal_type .
variant_list=variant { case_separator variant } [ "ELSE" field_list ] .
variant=[ variant_label_list ":" field_list ] .
variant_label_list=variant_label { "," variant_label } .
variant_label=constant_expression [ ".." constant_expression ] .
vector_type="VECTOR" "OF" type .
procedure_declaration=proper_procedure_declaration | function_procedure_declaration .
proper_procedure_declaration=proper_procedure_heading ";" (proper_procedure_block procedure_identifier | "FORWARD" ) .
procedure_identifier=identifier .
proper_procedure_heading="PROCEDURE" procedure_identifier [ formal_parameter_list ] .
formal_parameter_list="(" [ formal_parameter { ";" formal_parameter } ] ")" .
proper_procedure_block=declarations [ "BEGIN" statement_sequence [ "EXCEPT" statement_sequence ] ] "END" .
function_procedure_declaration=function_procedure_heading ";" (function_procedure_block procedure_identifier | "FORWARD" ) .
function_procedure_heading="PROCEDURE" procedure_identifier formal_parameter_list function_result_type .
function_procedure_block=declarations "BEGIN" statement_sequence [ "EXCEPT" statement_sequence ] "END" .
formal_parameter=value_parameter_specification | variable_parameter_specification .
value_parameter_specification=identifier_list ":" formal_type .
variable_parameter_specification="VAR" identifier_list ":" formal_type .
proper_trap_procedure_heading="PROCEDURE" procedure_identifier code [ formal_parameter_list ] | "PROCEDURE" procedure_identifier [ formal_parameter_list ] ";" "INLINE" code_value_list .
function_trap_procedure_heading="PROCEDURE" procedure_identifier code formal_parameter_list function_result_type | "PROCEDURE" procedure_identifier formal_parameter_list function_result_type ";" "INLINE" code_value_list .
code=left_bracket code_value_list right_bracket .
code_value_list=constant_expression { "," constant_expression } .
module_declaration=local_module_declaration | refining_local_module_declaration .
local_module_declaration="MODULE" module_identifier [ protection ] ";" { import_lists } [ export_list] module_block module_identifier "." .
refining_local_module_declaration="MODULE" module_identifier "=" generic_separate_module_identifier [ actual_module_parameters ] ";" [ export_list ] "END" module_identifier .
statement=empty_statement | assign_statement | procedure_call | return_statement | retry_statement | with_statement | if_statement | case_statement | while_statement | repeat_statement | loop_statement | exit_statement | for_statement | guard_statement .
statement_sequence=statement { ";" statement } .
empty_statement= .
assign_statement=variable_designator ":=" expression .
procedure_call=procedure_designator [ actual_parameters ] .
procedure_designator=value_designator .
actual_parameters="(" [ actual_parameter_list ] ")" .
actual_parameter_list=actual_parameter { "," actual_parameter } .
actual_parameter=variable_designator | expression | type_parameter .
type_parameter=type_identifier .
return_statement=simple_return_statement | function_return_statement .
simple_return_statement="RETURN" .
function_return_statement="RETURN" expression .
retry_statement="RETRY" .
with_statement="WITH" record_designator "DO" statement_sequence "END" .
record_designator=variable_designator | value_designator .
if_statement=guarded_statements [ "ELSE" statement_sequence ] "END" .
guarded_statements="IF" boolean_expression "THEN" statement_sequence { "ELSIF" boolean_expression "THEN" statement_sequence } .
boolean_expression=expression .
case_statement="CASE" case_selector "OF" case_list "END" .
case_selector=ordinal_expression .
case_list=case { "|" case } [ "ELSE" statement_sequence ] .
case=[ case_label_list ":" statement_sequence ] .
case_label_list=case_label { "," case_label } .
case_label=constant_expression [ ".." constant_expression ] .
while_statement="WHILE" boolean_expression "DO" statement_sequence "END" .
repeat_statement="REPEAT" statement_sequence "UNTIL" boolean_expression .
loop_statement="LOOP" statement_sequence "END" .
exit_statement="EXIT" .
for_statement="FOR" control_variable_identifier ":=" initial_value "TO" final_value [ "BY" step_size ] "DO" statement_sequence "END" .
control_variable_identifier=identifier .
initial_value=ordinal_expression .
final_value=ordinal_expression .
step_size=constant_expression .
guard_statement="GUARD" guard_selector "AS" guarded_list [ "ELSE" statement_sequence ] "END" .
guard_selector=expression .
guarded_list=guarded_statement_sequence { "|" guarded_statement_sequence } .
guarded_statement_sequence=[[ object_denoter] ":" guarded_class_type "DO", statement_sequence ] .
guarded_class_type=class_type_identifier .
object_denoter=identifier .
variable_designator=entire_designator | indexed_desigantor | selected_designator | dereferenced_designator | object_selected_designator .
entire_designator=qualified_identifier .
indexed_desigantor=array_designator left_bracket index_expression { "," index_expression } right_bracket .
array_designator=variable_designator .
index_expression=ordinal_expression .
ordinal_expression=expression .
selected_designator=record_designator "." field_identifier .
field_identifier=identifier .
dereferenced_designator=pointer_designator dereferencing_operator .
pointer_designator=variable_designator .
object_selected_designator=object_variable_designator "." [ class_identifier "." ] class_variable_identifier .
object_variable_designator=variable_designator .
expression=simple_expression [ relational_operator simple_expression ] .
simple_expression=[ sign ] term { term_operator term } .
term=factor { factor_operator factor } .
factor="(" expression ")" | not_operator factor | value_designator | function_call | value_constructor | constant_literal .
factor_operator="*" | "/" | "REM" | "DIV" | "MOD" | and_operator .
and_operator="AND" | "&" .
term_operator="+" | "-" | "OR" | catenate_symbol .
relational_operator="=" | inequality_operator | "<" | ">" | "<=" | ">=" | "IN" .
sign=[ "+" | "-" ] .
not_operator="NOT" | "~" .
value_designator=( entire_value | indexed_value | selected_value | dereferenced_value | object_selected_value ) .
entire_value=qualified_identifier .
indexed_value=array_value left_bracket index_expression { "," index_expression } right_bracket .
array_value=value_designator .
selected_value=record_value "." field_identifier .
record_value=value_designator .
dereferenced_value=pointer_value dereferencing_operator .
pointer_value=value_designator .
object_selected_value=object_value_designator "." [ class_identifier "." ] entity_identifier .
object_value_designator=value_designator .
entity_identifier=identifier .
function_call=function_designator "(" [ actual_parameter_list ] ")" .
function_designator=value_designator .
value_constructor=array_constructor | record_constructor | set_constructor .
array_constructor=type_identifier array_constructed_value .
array_constructed_value=left_brace repeated_component { "," repeated_component } right_brace .
repeated_component=component_of_structure [ "BY" repetition_factor ] .
repetition_factor=constant_expression .
component_of_structure=expression | array_constructed_value | record_constructed_value | set_constructed_value .
record_constructor=type_identifier record_constructed_value .
record_constructed_value=left_brace [ component_of_structure { "," component_of_structure } ] right_brace .
set_constructor=type_identifier set_constructed_value .
set_constructed_value=left_brace [ member { "," member } ] right_brace .
member=interval | singleton .
interval=ordinal_expression ".." ordinal_expression .
singleton=ordinal_expression .
constant_literal=whole_number_literal | real_literal | bcd_literal | string_literal .
string_literal=quoted_string | character_number_literal .
qualified_identifier=identifier { "." identifier } .

Appendix II: Differences Between This and Previous Implementations

With version 8.0 of p1 Modula-2 support for 68k code generation was dropped. In this context also all (long deprecated) remnants of pre standard features like the old objects or the old pragma syntax have gone too to make the compiler smaller and faster.

As the old features did not provide for any semantics not achievable by the corresponding standard features, there is no loss in functionality. The following paragraphs give an overview over the dropped features and proposals how to replace these features.

II.1 The Differences to V7.x

Following details should be considered when recompiling programs with version 8.0:

II.2 Conversion Tips

The steps detailed below should be of assistance when updating code from version 7.x to version 8.0.

Substantial changes to the program text are necessary if you still used the old style objects. In this case you should redesign your object model before compiling the program with version 8.0. In all other cases you can just recompile your code and correct lines where warnings or errors are emitted.

The following table may help you to change the lines in question:
Simple textual replacements:
LONGINT->SYSTEM. INT32(or INTEGER)
LONGCARD->SYSTEM. CARD32(or CARDINAL)
LEN->LENGTH 

Simple changes that need to be done manually:
SHORT, LONG->can be removed if argument a whole number—no longer necessary
SHORT (x)->VAL (REAL, x)for LONGREAL -> REAL
LONG (x)->VAL (LONGREAL, x)for REAL -> LONGREAL

More involved changes:
TYPE (expr)->CAST (TYPE, expr)old type-casting syntax
SYSTEM. EXTENDED->LONGREALnot available on PowerPC
SYSTEM. EXTENDEDCOMPLEX->LONGCOMPLEXnot available on PowerPC
(*$...*)-><* ... *>new pragma syntax
"\" in string constants cf. II.3 
%FOREIGN, %C, %PASCAL->new pragma method 

II.3 Old String Constants

Since earlier implementations had no string concatenation facility, control characters could only readily be included in string constants by using the specially selected meta-character "\". How this meta-character was applied is shown in the following:
\nnnInclude the character with three-digit octal ASCII code "nnn" ("\nnn" = nnnC; e.g.: "\015\012", which corresponds to CR, LF).
\TInclude tab character (= "\011").
\LReplace with the count of how many characters there are after this up to the end of the string or the next "\L". Makes above all the representation of string constants with initial length byte as used in many Pascal implementations much more convenient.
Examples:
"\LHallo" = "\005Hallo"
"\T\Labc\Luvwxyz" = "\011\003abc\006uvwxyz"
\∂If "\" is the last character on a line, continue string with first character on next line. Makes it possible for a string to extend over several lines.
\\Include the character "\" itself (= "\134").

Control characters can be embedded in strings using concatenation in the standard implementation. ""This " + 7C + "is the bell"" has the same effect as ""This \007is the bell"" in the old syntax. Wrapping a string around the end of a line can also be achieved by string concatenation.
Only the string-length meta-character ("\L") is not easy to substitute when appearing in the middle of a string. However the introduction of "SYSTEM. STR255" has made the explicit declaration of Pascal-style string constants superfluous in the vast majority of cases.
chapter 6 (compiler) start page table of contents (library)