14 KiB
Executable File
14 KiB
Executable File
Guise Syntax Specification (BNF)
- Introduction
- Notation Conventions
- Lexical Elements
- Expressions
- Type Annotations
- Definitions
- Module System
- Pattern Matching (Future)
- Lexical Scoping (Future)
- Complete Grammar Summary
- Examples
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 -> numberint 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