Jamie Balfour

Welcome to my personal website.

Find out more about me, my personal projects, reviews, courses and much more here.

Official ZPE/YASS documentationYASS formal specification

The following is the official YASS formal specification (actually it's Backus–Naur Form) for the latest version of YASS. The ε represents a termination case.

ε symbolises syntactic termination (i.e. the end of a rule)

ZPE/YASS formal specification


ZPE 1.14.12 (December 2026)


The following productions describe the current YASS language. They replace or


extend the corresponding productions in earlier formal specifications.


1. Lexical tokens and modifiers


-------------------------------


⟨scope_resolution_operator⟩
  ::


⟨object_access_operator⟩
  ->


⟨inheritance_keyword⟩
  inherits
  extends


⟨scope⟩
  public
  private
  protected
  friendly


⟨static_modifier⟩
  static


⟨method_modifiers⟩
  ⟨scope⟩ ⟨static_modifier⟩


| ⟨scope⟩
  ||

| ⟨static_modifier⟩


| ε


⟨keyword⟩
  assert
  break
  case
  catch
  class
  component
  count


| default | do | each | else | elseif | end | enum | enumerator
  ||

| extends | finally | for | from | function | global | goto


| if | implements | import | include | includes | inherits | in


| is | is_set | label | let | match | module | namespace | new


| not | public | private | protected | record | return | static


| structure | super | switch | test | to | try | type | typeof


| unset | until | var | when | while | async | await | continue


The spelling include is preferred. includes remains accepted for compatibility.


2. Program and body forms


--------------------------


⟨program⟩
  ⟨construct_body⟩


⟨construct_body⟩
  ⟨body⟩ ⟨construct_body⟩
  ε


⟨body⟩
  ⟨assert⟩
  ⟨import⟩
  ⟨include⟩
  ⟨assign⟩
  ⟨declaration⟩


| ⟨function⟩ | ⟨component⟩ | ⟨if⟩ | ⟨for⟩ | ⟨for_to⟩
  ||

| ⟨for_each⟩ | ⟨until⟩ | ⟨while⟩ | ⟨do_while⟩ | ⟨when⟩


| ⟨match_statement⟩ | ⟨lambda_call⟩ | ⟨function_call⟩


| ⟨object_accessor⟩ | ⟨scope_resolution⟩ | ⟨increment⟩


| ⟨decrement⟩ | ⟨module⟩ | ⟨structure⟩ | ⟨enum⟩ | ⟨record⟩


| ⟨return⟩ | ⟨break⟩ | ⟨label⟩ | ⟨goto⟩ | ⟨breakpoint⟩


| ⟨scope_block⟩ | ⟨unset⟩


⟨term⟩
  ⟨identifier⟩
  ⟨variable⟩
  ⟨increment⟩
  ⟨decrement⟩


| ⟨value⟩ | ⟨lambda_call⟩ | ⟨function_call⟩
  ||

| ⟨object_accessor⟩ | ⟨scope_resolution⟩ | ⟨power⟩


| ⟨match_expression⟩ | ⟨matcher_expression⟩


| ⟨conditional_expression⟩ | ⟨count⟩ | ⟨cast⟩


| ⟨arrow_function⟩ | ( ⟨expression⟩ )


3. Functions, methods, and annotations


---------------------------------------


⟨function⟩
  ⟨annotations⟩ function ⟨identifier⟩


( ⟨formal_parameters⟩ ) ⟨function_type⟩ ⟨construct_body⟩
  ||

end function


| ⟨annotations⟩ function ⟨identifier⟩


( ⟨formal_parameters⟩ ) ⟨function_type⟩


{ ⟨construct_body⟩ }


⟨method⟩
  ⟨annotations⟩ ⟨method_modifiers⟩ function ⟨identifier⟩


( ⟨formal_parameters⟩ ) ⟨function_type⟩ ⟨construct_body⟩
  ||

end function


| ⟨annotations⟩ ⟨method_modifiers⟩ function ⟨identifier⟩


( ⟨formal_parameters⟩ ) ⟨function_type⟩ { ⟨construct_body⟩ }


⟨annotations⟩
  ⟨annotation⟩ ⟨annotations⟩
  ε


⟨annotation⟩
  @doc ⟨annotation_value⟩


| @author ⟨annotation_value⟩
  ||

| @date ⟨annotation_value⟩


| @directive ⟨annotation_value⟩


| @compile ⟨compile_value⟩


| @requires return


| @requires permission ⟨integer⟩


| @router ⟨annotation_value⟩


| @request ⟨annotation_value⟩


| @get ⟨annotation_value⟩


| @post ⟨annotation_value⟩


| @put ⟨annotation_value⟩


| @patch ⟨annotation_value⟩


| @delete ⟨annotation_value⟩


| @head ⟨annotation_value⟩


| @options ⟨annotation_value⟩


| @any ⟨annotation_value⟩


@requires return requires the function to leave with a non-null return value.


The requirement is checked when execution leaves the function, including an


explicit return and normal fall-through. The compiler rejects functions that


can be proven not to return a value.


@requires permission N requires the active ZPE permission level to be at least


N before the function body begins. User-defined functions default to level 0.


Asynchronous functions were introduced in ZPE 1.14.12:


⟨async_function⟩
  async function ⟨identifier⟩


( ⟨formal_parameters⟩ ) ⟨function_type⟩ ⟨construct_body⟩
  ||

end function


| async function ⟨identifier⟩


( ⟨formal_parameters⟩ ) ⟨function_type⟩


{ ⟨construct_body⟩ }


⟨await_expression⟩
  await ⟨term⟩


An async function invocation starts execution on the ZPE asynchronous executor
  ||

and returns a Future object immediately. It does not block the calling function.


The await expression blocks the calling function until that Future completes and


then evaluates to the async function's returned value. If the async function


fails, await raises the corresponding runtime error in the calling function.


Future objects expose these native methods:


await()       waits for completion and returns the result


done()        returns true when execution has completed, otherwise false


on_complete(f) registers f as an asynchronous completion callback and returns


the Future object; f receives the completed result


Calling an async function without await is valid for fire-and-forget work. A


Future is not constructed directly by YASS; it is created only by an async


function invocation.


The scheduled callback functions run_in and run_at use the same asynchronous


executor and Future-compatible execution model. They accept a callable and


schedule its invocation without executing it on the timer thread.


4. Parameters, return types, and declarations


----------------------------------------------


⟨formal_parameters⟩
  ⟨formal_parameter⟩ , ⟨formal_parameters⟩


| ⟨formal_parameter⟩ | ε
  ||

⟨formal_parameter⟩
  ⟨variable⟩


| ⟨type_expression⟩ ⟨variable⟩
  ||

| ⟨type_expression⟩ ⟨variable⟩ = ⟨expression⟩


⟨function_type⟩
  : ⟨type_expression⟩
  ε


⟨declaration⟩
  var ⟨variable_declaration⟩


| let ⟨variable_declaration⟩
  ||

| type ⟨identifier⟩ = ⟨type_expression⟩


⟨type_expression⟩
  string
  number
  boolean
  object
  record
  list


| map | fn | mixed | ⟨identifier⟩
  ||

| list < ⟨type_expression⟩ >


| map < ⟨type_expression⟩ , ⟨type_expression⟩ >


| ⟨type_expression⟩ [ ⟨integer⟩ ]


Type aliases are compile-time names for type expressions, for example:


type UserID = number


type Scores = list<number>


Typed collections and fixed-size arrays are checked when values are assigned,


passed as arguments, or returned from functions. Multidimensional arrays are


formed by repeating the indexed type suffix.


5. Instance and inherited-member access


----------------------------------------


⟨object_root⟩
  ⟨variable⟩
  this
  super


⟨object_member⟩
  ⟨variable⟩
  ⟨identifier⟩
  ⟨function_call⟩


| ⟨lambda_call⟩
  ||

⟨object_accessor⟩
  ⟨object_root⟩ ⟨object_access_operator⟩ ⟨object_member⟩


| ⟨object_accessor⟩ ⟨object_access_operator⟩ ⟨object_member⟩
  ||

Nested access is permitted, including UI->Button->set_text(). The variable


form permits a variable to supply the member name, for example $object->$name.


super is valid inside an instance method and begins method lookup at the parent


of the current structure while retaining the current child instance.


6. Static, module, enum, and object-member access


-------------------------------------------------


⟨scope_resolution_root⟩
  ⟨identifier⟩


⟨scope_resolution_member⟩
  ⟨identifier⟩
  ⟨variable⟩
  ⟨function_call⟩


⟨scope_resolution⟩
  ⟨scope_resolution_root⟩


:: ⟨scope_resolution_member⟩
  ||

Examples:


Math::random_number()


Person::get_people_list()


Status::OK


Static methods and properties belong to their declaring structure and do not


construct an instance. Private static members cannot be called externally.


7. Structures, inheritance, interfaces, and enums


--------------------------------------------------


⟨structure_id⟩
  structure
  struct
  class


⟨inherits⟩
  inherits ⟨identifier⟩
  extends ⟨identifier⟩
  ε


⟨implements⟩
  implements ⟨identifier⟩ , ⟨implements⟩


| implements ⟨identifier⟩ | ε
  ||

⟨structure⟩
  ⟨structure_id⟩ ⟨identifier⟩ ⟨inherits⟩ ⟨implements⟩


⟨namespace⟩ ⟨structure_inner⟩ end structure
  ||

| ⟨structure_id⟩ ⟨identifier⟩ ⟨inherits⟩ ⟨implements⟩


{ ⟨namespace⟩ ⟨structure_inner⟩ }


⟨structure_inner⟩
  ⟨structure_member⟩ ⟨structure_inner⟩
  ε


⟨structure_member⟩
  ⟨variable⟩
  ⟨assign⟩
  ⟨method⟩


⟨interface⟩
  interface ⟨identifier⟩ ⟨interface_inner⟩ end interface


| interface ⟨identifier⟩ { ⟨interface_inner⟩ }
  ||

⟨interface_inner⟩
  ⟨interface_method⟩
  ⟨interface_method⟩ ⟨interface_inner⟩


⟨interface_method⟩
  public function ⟨identifier⟩


( ⟨formal_parameters⟩ ) ⟨function_type⟩
  ||

Interfaces may contain default method bodies where supported. A structure that


declares implements must satisfy every interface method contract.


⟨enum⟩
  enum ⟨identifier⟩ ⟨enum_member⟩* end enum


| enumerator ⟨identifier⟩ ⟨enum_member⟩* end enumerator
  ||

⟨enum_member⟩
  ⟨identifier⟩ = ⟨expression⟩


Enum members are accessed with the scope-resolution operator and must have an
  ||

assigned value.


8. Conditional, matcher, arrow, and selection expressions


----------------------------------------------------------


⟨conditional_expression⟩
  ⟨term⟩ if ⟨condition⟩ else ⟨term⟩


Only the selected branch is evaluated. The established ? ternary syntax remains
  ||

valid.


⟨arrow_function⟩
  ( ⟨formal_parameters⟩ ) => ⟨expression⟩


| ⟨variable⟩ => ⟨expression⟩
  ||

⟨matcher_expression⟩
  matcher ( ⟨matcher_entries⟩ ⟨matcher_default⟩ )


⟨matcher_entry⟩
  ⟨literal⟩ => ⟨expression⟩ ;


⟨matcher_default⟩
  else => ⟨expression⟩ ;
  ε


Matcher keys are literals, duplicate keys are compile-time errors, and only the
  ||

selected result expression is evaluated. A matcher without a matching key or


else entry returns null.


Match expressions evaluate their comparator once and test candidates in source


order. When-is and switch-case retain first-branch-wins behaviour.


9. Template strings


-------------------


⟨template_string⟩
  ` ⟨template_content⟩ `


⟨template_content⟩
  ⟨literal_text⟩ ⟨template_content⟩


| {{ ⟨expression⟩ }} ⟨template_content⟩
  ||

| ε


Template interpolation uses double braces. A normal variable is written as


{{$name}}, while an expression may be written as {{function_call()}}.


Templates are compiled into reusable expression fragments and only interpolated


expressions are evaluated at runtime.


10. Components


-------------


⟨component⟩
  component ⟨identifier⟩ ⟨component_content⟩ end component


| component ⟨identifier⟩ { ⟨component_content⟩ }
  ||

⟨component_content⟩
  ⟨component_text⟩ ⟨component_content⟩


| {{ ⟨expression⟩ }} ⟨component_content⟩
  ||

| ε


Components are named, compiled renderable values. Their content is not parsed


as ordinary YASS statements. A component may be called using its identifier and


an object or map of interpolation values:


component page


<h1>Hello, {{$name}}</h1>


end component


print(page({"name" : "Jamie"}))


Components use the same {{...}} interpolation form as template strings. A


component call returns its rendered text. Components are registered in the


compiled-program index and may be removed with:


unset(page)


After removal, the component identifier is no longer callable. Components are


not ordinary functions and do not use a function body or function return type.


11. Indentation-based blocks


----------------------------


⟨indented_header⟩
  if ⟨condition⟩ :


| else if ⟨condition⟩ :
  ||

| elseif ⟨condition⟩ :


| else :


| for ⟨for_header⟩ :


| while ⟨condition⟩ :


| function ⟨function_header⟩ :


| class ⟨identifier⟩ ⟨inherits⟩ :


| structure ⟨identifier⟩ ⟨inherits⟩ :


| module ⟨identifier⟩ :


| switch ⟨switch_header⟩ :


| try : | catch ⟨catch_header⟩ : | finally :


⟨indented_block⟩
  ⟨indented_header⟩ NEWLINE INDENT


⟨construct_body⟩ DEDENT
  ||

Tabs count as four spaces. Explicit end clauses remain accepted.


12. Assignment, mutation, and removal


--------------------------------------


⟨assignment⟩
  ⟨variable⟩ = ⟨expression⟩


| ⟨variable⟩ , ⟨variable_list⟩ = ⟨expression⟩
  ||

| ⟨accessor⟩ ⟨assignment_operator⟩ ⟨expression⟩


⟨assignment_operator⟩
  =
  +=
  -=
  *=
  /=
  %=
  **=


Multiple assignment permits forms such as $x, $y = get_values(). For lists and
  ||

arrays, += appends the assigned value to the collection.


⟨unset⟩
  unset ( ⟨identifier_or_accessor⟩ )


⟨is_set⟩
  is_set ( ⟨identifier_or_accessor⟩ )


unset removes a variable, member, or registered component identified by its
  ||

argument. is_set tests whether the identifier or accessor is currently bound.


13. Web request and response extensions


----------------------------------------


Web functions may be annotated with routing annotations such as @router,


@get, @post, @put, @patch, @delete, @head, @options, and @any. Request objects


provide access to the method, path, content type, body, and cookies.


Response objects support text bodies, binary bodies, downloadable responses,


and development-server session cookies. These are runtime APIs rather than


additional core expression productions.


14. Semantic and compatibility constraints


-------------------------------------------


1. A static call does not construct an object; this and instance properties are


unavailable in a static method.


2. super is valid only inside an instance method with an inherited implementation.


3. super->method() starts lookup at the parent of the current structure.


4. The inherited implementation still operates on the current child instance.


5. Private parent methods cannot be invoked through super.


6. Interface compliance is checked at compile time and safeguarded at runtime


for dynamically loaded compiled programs.


7. Only selected conditional, matcher, match, and component expressions are


evaluated; unused branches are lazy.


8. Explicit end clauses remain compatible with indentation-based syntax.


9. Object access and scope resolution may be nested to arbitrary supported depth.


10. Older compiled programs using the .yex extension remain loadable; current


compiled programs use .zex.


Availability


------------


Inheritance, structures, modules, templates, records, and object access existed


before 1.14.9. Their grammar and runtime behaviour were expanded in later


releases.


ZPE 1.14.9 enabled interfaces and enums by default and introduced or formalised


ZEQL, database access, project compilation and resources, web routing/YWP,


inheritance improvements, super, static structure methods, match/matcher


expressions, indentation syntax, and typed arrays.


ZPE 1.14.10 added typed collections, type aliases, default interface methods,


native UI, project manifests, resource bundling, ZenLang, Graphics, NativeUIKit,


and expanded native runtime support.


ZPE 1.14.11 changed template and component interpolation to {{...}}, added


components and component removal, added @requires return and


@requires permission N, and expanded web request and response support.
      
Comments

There are no comments on this page.

New comment

Comments are welcome and encouraged, including disagreement and critique. However, this is not a space for abuse. Disagreement is welcome; personal attacks, harassment, or hate will be removed instantly. This site reflects personal opinions, not universal truths. If you can’t distinguish between the two, this probably isn’t the place for you. The system temporarily stores IP addresses and browser user agents for the purposes of spam prevention, moderation, and safeguarding. This data is automatically removed after fourteen days. Your email address is stored so that replies can be sent to your email address.

Comments powered by BalfComment

Feedback 👍
Comments are sent via email to me.