guise-lang/doc/syntax.org

14 KiB
Executable File

Guise Syntax Specification (BNF)

Introduction

This document provides a formal BNF (Backus-Naur Form) grammar specification for the Guise programming language. Guise is a purely functional, statically-typed, stack-based language with S-expression syntax.

Notation Conventions

  • <name> : Non-terminal symbol
  • "literal" : Terminal symbol (literal text)
  • | : Alternative (or)
  • * : Zero or more repetitions
  • + : One or more repetitions
  • ? : Optional (zero or one)
  • () : Grouping

Lexical Elements

Whitespace

<whitespace> ::= <space> | <tab> | <newline> | <carriage-return>
<ws>         ::= <whitespace>*

Comments

<comment>    ::= ";;" <any-char-except-newline>* <newline>

Identifiers

<identifier> ::= <initial> <subsequent>*
<initial>    ::= <letter> | <special-initial>
<subsequent> ::= <initial> | <digit> | <special-subsequent>

<letter>     ::= "a" | "b" | ... | "z" | "A" | "B" | ... | "Z"
<digit>      ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"

<special-initial>     ::= "!" | "$" | "%" | "&" | "*" | "/" | ":" | "<" | "="
                        | ">" | "?" | "^" | "_" | "~" | "+" | "-"
<special-subsequent>  ::= <special-initial> | "." | "@" | "#"

Examples: square, make-point, ++, foo->bar, h:helper

Literals

Numbers

<number>     ::= <prefix>? <complex>
<complex>    ::= <real>
               | <real> "+" <imag> "i"
               | <real> "-" <imag> "i"
               | <imag> "i"
               | "+" "i"
               | "-" "i"

<real>       ::= <sign>? <ureal>
<imag>       ::= <sign>? <ureal>
<ureal>      ::= <uinteger>
               | <uinteger> "/" <uinteger>
               | <decimal>

<decimal>    ::= <uinteger> <suffix>
               | "." <digit>+ <suffix>
               | <digit>+ "." <digit>* <suffix>

<uinteger>   ::= <digit>+
<suffix>     ::= <exponent>?
<exponent>   ::= ("e" | "E") <sign>? <digit>+

<prefix>     ::= <radix> <exactness>?
               | <exactness> <radix>?

<radix>      ::= "#b" | "#B"    ; binary
               | "#o" | "#O"    ; octal
               | "#d" | "#D"    ; decimal
               | "#x" | "#X"    ; hexadecimal

<exactness>  ::= "#e" | "#E"    ; exact
               | "#i" | "#I"    ; inexact

<sign>       ::= "+" | "-"
<digit>      ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"

Examples:

  • Decimal: 42, -17, 3.14, 2.5e10, -1.23e-4
  • Binary: #b11010 (26), #b-1010 (-10)
  • Octal: #o77 (63), #o-755 (-493)
  • Hexadecimal: #xab (171), #xFF (255), #x-1a (-26)
  • Explicit decimal: #d100 (100)
  • Rational: 1/2, 22/7, -3/4
  • Complex: 3+4i, -2-5i, 1.5+2.5i
  • Exactness: #e3.14 (exact), #i5 (inexact)
  • Combined: #b#e1010 (exact binary)

Strings

<string>     ::= '"' <string-char>* '"'
<string-char>::= <any-char-except-quote-or-backslash>
               | <escape-sequence>

<escape-sequence> ::= "\\" | "\"" | "\n" | "\t" | "\r"

Examples: "hello", "Hello, World!", "line1\nline2"

Booleans

<boolean>    ::= "#t" | "#f" | "#true" | "#false"

Characters

<character>  ::= "#\\" <any-char>
               | "#\\newline" | "#\\space" | "#\\tab"

Examples: #\a, #\Z, #\newline, #\space

Symbols

<symbol>     ::= <identifier>

Note: In Guise, all identifiers are symbols when they appear as literals.

Keywords

<keyword>    ::= "define" | "module" | "import" | "public" | "private"
               | "quotation" | "match" | "let"
               | "sum" | "product" | "⊕" | "⊗"
               | "only" | "prefix" | "rename" | "except"

Type Markers

<arrow>      ::= "->"
<sum-marker> ::= "⊕" | "sum"
<prod-marker>::= "⊗" | "product"

Expressions

Program

<program>    ::= <top-level>*

<top-level>  ::= <definition>
               | <module-def>
               | <import-stmt>
               | <expression>

Atomic Expressions

<atom>       ::= <number>
               | <string>
               | <boolean>
               | <character>
               | <symbol>

Quotations

<quotation>  ::= "'" "(" <expression>* ")"
               | "(" "quotation" <expression>* ")"

Examples:

  • '(dup *)
  • '(1 +)
  • '()
  • (quotation dup dup * *)

List Literals

<list-literal> ::= "#(" <expression>* ")"

Examples:

  • #(1 2 3)
  • #("a" "b" "c")
  • #(#(1 2) #(3 4)) (nested)

Sequences

<sequence>   ::= "(" <expression>* ")"
<expression> ::= <atom>
               | <quotation>
               | <list-literal>
               | <sequence>

Type Annotations

Type Variables

<type-var>   ::= "'" <letter> <letter-or-digit>*

Examples: 'a, 'b, 'result, 'T

Primitive Types

<prim-type>  ::= "int" | "float" | "number"
               | "bool" | "string" | "char" | "symbol"

Compound Types

<compound-type> ::= <quotation-type>
                  | <list-type>
                  | <tuple-type>
                  | <custom-type>

<quotation-type> ::= "(" "quot" "(" <stack-effect> ")" ")"
<list-type>      ::= "(" "list" <type> ")"
<tuple-type>     ::= "(" "tuple" <type>+ ")"
<custom-type>    ::= <identifier>

Examples:

  • (quot (int -> int))
  • (quot ('a -> 'a 'a))
  • (list int)
  • (tuple float float)
  • Point, Maybe

Type Expressions

<type>       ::= <type-var>
               | <prim-type>
               | <compound-type>

Stack Effects

<stack-effect> ::= <type>* <arrow> <type>*

Examples:

  • number -> number
  • int int -> int
  • 'a -> 'a 'a
  • 'a 'b -> 'b 'a
  • -> int (nullary, produces int)
  • int -> (consumes int, produces nothing)

Definitions

Word Definitions

<word-def>   ::= "(" "define" <visibility>? <identifier>
                 "(" <stack-effect> ")" <expression>* ")"

<visibility> ::= "public" | "private"

Examples:

(define square (number -> number)
  (dup *))

(define public distance (Point Point -> float)
  (x. swap x. - dup *
   y. swap y. - dup *
   + sqrt))

(define private helper (int -> int)
  (2 *))

Primitive Definitions

<prim-def>   ::= "(" "define" "primitive" <identifier>
                 "(" <stack-effect> ")" ")"

Example:

(define primitive dup ('a -> 'a 'a))
(define primitive + (number number -> number))

Product Type Definitions (Tuples)

<product-def> ::= "(" "define" <visibility>? <identifier> <prod-marker>?
                  <field-spec>+ <default-spec>* ")"

<field-spec>  ::= "(" <identifier> <type> ")"
<default-spec>::= "(" <identifier> <type> "=" <expression> ")"

Examples:

;; Implicit product type
(define Point (x float) (y float))

;; Explicit with ⊗
(define Vec3  (x float) (y float) (z float))

;; With explicit defaults
(define Config
  (port int = 8080)
  (host string = "localhost")
  (debug bool = #f))

;; Public tuple in module
(define public Person (name string) (age int))

Sum Type Definitions

<sum-def>    ::= "(" "define" <visibility>? <identifier> <sum-marker>
                 <variant>+ ")"

<variant>    ::= "(" <identifier> <type>* ")"

Examples:

;; Basic sum type with ⊕
(define Maybe 
  (Just 'a)
  (Nothing))

;; Using 'sum' keyword
(define Either sum
  (Left 'a)
  (Right 'b))

;; Result type
(define Result 
  (Ok 'ok)
  (Err 'err))

;; Enum-style
(define Color sum
  (Red)
  (Green)
  (Blue)
  (RGB int int int))

;; Recursive type
(define List 
  (Nil)
  (Cons 'a (List 'a)))

Module Definitions

<module-def> ::= "(" "define" "module" <identifier>
                 <import-stmt>?
                 <module-body>* ")"

<module-body>::= <word-def>
               | <prim-def>
               | <product-def>
               | <sum-def>

Example:

(define module math
  (import
    (helpers (prefix h:))
    (numeric-types (only int float)))

  (define public square (number -> number)
    (dup *))

  (define public cube (number -> number)
    (dup dup * *))

  (define private internal-helper (int -> int)
    (2 *)))

Module System

Import Statements

<import-stmt> ::= "(" "import" <import-spec>+ ")"

<import-spec> ::= <identifier>
                | "(" <identifier> <import-modifier>+ ")"

<import-modifier> ::= <only-modifier>
                    | <prefix-modifier>
                    | <rename-modifier>
                    | <except-modifier>

Import Modifiers

<only-modifier>   ::= "(" "only" <identifier>+ ")"
<prefix-modifier> ::= "(" "prefix" <identifier> ")"
<rename-modifier> ::= "(" "rename" <rename-pair>+ ")"
<except-modifier> ::= "(" "except" <identifier>+ ")"

<rename-pair>     ::= "(" <identifier> <identifier> ")"

Examples:

;; Simple import
(import stack-ops numeric-types)

;; Only specific bindings
(import (math (only square cube)))

;; With prefix
(import (helpers (prefix h:)))

;; With rename
(import (geometry (rename (distance point-distance))))

;; Multiple modifiers
(import
  (numeric-types (only int float) (prefix num:)))

;; Except modifier
(import (collections (except filter map)))

;; Complex example
(import
  stack-ops
  (math (only square) (prefix m:))
  (geometry (rename (distance dist)))
  (collections (except fold)))

Pattern Matching (Future)

Match Expressions

<match-expr> ::= "(" "match" <match-case>+ ")"

<match-case> ::= "(" <pattern> "→" <expression>* ")"

<pattern>    ::= <literal-pattern>
               | <variable-pattern>
               | <variant-pattern>
               | <tuple-pattern>
               | <wildcard-pattern>

<literal-pattern>  ::= <number> | <string> | <boolean>
<variable-pattern> ::= <identifier>
<variant-pattern>  ::= "(" <identifier> <pattern>* ")"
<tuple-pattern>    ::= "(" <identifier> <pattern>* ")"
<wildcard-pattern> ::= "_"

Examples:

;; Match on Maybe
(42 make-just match
  (Nothing  0)
  ((Just x)  x))

;; Match on list
(my-list match
  (Nil  0)
  ((Cons x xs)  (xs length 1 +)))

;; Match on custom tuple
(point match
  ((Point x y)  (x y + 2 /)))

Lexical Scoping (Future)

Let Bindings

<let-expr>   ::= "(" "let" "(" <binding>+ ")" <expression>* ")"

<binding>    ::= "(" <identifier> ")"
               | "(" <identifier>+ ")"

Example:

;; Bind single value
(5 let ((x))
  (x x *))

;; Bind multiple values
(1 2 3 let ((z y x))
  (x y + z *))

Complete Grammar Summary

;; ========================================
;; LEXICAL ELEMENTS
;; ========================================

<identifier>  ::= <initial> <subsequent>*
<number>      ::= <integer> | <float>
<string>      ::= '"' <string-char>* '"'
<boolean>     ::= "#t" | "#f"
<character>   ::= "#\\" <any-char>
<comment>     ::= ";;" <text> <newline>

;; ========================================
;; EXPRESSIONS
;; ========================================

<program>     ::= <top-level>*
<top-level>   ::= <definition> | <module-def> | <import-stmt> | <expression>

<expression>  ::= <atom>
                | <quotation>
                | <list-literal>
                | <sequence>

<atom>        ::= <number> | <string> | <boolean> | <character> | <symbol>
<quotation>   ::= "'" "(" <expression>* ")" | "(" "quotation" <expression>* ")"
<list-literal>::= "#(" <expression>* ")"
<sequence>    ::= "(" <expression>* ")"

;; ========================================
;; TYPES
;; ========================================

<type>        ::= <type-var> | <prim-type> | <compound-type>
<type-var>    ::= "'" <identifier>
<prim-type>   ::= "int" | "float" | "number" | "bool" | "string" | "char"
<compound-type> ::= <quotation-type> | <list-type> | <tuple-type> | <custom-type>

<stack-effect> ::= <type>* "->" <type>*

;; ========================================
;; DEFINITIONS
;; ========================================

<definition>  ::= <word-def> | <prim-def> | <product-def> | <sum-def>

<word-def>    ::= "(" "define" <visibility>? <identifier>
                  "(" <stack-effect> ")" <expression>* ")"

<prim-def>    ::= "(" "define" "primitive" <identifier>
                  "(" <stack-effect> ")" ")"

<product-def> ::= "(" "define" <visibility>? <identifier> <prod-marker>?
                  <field-spec>+ ")"

<sum-def>     ::= "(" "define" <visibility>? <identifier> <sum-marker>
                  <variant>+ ")"

<module-def>  ::= "(" "define" "module" <identifier>
                  <import-stmt>? <module-body>* ")"

;; ========================================
;; MODULE SYSTEM
;; ========================================

<import-stmt> ::= "(" "import" <import-spec>+ ")"
<import-spec> ::= <identifier> | "(" <identifier> <import-modifier>+ ")"

<import-modifier> ::= "(" "only" <identifier>+ ")"
                    | "(" "prefix" <identifier> ")"
                    | "(" "rename" <rename-pair>+ ")"
                    | "(" "except" <identifier>+ ")"

Examples

Simple Expressions

;; Stack operations
(5 3 +)           ; → 8
(dup *)           ; → square top of stack
(swap drop)       ; → keep second element

;; With quotations
'(dup *)          ; → push quotation
(5 '(dup *) call) ; → 25

Word Definitions

;; Basic word
(define square (number -> number)
  (dup *))

;; Multiple inputs/outputs
(define pythagorean (number number -> number)
  (dup * swap dup * + sqrt))

;; Higher-order
(define twice ('a (quot ('a -> 'a)) -> 'a)
  (dup call call))

Type Definitions

;; Product type (tuple)
(define Point (x float) (y float))

;; Sum type (tagged union)
(define Maybe 
  (Just 'a)
  (Nothing))

;; Using the types
(3.0 4.0 make-point)      ; Creates Point
(42 make-just)            ; Creates Maybe

Modules

;; Define a module
(define module math
  (import (helpers (prefix h:)))

  (define public square (number -> number)
    (dup *))

  (define private helper (number -> number)
    (2 *)))

;; Use a module
(import math)
(5 square)  ; → 25