-
Notifications
You must be signed in to change notification settings - Fork 2
Preprocessor Directives
A macro shall be defined by a left-most opening tag which includes a comma delimited argument list enclosed by parentheses. The first argument shall be an identifier denoting the macro's name. It shall be mandatory. Further arguments shall be optional identifiers denoting the macro's parameters. The opening tag shall be followed by the body of the macro. The body shall contain its definition. The body shall be followed by a right-most closing tag.
macroDefinition :=
openingTag body closingTag
;
openingTag :=
'(*?MACRO(' macroIdent ( ',' macroParam )* ')*)'
;
alias macroIdent, macroParam = StdIdent ;
body :=
printableCharacter*
;
closingTag :=
'(*?END' _ macroIdent '*)'
;
An invocation of a macro shall be denoted by the macro's identifier, followed by a comma separated argument list in parentheses, if and only if the macro's definition specifies any parameters.
macroInvocation :=
'(*?' macroIdent ( '(' argList ')' )? '*)'
;
argList :=
arg ( ',' arg )*
;
alias arg = <Modula-2 expression> ;
(*?MACRO(TwosComplement, T, v)*)
MAX(T) - v + 1
(*?END TwosComlement*)subtrahend := (*?TwosComplement(CARDINAL, value)*);subtrahend := MAX(CARDINAL) - value + 1;functionDefinition :=
openingTag body closingTag
;
openingTag :=
'(*?DEFUN(' functionIdent ( ',' functionParam )* ')*)'
;
alias functionIdent, functionParam = StdIdent ;
body :=
printableCharacter*
;
closingTag :=
'(*?END' _ functionIdent '*)'
;
functionInvocation :=
'(*?' functionIdent '(' argList? ')' '*)'
;
argList :=
arg ( ',' arg )*
;
alias arg = <Modula-2 expression> ;
(*?DEFUN(POW10, n)*)
(*?IF(n=0)*)1(*?ELSE*)POW10(n-1)(*?END*)
(*?END POW10*)(*?FORTO(i, 0, 5)*)
m[i] := (*?POW10(i)*);(*?NL*)
(*?END*)m[0] := 1;
m[1] := 10;
m[2] := 100;
m[3] := 1000;
m[4] := 10000;
m[5] := 100000;mapDefinition :=
openingTag body closingTag
;
openingTag :=
'(*?MAP(' mapIdent ')*)'
;
body :=
mapMember ( ',' mapMember )*
;
alias mapIdent, mapMember = StdIdent ;
closingTag :=
'(*?END' mapIdent '*)'
;
mapInvocation :=
mapIdent '(' indexArg ')'
;
alias indexArg = <Modula-2 expression> ;
(*?MAP(RESWORD)*)
"ALIAS", "AND", "ARGLIST", "ARRAY", ...
(*?END RESWORD*)(* ##VER## version *)
(*?IF(ver=pim)*)
(*?FORIN(i, RESWORD)*)
Insert(table, RESWORD(i));(*?NL*)
(*?END FORIN*)
(*?ELIF(ver=iso)*)
table := { (*?FORIN(i, RESWORD*)RESWORD(i), (*?END*)};
(*?END IF*)if ver matches pim
(* PIM version *)
Insert(table, "ALIAS");
Insert(table, "AND");
Insert(table, "ARGLIST");
Insert(table, "ARRAY");
...if ver matches iso
(* ISO version *)
table := { "ALIAS", "AND", "ARGLIST", "ARRAY", ... }The IF-ELIF-ELSE directive shall insert source text within its body conditionally depending on a relational expression.
Source text placed between the opening tag and an optional ELIF or ELSE tag or the closing END tag will be copied into the output if the relational expression in the IF tag is true.
Source text placed between an optional ELIF tag and a following ELIF or ELSE tag or the closing END tag will be copied into the output if the relational expression in the IF tag is false, the relational expressions of any preceding ELIF tags are false, and the relational expression in the ELIF tag is true.
Source text placed between an optional ELSE tag and the closing END tag will be copied into the output if the relational expression in the IF tag is false and the relational expressions of any ELIF tags are false.
if :=
openingTag body ( elifTag body )* ( elseTag body )? closingTag
;
openingTag :=
'(*?IF(' term relOp term ')*)'
;
body :=
printableCharacter*
;
elifTag :=
'(*?ELIF(' term relOp term ')*)'
;
elseTag :=
'(*?ELSE*)'
;
closingTag :=
'(*?END' ( _ ident )? '*)'
;
The following fragment of template source
PROCEDURE NewSet64
(*?IF(ver="16bit")*)
( VAR set : Set64; seg3, seg2, seg1, seg0 : CARDINAL );
(*?ELIF(ver="32bit")*)
( VAR set : Set64; seg1, seg0 : CARDINAL );
(*?ELIF(ver="64bit")*)
( VAR set : Set64; value : CARDINAL );
(*?END IF*)will be expanded to the following output,
if ver matches 16bit
PROCEDURE NewSet64
( VAR set : Set64; seg3, seg2, seg1, seg0 : CARDINAL );if ver matches 32bit
PROCEDURE NewSet64
( VAR set : Set64; seg1, seg0 : CARDINAL );and if ver matches 64bit
PROCEDURE NewSet64
( VAR set : Set64; value : CARDINAL );The FORTO directive shall insert source text within its body repeatedly depending on a loop variant. The loop variant may be referenced within the body and any such reference shall be replaced with the value of the loop variant at each iteration.
forTo :=
openingTag body closingTag
;
openingTag :=
'(*?FORTO(' loopVariant ',' startValue ',' endValue ')*)'
;
body :=
printableCharacter*
;
closingTag :=
'(*?END' ( _ ident )? *)'
;
The following fragment of template source
(*?FORTO(i, 0, 4)*)
m[i] := 0;(*?NL*)
(*?END*)will be expanded to the following output
m[0] := 0;
m[1] := 0;
m[2] := 0;
m[3] := 0;
m[4] := 0;The CAT directive shall be replaced in the output with the concatenation of its arguments.
cat :=
'(*?CAT(' component ( ',' component )+ ')*)'
;
component :=
printableCharacter*
;
The following fragment of template source
(*?FORTO(i, 1, 80)*)
TYPE (*?CAT(String, i)*) = ARRAY [0..i] OF CHAR;(*?NL*)
(*?END*)will be expanded to the following output
TYPE String1 = ARRAY [0..1] OF CHAR;
TYPE String2 = ARRAY [0..2] OF CHAR;
TYPE String3 = ARRAY [0..3] OF CHAR;
...
TYPE String80 = ARRAY [0..80] OF CHAR;The following fragment of template source
TYPE VariableLengthString = RECORD
CASE length : CARDINAL OF
(*?FORTO(i, 1, 80)*)
(*?IF(i=1)*) (*?ELSE*)|(*?END*) i : string : (*?CAT(String, i)*)(*?NL*)
(*?END FORTO*)
END (* CASE *)
END; (* VariableLengthString *)will be expanded to the following output
TYPE VariableLengthString = RECORD
CASE length : CARDINAL OF
1 : string : String1
| 2 : string : String2
| 3 : string : String3
...
| 80 : string : String80
END (* CASE *)
END (* VariableLengthString *)The EVAL directive shall be replaced in the output with the value of its argument. Its argument shall be an arithmetic expression.
eval :=
'(*?EVAL(' expr ')*)'
;
alias expr = <Modula-2 expression> ;
The following fragment of template source
1(*?FORTO(i, 1, 7)*), (*?EVAL(2*i+1)*)(*?END*)will be expanded to the following output
1, 3, 5, 7, 9, 11, 13, 15Copyright © 2017 Modula-2 Software Foundation