Grammar
The complete grammar of PaskalCPP, one section per part of the language: the shape of every construct. What each one means, and the rules the compiler checks, are on the topic pages.
Notation
The grammar is written in EBNF (ISO 14977):
name = ... ;defines a production; a name with spaces, such astype expr, is one name.a , bisafollowed byb;a | bisaorb.[ a ]is an optionala;{ a }isazero or more times;( a | b )groups."begin"and'R"'are text written exactly as shown."a" .. "z"is any one character in that range.? ... ?describes in words what the grammar cannot spell out.
Program and Modules
program = module ;
module = "module" , module kind , identifier , ";" ,
{ directive } ,
[ import clause ] ,
{ declaration } ,
[ initialize section ] ,
[ finalize section ] ,
[ module body ] ,
"end" , "." ,
{ test block } ;
module kind = "exe" | "dll" | "lib" | "unit" ;
import clause = "import" , identifier , { "," , identifier } , ";" ;
initialize section
= "initialize" , routine body ;
finalize section
= "finalize" , routine body ;
module body = "begin" , { statement } ;
Directives
directive = conditional directive | build directive ;
conditional directive
= "@define" , identifier
| "@undef" , identifier
| "@ifdef" , identifier
| "@ifndef" , identifier
| "@elseif" , identifier
| "@else"
| "@endif" ;
build directive = "@optimize" , identifier , ";"
| "@subsystem" , identifier , ";"
| "@target" , target spec , ";"
| "@addverinfo" , identifier , ";"
| "@unitTestMode" , identifier , ";"
| "@vimajor" , integer , ";"
| "@viminor" , integer , ";"
| "@vipatch" , integer , ";"
| "@viproductname" , cstring , ";"
| "@videscription" , cstring , ";"
| "@vifilename" , cstring , ";"
| "@vicompanyname" , cstring , ";"
| "@vicopyright" , cstring , ";"
| "@exeicon" , cstring , ";"
| "@copydll" , cstring , ";"
| "@linklibrary" , cstring , ";"
| "@addlibrarypath" , cstring , ";"
| "@addmodulepath" , cstring , ";"
| "@addincludepath" , cstring , ";"
| "@addsourcefile" , cstring , ";"
| "@cppdefine" , cstring , [ cstring ] , ";"
| "@cppundef" , cstring , ";"
| "@breakpoint" , ";"
| "@message" , severity , cstring , ";"
| "@outputpath" , cstring , ";" ;
target spec = cstring ;
severity = "hint" | "warn" | "error" | "fatal" ;
Declarations
declaration = var block | const block | type block
| routine decl | forward decl | exported decl
| cpp placement | cpp block | cpp preprocessor
| cpp declaration ;
exported decl = "exported" , declaration ;
forward decl = "forward" , ( "routine" , [ linkage ] , identifier , [ param list ] ,
[ ":" , type expr ]
| "type" , identifier ) , ";" ;
var block = "var" , { var decl } ;
var decl = identifier , ":" , type expr ,
[ "(" , [ arg list ] , ")" | "=" , expression ] , ";" ,
[ external clause ] ;
const block = "const" , { const decl } ;
const decl = identifier , ":" , type expr , "=" , expression , ";" ;
routine decl = "routine" , [ linkage ] , identifier ,
[ param list ] , [ ":" , type expr ] , ";" ,
( external clause | routine body ) ;
routine body = { var block | const block | type block } , block , ";" ;
method decl = [ "virtual" | "override" ] , [ "final" ] ,
[ "const" ] ,
"method" , identifier , [ param list ] ,
[ ":" , type expr ] , ";" ,
( "abstract" , ";" | { var block } , block , ";" ) ;
linkage = "clink" | "cpplink" ;
external clause = "external" , [ cstring | identifier ] , ";" ;
param list = "(" , [ params ] , ")" ;
params = "..." | param , { ";" , param } , [ ";" , "..." ] ;
param = [ "var" | "const" ] , identifier , ":" , type expr ;
Types
type block = "type" , { type decl } ;
type decl = identifier , "=" , type def , ";" ;
type def = record type | [ "final" ] , object type | interface type
| overlay type | choices type
| array type | pointer type | set type | routine type
| alias type ;
alias type = type expr ;
record type = "record" , [ "(" , qualified type , ")" ] ,
[ "packed" ] , [ "align" , "(" , expression , ")" ] ,
{ field decl | anon overlay | operator decl } , "end" ;
object type = "object" , [ "(" , qualified type , ")" ] ,
[ "implements" , qualified type , { "," , qualified type } ] ,
{ [ "hidden" ] , ( field decl | embed decl | method decl | property decl )
| init decl | copy decl | done decl | operator decl } ,
"end" ;
operator decl = "operator" , operator symbol , param list , ":" , type expr , ";" ,
{ var block } , block , ";" ;
operator symbol = "+" | "-" | "*" | "/" | "div" | "mod" | "=" | "<>" | "<" | "<=" | ">" | ">=" | "in" ;
property decl = [ "virtual" | "override" ] , [ "final" ] ,
"property" , identifier , [ "[" , [ "const" ] , identifier , ":" , type expr , "]" ] ,
":" , type expr ,
"read" , ( identifier , ";" | "abstract" , ";" | { var block } , block , ";" ) ,
[ [ "hidden" ] , "write" , ( identifier , ";" | "abstract" , ";"
| "(" , identifier , ")" , { var block } , block , ";" ) ] ,
[ "default" , ";" ] ;
interface property = "property" , identifier , [ "[" , [ "const" ] , identifier , ":" , type expr , "]" ] ,
":" , type expr , "read" , ";" , [ "write" , ";" ] ;
embed decl = "embed" , identifier , ":" , type expr , ";" ;
interface type = "interface" , [ "(" , qualified type , ")" ] ,
{ [ "const" ] , "method" , identifier , [ param list ] , [ ":" , type expr ] , ";"
| interface property } , "end" ;
init decl = "init" , param list , ";" , { var block } , block , ";" ;
copy decl = "copy" , param list , ";" , { var block } , block , ";" ;
done decl = "done" , ";" , { var block } , block , ";" ;
overlay type = "overlay" , { field decl | anon record } , "end" ;
anon record = "record" , [ "packed" ] ,
{ field decl | anon overlay } , "end" , ";" ;
anon overlay = "overlay" , { field decl | anon record } , "end" , ";" ;
field decl = identifier , ":" , type expr , [ ":" , expression ] , ";" ;
choices type = "choices" , "(" , choice value ,
{ "," , choice value } , ")" ;
choice value = identifier , [ "=" , expression ] ;
array type = "array" , [ "[" , [ expression , ".." , expression ] , "]" ] ,
"of" , type expr ;
pointer type = "ptr" , [ "to" , [ "const" ] , type expr ] ;
set type = "set" , "of" , ( expression , ".." , expression | type expr ) ;
routine type = "routine" , [ linkage ] , param list ,
[ ":" , type expr ] ;
type expr = builtin type | qualified type | pointer type | array type
| routine type
| owner type
| cpp type ;
owner type = ( "own" | "ref" | "weak" ) , type expr ;
qualified type = identifier , { "." , identifier } ;
builtin type = "int8" | "int16" | "int32" | "int64"
| "uint8" | "uint16" | "uint32" | "uint64"
| "float32" | "float64"
| "bool" | "char" | "wchar"
| "string" | "wstring"
| "ptr"
| "varargs" ;
cpp type = [ cv qualifier ] , cpp type name , [ cv qualifier ] ,
{ "*" , [ cv qualifier ] } , [ "&" | "&&" ] ;
cv qualifier = ( "const" | "volatile" ) , [ "const" | "volatile" ] ;
cpp type name = cpp fundamental , { cpp fundamental }
| [ elaborated key ] ,
cpp qualified name , [ template args ] , { "::" , identifier , [ template args ] }
| "decltype" , "(" , { character } , ")" ;
elaborated key = "struct" | "class" | "union" | "enum" ;
cpp fundamental = "void" | "bool" | "char" | "short" | "int" | "long" | "float"
| "double" | "signed" | "unsigned" | "auto"
| "wchar_t" | "char8_t" | "char16_t" | "char32_t" ;
cpp qualified name
= [ "::" ] , identifier , { "::" , identifier } ;
template args = "<" , [ template arg , { "," , template arg } ] , ">" ;
template arg = type expr | constant expression
| cpp type id ;
cpp type id = ? any other C++ text, verbatim, up to the argument's depth-0 "," or ">" ? ;
constant expression
= expression ;
Statements
block = "begin" , { statement } , "end" ;
statement = block , ";"
| if stmt | while stmt | for stmt | repeat stmt | match stmt
| guard stmt
| return stmt | leave stmt | skip stmt
| directive stmt
| memory stmt | exception stmt | io stmt | assert stmt
| var block | const block | type block
| cpp preprocessor | cpp block
| expression statement ;
if stmt = "if" , expression , "then" , { statement } ,
[ "else" , { statement } ] , "end" , ";" ;
while stmt = "while" , expression , "do" , { statement } , "end" , ";" ;
for stmt = "for" , identifier , ":=" , expression ,
( "to" | "downto" ) , expression , "do" ,
{ statement } , "end" , ";" ;
repeat stmt = "repeat" , { statement } , "until" , expression , ";" ;
match stmt = "match" , expression , "of" , { match arm } ,
[ "else" , { statement } ] , "end" , ";" ;
match arm = match label , { "," , match label } , ":" , { statement } ;
match label = expression , [ ".." , expression ] ;
guard stmt = "guard" , { statement } ,
[ "except" , { statement } ] ,
[ "finally" , { statement } ] ,
"end" , ";" ;
return stmt = "return" , [ expression ] , ";" ;
leave stmt = "leave" , ";" ;
skip stmt = "skip" , ";" ;
directive stmt = "@breakpoint" , ";"
| "@message" , severity , cstring , ";" ;
expression statement
= expression , ";" ;
Expressions
expression = assign expr ;
assign expr = cond expr , [ assign op , assign expr ] ;
assign op = ":=" | "+=" | "-=" | "*=" | "/="
| "%=" | "&=" | "|=" | "<<=" | ">>=" ;
cond expr = or expr , [ "?" , expression , ":" , cond expr ] ;
or expr = and expr , { ( "or" | "||" ) , and expr } ;
and expr = rel expr , { ( "and" | "&&" ) , rel expr } ;
rel expr = add expr , [ rel op , add expr | "is" , type expr ] ;
rel op = "=" | "<>" | "<" | ">" | "<=" | ">=" | "in"
| "<=>" ;
add expr = shift expr , { ( "+" | "-" | "|" | "xor" ) , shift expr } ;
shift expr = mul expr , { ( "shl" | "shr" | "<<" | ">>" ) , mul expr } ;
mul expr = unary expr ,
{ ( "*" | "/" | "div" | "mod" | "%" | "&" ) , unary expr
| "as" , type expr } ;
unary expr = prefix op , unary expr
| cpp cast , unary expr
| postfix expr ;
prefix op = "not" | "-" | "+" | "address" , "of"
| "!" | "~" | "*" | "&" | "++" | "--" ;
postfix expr = primary expr , { postfix op } ;
postfix op = "(" , [ arg list ] , ")"
| "[" , expression , "]"
| "." , member name
| "->" , member name
| "^"
| "++" | "--"
| braced init ;
arg list = expression , { "," , expression } ;
member name = identifier , [ template args ] ;
owner new = ( "own" | "ref" ) , type expr , [ "(" , [ arg list ] , ")" ] ;
primary expr = integer | float | cstring | cchar
| "true" | "false" | "nil"
| "self" | "parent"
| owner new
| identifier
| cpp name
| varargs expr
| type cast
| pointer cast
| set literal
| record literal
| intrinsic call
| cpp special
| cpp lambda
| cpp expression
| braced init
| "(" , expression , ")" ;
type cast = builtin type , "(" , expression , ")" ;
pointer cast = "ptr" , "to" , [ "const" ] , type expr ,
"(" , expression , ")" ;
set literal = "[" , [ set element , { "," , set element } ] , "]" ;
set element = expression , [ ".." , expression ] ;
record literal = qualified type , "(" , field init , { "," , field init } , ")" ;
field init = identifier , ":" , expression ;
varargs expr = "varargs" , "." , ( "count"
| "next" , "(" , type expr , ")"
| "get" , "(" , expression , "," , type expr , ")"
| "reset" , "(" , ")"
| "copy" , "(" , ")" ) ;
cpp name = cpp qualified name , [ template args ] ,
{ "::" , identifier , [ template args ] } ;
cpp special = "new" , cpp type name , [ "(" , [ arg list ] , ")"
| "[" , expression , "]"
| braced init ]
| "delete" , [ "[" , "]" ] , unary expr
| cpp named cast , template args , "(" , expression , ")"
| opaque group
| "nullptr" | "this" ;
opaque group = ( "sizeof" | "alignof" | "decltype" | "noexcept" | "typeid" ) ,
"(" , { character } , ")" ;
cpp named cast = "static_cast" | "reinterpret_cast" | "const_cast" | "dynamic_cast" ;
cpp cast = "(" , cpp type , ")" ;
braced init = "{" , [ arg list ] , "}" ;
cpp lambda = "[" , { character } , "]" , [ "(" , { character } , ")" ] ,
[ "->" , cpp type ] , "{" , { character } , "}" ;
Intrinsics
intrinsic call = "len" , "(" , expression , ")"
| "size" , "(" , type expr , ")"
| "utf8" , "(" , expression , ")"
| "paramcount" , "(" , ")"
| "paramstr" , "(" , expression , ")"
| "getmem" , "(" , expression , ")"
| "resizemem" , "(" , expression , "," , expression , ")"
| "exccode" , "(" , ")"
| "excmsg" , "(" , ")"
| "alive" , "(" , expression , ")"
| "lock" , "(" , expression , ")" ;
memory stmt = "create" , "(" , expression , ")" , ";"
| "destroy" , "(" , expression , ")" , ";"
| "getmem" , "(" , expression , ")" , ";"
| "freemem" , "(" , expression , ")" , ";"
| "resizemem" , "(" , expression , "," , expression , ")" , ";"
| "setlength" , "(" , expression , "," , expression , ")" , ";" ;
exception stmt = "raise" , "(" , expression , ")" , ";"
| "raisecode" , "(" , expression , "," , expression , ")" , ";" ;
io stmt = ( "print" | "println" ) , "(" , [ arg list ] , ")" , ";" ;
Unit Testing
test block = "test" , cstring , [ var block ] , block , ";" ;
assert stmt = assert1 , "(" , expression , ")" , ";"
| assert2 , "(" , expression , "," , expression , ")" , ";" ;
assert1 = "testAssert" | "testAssertTrue" | "testAssertFalse"
| "testAssertNil" | "testAssertNotNil" | "testFail" ;
assert2 = "testAssertEqualInt" | "testAssertEqualUInt"
| "testAssertEqualFloat" | "testAssertEqualStr"
| "testAssertEqualBool" | "testAssertEqualPtr" ;
Lexical
identifier = letter , { letter | digit | "_" } ;
letter = "A" .. "Z" | "a" .. "z" | "_" ;
digit = "0" .. "9" ;
hex digit = digit | "A" .. "F" | "a" .. "f" ;
integer = ( decimal | octal | hexadecimal | binary ) ,
[ int suffix | ud suffix ] ;
decimal = "0" | nonzero digit , { [ "'" ] , digit } ;
nonzero digit = "1" .. "9" ;
octal = "0" , octal digit , { [ "'" ] , octal digit } ;
octal digit = "0" .. "7" ;
hexadecimal = ( "0x" | "0X" ) , hex digit , { [ "'" ] , hex digit } ;
binary = ( "0b" | "0B" ) , ( "0" | "1" ) , { [ "'" ] , ( "0" | "1" ) } ;
int suffix = ( "u" | "U" ) , [ "l" | "L" | "ll" | "LL" | "z" | "Z" ]
| ( "l" | "L" | "ll" | "LL" | "z" | "Z" ) , [ "u" | "U" ] ;
float = ( decimal float | hex float ) , [ float suffix | ud suffix ] ;
decimal float = digits , "." , [ digits ] , [ exponent ]
| "." , digits , [ exponent ]
| digits , exponent ;
digits = digit , { [ "'" ] , digit } ;
exponent = ( "e" | "E" ) , [ "+" | "-" ] , digits ;
hex float = ( "0x" | "0X" ) , hex digit , { hex digit } , [ "." , { hex digit } ] ,
( "p" | "P" ) , [ "+" | "-" ] , digits ;
float suffix = "f" | "F" | "l" | "L" | "f16" | "F16" ;
ud suffix = identifier ;
cstring = ( [ cstring prefix ] , '"' , { character | escape } , '"'
| raw string ) , [ ud suffix ] ;
cstring prefix = "u8" | "u" | "U" | "L" ;
raw string = [ cstring prefix ] , 'R"' , delimiter , "(" , { character } , ")" ,
delimiter , '"' ;
delimiter = { character } ;
cchar = [ cstring prefix ] , "'" , { character | escape } , "'" , [ ud suffix ] ;
escape = "\" , character ;
comment = line comment | block comment ;
line comment = "//" , { character } , newline ;
block comment = "/*" , { character } , "*/" ;
newline = LF | CR , LF | CR ;
line splice = "\" , { space | tab | FF | VT } , newline ;
character = ? any source character ? ;
LF = ? line feed, U+000A ? ;
CR = ? carriage return, U+000D ? ;
space = " " ;
tab = ? horizontal tab, U+0009 ? ;
FF = ? form feed, U+000C ? ;
VT = ? vertical tab, U+000B ? ;
C++ Integration
cpp preprocessor
= ( "#" | "%:" ) , { character } , newline ;
cpp placement = "cpp" , ( "header" | "source" ) , ";" ;
cpp block = "cppstart" , ( "header" | "source" ) ,
{ character } , "cppend" , ";" ;
cpp expression = "cpp" , "(" , cstring , ")" ;
cpp declaration = cpp first token , { character } ;
cpp first token = ? any token at module level that is not a starter ? ;
starter = "var" | "const" | "type"
| "routine" | "forward" | "exported" | "cpp" | "cppstart" | "begin" | "end" | "test"
| "initialize" | "finalize"
| "import"
| directive | cpp preprocessor ;