Skip to content

Parser rules and grammar definitions for the Kemet programming language.

License

Notifications You must be signed in to change notification settings

kemet-lang/rules

Repository files navigation


Kemet-Logo

Kemet-Desc

line
  • Syntax Rules

    1. Type

      Primitive
          | type                      # e.g. `bool, i32, u32, ..`
      
          | bool                      # e.g. `let x : bool   = true`
          | cint                      # e.g. `let x : cint   = 9999`
          | cflt                      # e.g. `let x : cflt   = 3.14`
          | und_t                     # e.g. `let x : und_t  = und`
          | null_t                    # e.g. `let x : null_t = null`
          | any                       # e.g. `let x : any    = true`
      
          | void                      # e.g. `fn x() -> void { /* no return stmt requierd */ }`
          | err                       # e.g. `def e = errse t{ e1, ... }; let x : err = e.e1`
      
          | i[0-65535]                # Signed
          | u[0-65535]                # Unsigned
      
          | f[16,32,64,80,128]        # Float
      Identifier
          | x                         # .g. `def MyStruct = struct { ... }; let x : MyStruct = new MyStruct { ... };`
      Optional
          | ?type                     # e.g. `let x : ?i32 = null`
      Pointer
          | *mut type                 # e.g. `let y: i32 = 0; let x: *i32 = &y`
      Array
          | [expr] mut type           # e.g. `let x : [3]u8 = [0, 1, 2]`
      Tuple
          | (type, ..)                # e.g. `let x : ,{ i32, bool } = .{ 0, true }`
      Function
          | pub inline fn(args) -> err!type stmt
                                      # pub, inline, args, err, !, type is optional
                                      # arg can be, ident: type = expr, .., .., ..
                                      # stmt can be, block stmt, expr stmt, or any other stmt
                                      # err can be, errset { ident, .. }
                                      # or just ident as shortcut for annonymous error
                                      # or member of error set, e.g. myErrorSet.myError
                                      # ! required after err type
      Errorset
          | errset { err, ... }       # e.g. `def e = errset { e1, ... }`
      Structure
          | struct { ... }            # e.g. `def MyStruct = struct {
                                      #   static x = 512;
                                      #   pub mut y : bool = false;
                                      #   static fn getX() return MyStruct.x;
                                      #   pub fn getY() return self.y;
                                      # }`
      Enum
          | enum { x }                # e.g. `def e = enum { x, y, ... }`
          | enum { x: type }          # e.g. `x: i32, y: struct { ... }`
      Union
          | type | type               # e.g. `let x : i32 | null = null`
      Paren
          | (type)                    # e.g. `let x : (i32) = 0`
      Alias
          | slice                     # []u8
          | char                      # u8
          | cpoint                    # u21
          | usize                     # u64
          | isize                     # i64
    2. Expr

      To have a value, we need an expression.

      • [1] Primary

        | Literal
            | 1                     # Integer (Decimal)
            | 0x1                   # Integer (Hexadecimal)
            | 0o1                   # Integer (Octal)
            | 0b1                   # Integer (Binary)
        
            | 1.0                   # Float
            | 1.0e-2                # Float (Scientific)
        
            | "text"                # String
            | 'c'                   # Character
        
            | true                  # Boolean (true)
            | false                 # Boolean (false)
        
            | null                  # Null
            | undefined             # Undefined
        
            | []                    # Empty Array
            | [expr, expr, ..]      # Filled Array
        | Ident
            | x                     # Identifier
            | @x                    # Builtin Identifier
        | Type                      # Type in Expression rule
        | Paren
            | (expr)                # Paren Expression
        | Tuple
            | (expr, expr, ..)      # Tuple Expression (',' required)
        | Object
            | {}                    # Empty Object
            | { key: expr, .. }     # Filled Object (props can be (key: value) pairs separated by commas)
            | new ident { .. }      # Tagged object
      • [2] Postfix

        | [^]                       # Previous
        | [^] ++                    # Increment
        | [^] --                    # Decrement
        | [^].*                     # Dereference
        | [^].expr                  # Member Access
        | [^]?.expr                 # Member Access (optional)
        | [^](expr, ..)             # Call
        | type([^])                 # Call as Cast e.g. `i32(12345)`
        | [^][expr]                 # Array Access

        The postfix operator can be repeated multiple times.

      • [3] Prefix

        | ++ [^]                    # Increment
        | -- [^]                    # Decrement
        | &  [^]                    # Reference
        | -  [^]                    # UnaryMinus
        | +  [^]                    # UnaryPlus
        | !  [^]                    # LogicalNot
        | ~  [^]                    # BitwiseNot
        |    [^]                    # Previous

        The Prefix operator can be repeated multiple times.

      • [4] Binary

        | [^] ... [^]               # Power (**)
        | [^] ... [^]               # Multiplicative (*,/,%)
        | [^] ... [^]               # Additive (+,-)
        | [^] ... [^]               # Shift (<<,>>)
        | [^] ... [^]               # Relational (<=, >=, <, >)
        | [^] ... [^]               # Equality (==, !=)
        | [^] ... [^]               # BitwiseAnd (&)
        | [^] ... [^]               # BitwiseXor (^)
        | [^] ... [^]               # BitwiseOr  (|)
        | [^] ... [^]               # LogicalAnd (and)
        | [^] ... [^]               # LogicalOr  (or)
      • [5] Conditional

        | [^]                       # Previous
        | [^] ? expr : expr         # Conditional
      • [6] Assignment

        | [^]                       # Previous
        | [^] = expr                # Assignment (=, +=, -=, *=, /=, %=, ..)
      • [7] If/Else

        | if expr stmt              # If
        | [^]                       # Previous

        after if :

        | else stmt                 # Else
      • [8] Match

        | match expr { ... }        # Match
        | [^]                       # Previous

        inside match :

        | expr    => stmt           # match case
        | default => stmt           # default match case
      • [9] Catch

        | [^]                       # Previous
        | [^] catch stmt            # Catch
      • [10] Try

        | try [^]                   # Try
        | [^]                       # Previous
      • [11] Range

        | [^]..                     # exclusive | Auto End (only for arrays, end = array length)
                                    # the last element index in this case (will be array.length)
        
        | [^]..=                    # inclusive | Auto End (only for arrays, end = array length)
                                    # the last element index in this case (will be array.length - 1)
                                    # this includes the last element
        
        | [^]..expr                 # Manual End
        | [^]                       # Previous
      • [12] Orelse

        | [^]                       # Previous
        | [^] ?? expr               # Orelse (returns right if left is null/undefined)

        The ?? operator returns the right operand when the left operand is null or undefined. This is especially useful with optional types: x: ?i32

        Examples:

        • value ?? defaultValue - use defaultValue if value is null/undefined
        • user?.name ?? "Unknown" - chain with optional access
        • a ?? b ?? c - multiple coalescing (left-associative)
      • [13] As

        you can also use type(expr) syntax for casting.

        | [^]                       # Previous
        | [^] as type               # Cast to type
      • [14] Special

        | typeof [^]                # get type of expr
        | sizeof [^]                # get size of expr(as type)
    3. Stmt

      To do something, we need a statement.

      • [1] Expression & Block

        | expr                      # Expression Statement
        | { stmts }                 # Block Statement

        ; is optional after statements

        , is optional after sequence items

      • [2] Use

        | use x as myX              # Use (from current module) as alias
        | use x from 'path'         # Use (from outside module) as import
        | use x as myX from 'path'  # Use (from outside module) with alias
        | use x.y as z from "path"  # with member access
      • [3] Type Definition

        | def x = type              # Define (Private)
        | pub def x = type          # Define (Public)
      • [4] Variable Declaration

        | let x: type                   # Variable with type
        | let x = expr                  # Variable with initializer
        | let x: type = expr            # Variable with type and initializer
        | let mut x = expr              # Mutable variable
        | pub let x = expr              # Public variable
        | pub let mut x: type = expr    # Public mutable variable with type
        | pub comptime let x = expr     # Comptime constant..
      • [5] Function Declaration

        | fn ident() { stmt }                           # Simple function
        | fn ident(param: type) { stmt }                # Function with parameters
        | fn ident(param: type = expr) { stmt }         # Function with default parameters
        | fn ident() -> type { stmt }                   # Function with return type
        | fn ident() -> err!type { stmt }               # Function with error and return type
        | pub fn ident() { stmt }                       # Public function
        | pub inline fn ident() { stmt }                # Public inline function
        | pub comptime inline fn ident() { stmt }       # Public comptime inline function

        Parameters can be: ident, ident: type, ident: type = expr Error type can be: errset { err, .. }, err, or errorSet.err

      • [6] Loop

        | for expr stmt             # For loop      (expr should be range)
                                    # to access to the current index use `@i` [TODO]
        
        | while expr stmt           # While loop
        
        | do stmt while expr        # Do loop
      • [7] Control Flow

        | return                    # Return (no value)
        | return expr               # Return with value
        | break                     # Break from loop
        | continue                  # Continue loop
        | defer expr                # Defer stmt
        | throw err                 # Throw stmt
      • [8] Test

        | test str block-stmt       # Test stmt (str is optional)

line

About

Parser rules and grammar definitions for the Kemet programming language.

Topics

Resources

License

Stars

Watchers

Forks