bobbylisp/spec.md

4.6 KiB

Specification

Syntax


Expressions

  • Literals

    A literal is a value that is written directly into the source code.

    • Number

      An number literal is of type f64 and can be expressed with or without a decimal point.

      • Examples: 1, 3.14, .5
      Number:
          Digits + (maybe '.' + Digits).
          (* Optional whole number, e.g. .5 *)
          ('.' + Digits).
      Digits:
          one or more of 0..9.
      
    • String

      A string literal can consist of zero or more characters enclosed in double quotes (")

      • Examples: "Hello, World", "They said \"Hi\"", "Foo\nBar"
      String:
          '"' + (zero or more of Character) + '"'.
      Character:
          any character except '"' or '\'.
          escape sequences.
      
    • Boolean

      A boolean literal can be either true or false.

      Boolean:
          'true' or 'false'.
      
    • Unit

      A unit literal is a value that represents the absence of a value.

      Unit:
          '()'.
      
  • Identifiers

    An identifier is a name that is used to refer to a variable, function, or other entity.

    • Examples: foo, barBaz, add2
    Identifier:
        (Letter + zero or more of LetterOrDigit) but
        not any of Keywords.
    Letter:
        one of a..z or A..Z.
    LetterOrDigit:
        Letter or one of 0..9.
    
  • Operators

    An operator is a symbol that is used to represent an operation.

    Binary:
        one of (
            (* Arithmetic *)
            + - * / %
            (* Comparison *)
            == != < <= > >=
            (* Logical *)
            && ||
        ).
    Unary:
        one of (- !).
    
  • Application (Function Call)

    An application is an expression that calls a function with a list of arguments. It is not necessary that the callee is a function, but it must be an expression that evaluates to a function.

    Arguments:
        zero or more of Expression delimited by ','.
    Application:
        Expression + '(' + Arguments + ')'.
    
    • Examples:

      foo(1, 2, 3)
      (\x -> x + 1)(2)
      
  • If-Else

    An if-else expression is an expression that evaluates to one of two expressions depending on the value of a condition.

    IfElse:
        'if' + Expression + 'then' + Expression + 'else' + Expression.
    
    • Examples:

      if true then 1 else 2
      if 1 == 2 then "foo" else "bar"
      
  • Let Binding(s)

    There are 2 types of let bindings:

    • "Imperative" let bindings, which are similar to variable declarations in imperative languages (Javascript, Rust, etc.).

      Bindings:
          one or more of Binding delimited by ','.
      Let:
          'let' + Bindings.
      
      • Example:

        let x = 1 // -> ()
        x + 1     // -> 2
        
    • "Functional" let bindings, which are similar to variable declarations in functional languages (ML-family, etc.).

      LetIn:
          'let' + Bindings + 'in' + Expression.
      
      • Example:

        let x = 1, y = 2 in
            x + y // -> 3
        
  • Block & Return

    A block is a sequence of expressions that are evaluated in order and the value of the last expression is returned (if not ended with a semicolon).

    A return expression is an expression that will exit the current block and return the value of the expression. It is not necessary to use a return expression in a block, but it could be useful for early termination.

    Any use of a return expression outside of a block is not allowed.

    Block:
        '{' + zero or more of Expression + '}'.
    Return:
        'return' + Expression.
    
    • Examples:

      {
          let x = 1;
          let y = 2;
          x + y
      }
      
      fun foo(): num = {
          if true then
              return 1;
      
          let bar = 42;
          bar
      };
      

Keywords

Keywords are reserved words that cannot be used as identifiers. They are used to represent constructs of the language.

Keywords:
    if then else
    let fun return