Skip to content

Grammar

Positron edited this page Aug 4, 2017 · 13 revisions

The grammar of the BCS language is shown below. For the common user, this information might not be very useful. This information is targeted more towards compiler and tool writers, or for the curious user.

The (empty) terminal indicates that the rule is optional. // denotes the start of a one-line comment.

module:
   module-body

module-body:
   module-item-list
   (empty)

module-item-list:
   module-item
   module-item-list module-item

module-item:
   pseudo-directive
   namespace-member

// The names of pseudo directives are context-sensitive keywords.
pseudo-directive:
   # include string
   # import string
   # library string
   # linklibrary string
   # define identifier expression
   // The zcommon.acs file #defines `true` and `false`. In BCS, `true` and
   // `false` are keywords, so a syntax error will be generated when #including
   // the zcommon.acs file. To support the inclusion of the zcommon.acs file,
   // ignore the #defines of `true` and `false`.
   # define true 1
   # define false 0
   # libdefine identifier expression
   # encryptstrings
   # nocompact
   # wadauthor
   # nowadauthor
   # region
   # endregion

namespace:
   namespace-header { namespace-member-list }
   namespace-header { }

namespace-header:
   namespace-visibility strict namespace
   namespace-visibility strict namespace namespace-name
   namespace-visibility namespace namespace-name
   private namespace

namespace-visibility:
   private
   (empty)

namespace-name:
   identifier
   namespace-name . identifier

namespace-member-list:
   namespace-member
   namespace-member-list namespace-member

namespace-member:
   namespace
   using
   declaration
   script
   special
   ;

using:
   using path ; // Makes every object in the namespace available.
   using path : import-list ;

path:
   upmost // Upmost namespace.
   namespace // Current namespace.
   identifier
   path . identifier

import-list:
   import-item
   import-list , import-item

import-item:
   enum import-name
   enum import-name = import-name
   struct import-name
   struct import-name = import-name
   type-name
   type-name = type-name
   identifier
   identifier = identifier

import-name:
   identifier
   type-name

declaration:
   specifier-declaration
   object-declaration

specifier-declaration:
   specifier-visibility enumeration ;
   specifier-visibility structure ;
   specifier-visibility type-alias ;

specifier-visibility:
   private
   (empty)

enumeration:
   enum enumeration-name enumeration-base enumeration-body

enumeration-name:
   identifier
   type-name
   (empty)

enumeration-base:
   : enumeration-base-type
   (empty)

enumeration-base-type:
   int
   fixed
   bool
   str

enumeration-body:
   { enumerator-list }
   { enumerator-list , }

enumerator-list:
   enumerator
   enumerator-list , enumerator

enumerator:
   identifier
   identifier = expression

structure:
   struct structure-name { structure-member-list }

structure-name:
   identifier
   (empty)

structure-member-list:
   structure-member
   structure-member-list structure-member

structure-member:
   extended-specifier reference structure-member-instance-list ;

structure-member-instance-list:
   structure-member-instance
   structure-member-instance-list , structure-member-instance

structure-member-instance:
   identifier
   identifier dimension-list

object-declaration:
   visibility variable
   visibility function

visibility:
   private
   extern
   static
   (empty)

variable:
   storage extended-specifier reference instance-list ;
   auto auto-instance-list ;

storage:
   world
   global
   (empty)

storage-index:
   decimal-number :
   (empty)

auto:
   auto
   auto enum

extended-specifier:
   enumeration
   structure
   specifier

specifier:
   raw
   int
   fixed
   bool
   str
   void
   enum path
   struct path
   type-name

reference:
   reference-structure
   reference-structure reference-list
   reference-list
   (empty)

reference-structure:
   reference-storage reference-marker

reference-storage:
   reference-storage-name
   reference-storage-name : decimal-number
   (empty)

reference-storage-name:
   world
   global

reference-marker:
   &
   ?

reference-list:
   reference-item
   reference-item reference-list

reference-item:
   reference-storage dimension-list reference-marker
   ( parameter-list-declaration ) reference-marker

instance-list:
   instance
   instance-list , instance

instance:
   instance-name
   instance-name = initializer
   instance-name dimension-list
   instance-name dimension-list = initializer

instance-name:
   storage-index identifier

auto-instance-list:
   auto-instance
   auto-instance-list auto-instance

auto-instance:
   identifier = initializer

dimension-list:
   [ expression ]
   [ ]
   dimension-list [ expression ]
   dimension-list [ ]

initializer:
   expression
   braced-initializer

braced-initializer:
   { initializer-list }
   { initializer-list , }

initializer-list:
   initializer
   initializer-list , initializer

function:
   function-keyword function-return identifier (
      parameter-list-declaration ) function-body

function-keyword:
   function
   (empty)

function-return:
   extended-specifier reference
   auto

parameter-list-declaration:
   parameter-list
   void
   (empty)

parameter-list:
   parameter
   parameter-list , parameter

parameter:
   specifier parameter-name parameter-initializer

parameter-name:
   identifier
   (empty)

function-body:
   block-statement
   ;

type-alias:
   typedef extended-specifier reference type-alias-instance-list
   typedef function-keyword function-return type-name (
      parameter-list-declaration )

type-alias-instance-list:
   type-alias-instance
   type-alias-instance-list , type-alias-instance

type-alias-instance:
   type-name dimension-list
   type-name

script:
   script script-tag script-parameter-parentheses script-type
      script-flag statement

script-tag:
   << 0 >>
   // When reading the script number, function calls are not parsed because
   // they conflict with the start of the parameter list.
   expression

script-parameter-parentheses:
   ( script-parameter-list )
   ( void )
   ( )
   (empty)

script-parameter-list:
   script-parameter
   script-parameter-list , script-parameter

script-parameter:
   script-parameter-type identifier
   script-parameter-type

script-parameter-type:
   raw
   int

// The script types are context-sensitive keywords. 
script-type:
   bluereturn
   death
   disconnect
   enter
   event
   kill
   lightning
   open
   pickup
   redreturn
   reopen
   respawn
   return
   unloading
   whitereturn
   (empty)

// The script flags are context-sensitive keywords. 
script-flag:
   script-flag net
   script-flag clientside
   (empty)

special:
   special special-list ;

special-list:
   special-item
   special-list , special-item

special-item:
   special-sign decimal-number : identifier ( special-parameter-list )
      special-return

special-sign:
   - // If '-' is specified, the item is an extension function. Otherwise, the
     // item is an action-special.
   (empty)

special-parameter-list:
   special-parameter-list-minmax
   special-parameter-list-type
   (empty)

special-parameter-list-minmax:
   decimal-number // Maximum parameters.
   decimal-number , decimal-number // Minimum parameters, ',',
                                   // maximum parameters.

special-parameter-list-type:
   // Required parameters, ';', optional parameters. 
   special-parameter-list ; special-parameter-list
   ; special-parameter-list

special-parameter-list:
   special-parameter-type
   special-parameter-list , special-parameter-type

special-parameter-type:
   raw
   int
   fixed
   bool
   str

special-return:
   : special-return-type
   (empty)

special-return-type:
   raw
   int
   fixed
   bool
   str
   void

statement:
   local-declaration
   local-using
   block-statement
   if-statement
   switch-statement
   case-label
   while-statement
   do-statement
   for-statement
   foreach-statement
   jump-statement
   script-jump-statement
   return-statement
   goto-statement
   label
   palette-translation
   assert
   buildmsg
   inline-assembly
   empty-statement
   expression-statement

statement-list:
   statement
   statement-list statement

local-declaration:
   let declaration

local-using:
   let using

let:
   let
   (empty)

block-statement:
   { statement-list }
   { }

if-statement:
   if ( expression ) statement
   if ( expression ) statement else statement

condition:
   condition-variable
   expression

condition-variable:
   let specifier identifier = initializer
   let auto identifier = initializer

heavy-condition:
   condition-variable
   condition-variable ; expression
   expression

switch-statement:
   switch ( heavy-condition ) statement

case-label:
   case expression :
   default :

while-statement:
   while ( condition ) statement
   until ( condition ) statement

do-statement:
   do statement while ( expression ) ;
   do statement until ( expression ) ;

for-statement:
   for ( for-initialization for-condition for-post ) statement

for-initialization:
   let variable
   expression-list ;
   ;

for-condition:
   condition ;
   ;

for-post:
   expression-list
   (empty)

foreach-statement:
   foreach ( foreach-item expression ) statement

foreach-item:
   foreach-variable ;
   foreach-variable ; foreach-variable ;
   foreach-variable , identifier ;

foreach-variable:
   let specifier identifier
   let auto identifier

jump-statement:
   break ;
   continue ;

script-jump-statement:
   terminate ;
   suspend ;
   restart ;

return-statement:
   return ;
   return expression ;
   return buildmsg

goto-statement:
   goto identifier ;

label:
   identifier :

palette-translation:
   createtranslation ( expression )
   createtranslation ( expression , palette-range-list )

palette-range-list:
   palette-range
   palette-range-list , palette-range

palette-range:
   // NOTE: Assignment is not parsed in the second expression because it will
   // conflict with the following assignment token.
   expression : expression = palette-range-value

palette-range-value:
   expression : expression
   palette-range-rgb
   % palette-range-rgb
   # [ expression , expression , expression ]
   @ expression [ expression , expression , expression ]
   
palette-range-rgb:
   [ expression , expression , expression ] :
      [ expression , expression , expression ]

assert:
   assert ( expression ) ;
   assert ( expression , string ) ;
   static assert ( expression ) ;
   static assert ( expression , string ) ;

buildmsg:
   buildmsg ( expression ) block-statement

// The newline character becomes significant for inline-assembly.
// It is the terminating token of a line of inline-assembly code.
inline-assembly:
   > inline-assembly-opcode newline
   > inline-assembly-opcode inline-assembly-argument-list newline

inline-assembly-opcode:
   identifier
   terminate
   restart
   suspend
   goto

inline-assembly-argument-list:
   expression
   inline-assembly-argument-list , expression

inline-assembly-argument:
   number
   identifier
   string
   ( expression )

empty-statement:
   ;

expression-statement:
   expression-list ;

expression-list:
   expression
   expression-list , expression

expression:
   assignment

assignment:
   conditional
   conditional =   assignment
   conditional +=  assignment
   conditional -=  assignment
   conditional *=  assignment
   conditional /=  assignment
   conditional %=  assignment
   conditional <<= assignment
   conditional >>= assignment
   conditional &=  assignment
   conditional ^=  assignment
   conditional |=  assignment

conditional:
   logical-or
   logical-or ? expression : conditional
   logical-or ? : conditional

logical-or:
   logical-and
   logical-or || logical-and

logical-and:
   bitwise-or
   logical-and && bitwise-or

bitwise-or:
   bitwise-xor
   bitwise-or | bitwise-xor

bitwise-xor:
   bitwise-and
   bitwise-xor ^ bitwise-and

bitwise-and:
   equality
   bitwise-and & equality

equal:
   less-than
   equal == less-than
   equal != less-than

less-than:
   bitwise-shift
   less-than <  bitwise-shift
   less-than <= bitwise-shift
   less-than >  bitwise-shift
   less-than >= bitwise-shift
 
bitwise-shift:
   addition
   bitwise-shift << addition
   bitwise-shift >> addition

addition:
   multiplication
   addition + multiplication
   addition - multiplication

multiplication:
   prefix
   multiplication * prefix
   multiplication / prefix
   multiplication % prefix

prefix:
   suffix
   ++ prefix
   -- prefix
   -  prefix
   +  prefix
   !  prefix
   ~  prefix

suffix:
   primary
   suffix ++
   suffix --
   suffix [ expression ]
   suffix call
   suffix . identifier
   suffix ! !

call:
   ( )
   ( expression-list )
   ( format-item-list )
   ( format-item-list ; expression-list )

format-item-list:
   format-item
   format-item-list , format-item

format-item:
   format-cast : expression
   format-item-array

format-cast:
   // Valid value: [abcdfiklnsx]
   identifier

format-item-array:
   a : expression
   a : ( expression )
   a : ( expression , expression )
   a : ( expression , expression , expression )

primary:
   strcpy
   memcpy
   conversion
   parentheses
   identifier
   number
   string
   character
   upmost
   namespace
   true
   false
   null

strcpy:
   strcpy strcpy-call

strcpy-call:
   ( strcpy-source-argument , expression )
   ( strcpy-source-argument , expression , expression )

strcpy-source-argument:
   format-item-array
   expression

memcpy:
   memcpy strcpy-call

conversion:
   int ( expression )
   fixed ( expression )
   bool ( expression )
   str ( expression )

parentheses:
   cast
   compound-literal
   function-literal
   ( expression )

cast:
   ( raw ) prefix
   ( int ) prefix
   ( fixed ) prefix
   ( bool ) prefix
   ( str ) prefix

compound-literal:
   ( compound-literal-static specifier ) braced-initializer
   ( compound-literal-static specifier dimension-list )
      braced-initializer
   ( compound-literal-static specifier dimension-list ) string

compound-literal-static:
   static
   (empty)

function-literal:
   ( function-literal-header ) block-statement

function-literal-header:
   function-literal-static function-keyword function-literal-return (
      parameter-list-declaration )

function-literal-static:
   static
   (empty)

function-literal-return:
   specifier
   auto

identifier:
   [a-zA-Z_][a-zA-Z0-9_]*

type-name:
   (([a-zA-Z_][a-zA-Z0-9_]*)?[a-z_])?T

number:
   binary-number
   octal-number
   decimal-number
   hexadecimal-number
   fixed-point-number
   radix-number

binary-number:
   0[bB][0-1]+([']?[0-1]+)*

octal-number:
   0[oO][0-7]+([']?[0-7]+)*

decimal-number:
   [0-9]+([']?[0-9]+)*

hexadecimal-number:
   0[xX]([']?[0-9a-fA-F])*

fractional-number:
   [0-9]+([']?[0-9]+)*[.]([0-9]+([']?[0-9]+)*)?

radix-number:
   [0-9]+([']?[0-9]+)*[_rR]([']?[0-9a-zA-Z]+)*

string:
   "([^\\"]|\\.)*"

character:
   '.'
   ' character-escape-sequence '

character-escape-sequence:
   \\a
   \\b
   \\n
   \\t
   \\v
   \\f
   \\r
   \\'
   \\\\
   \\[oO][0-7]+
   \\[xX][0-9a-fA-F]+

newline:
   // Newline character

comment:
   [/][/][^\n]+ // Single-line comment.
   [/][*]([^*]*[*]+)+[/] // Multi-line comment.

(empty):
   // The rule is optional.
Keywords

Certain identifiers are reserved by the language and are used in specific ways. They cannot be used as names for your own objects. These identifiers are:

  1. assert
  2. auto
  3. bool
  4. break
  5. buildmsg
  6. case
  7. const
  8. continue
  9. createtranslation
  10. default
  11. do
  12. else
  13. enum
  14. extern
  15. false
  16. fixed
  17. for
  18. foreach
  19. function
  20. global
  21. goto
  22. if
  23. int
  24. let
  25. memcpy
  26. namespace
  27. null
  28. private
  29. raw
  30. restart
  31. return
  32. script
  33. special
  34. static
  35. str
  36. strcpy
  37. strict
  38. struct
  39. suspend
  40. switch
  41. terminate
  42. true
  43. typedef
  44. until
  45. upmost
  46. using
  47. void
  48. while
  49. world
Context-sensitive keywords

The following identifiers are keywords only in specific places:

  1. bluereturn
  2. clientside
  3. death
  4. define
  5. disconnect
  6. encryptstrings
  7. endregion
  8. enter
  9. event
  10. import
  11. include
  12. kill
  13. libdefine
  14. library
  15. lightning
  16. linklibrary
  17. net
  18. nocompact
  19. nowadauthor
  20. open
  21. pickup
  22. redreturn
  23. region
  24. reopen
  25. respawn
  26. unloading
  27. wadauthor
  28. whitereturn
Special identifiers that are usable as normal identifiers in BCS

Some identifiers that are known to have a special meaning in ACS and BCS can also be used as normal identifiers. You can use these identifiers as names for your objects. These identifiers are:

  1. acs_executewait
  2. acs_namedexecutewait
  3. bluereturn
  4. clientside
  5. death
  6. define
  7. disconnect
  8. encryptstrings
  9. endregion
  10. enter
  11. event
  12. hudmessage
  13. hudmessagebold
  14. import
  15. include
  16. kill
  17. libdefine
  18. library
  19. lightning
  20. linklibrary
  21. log
  22. net
  23. nocompact
  24. nowadauthor
  25. open
  26. pickup
  27. print
  28. printbold
  29. redreturn
  30. region
  31. reopen
  32. respawn
  33. strparam
  34. unloading
  35. wadauthor
  36. whitereturn