Skip to content
PaskalCPP
Reference

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 as type expr, is one name.
  • a , b is a followed by b; a | b is a or b.
  • [ a ] is an optional a; { a } is a zero 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

grammar
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

grammar
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

grammar
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

grammar
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

grammar
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

grammar
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

grammar
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

grammar
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

grammar
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

grammar
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 ;