cosmo

Syntax

Cosmo Syntax BNF Specification

Principles:

  • Minimal Syntax Base
  • Composition-first polymorphism.
  • Consistent syntax.
  • Modular design and C++ interoperability.

Part 0: Notation

The syntax is specified using a variant of Extended Backus-Naur Form (EBNF):

Syntax = { Production } .
Production = ProdName "=" [ Expression ] "." .
Expression = Term { "|" Term } .
Term = Factor { Factor } .
Factor = ProdName | Token [ "…" Token ] | Group | Option | Repetition .
Group = "(" Expression ")" .
Option = "[" Expression "]" .
Repetition = "{" Expression "}" .
Syntax = { Production } .
Production = ProdName "=" [ Expression ] "." .
Expression = Term { "|" Term } .
Term = Factor { Factor } .
Factor = ProdName | Token [ "…" Token ] | Group | Option | Repetition .
Group = "(" Expression ")" .
Option = "[" Expression "]" .
Repetition = "{" Expression "}" .

Productions are expressions constructed from terms and the following operators, in increasing precedence:

| alternation
() grouping
[] option (0 or 1 times)
{} repetition (0 to n times)
| alternation
() grouping
[] option (0 or 1 times)
{} repetition (0 to n times)

Lowercase production names are used to identify lexical (terminal) tokens. Non-terminals are in CamelCase. Lexical tokens are enclosed in double quotes “” or back quotes

.

The form a … b represents the set of characters from a through b as alternatives. The horizontal ellipsis … is also used elsewhere in the spec to informally denote various enumerations or code snippets that are not further specified. The character … (as opposed to the three characters …) is not a token of the Go language.

Part 1: Literal

Identifier

Identifier = XIDStart { XIDContinue }
Identifier = XIDStart { XIDContinue }
name, _name, name1
name, _name, name1

Integer Literals

IntLit = DecimalLit | BinaryLit | OctalLit | HexLit
IntLit = DecimalLit | BinaryLit | OctalLit | HexLit
0, 0b0, 0o0, 0x0
0, 0b0, 0o0, 0x0

Floating-point Literals

FloatLit = DecimalFloatLit | HexFloatLit
FloatLit = DecimalFloatLit | HexFloatLit
0., 1., 1e2, 0x1p-2
0., 1., 1e2, 0x1p-2

String Literals

StringLit = `"` { UnicodeChar | ByteValue } `"` |
`"""` { UnicodeChar | NewLine } `"""` |
`""""` { UnicodeChar | NewLine } `""""` | ...
StringLit = `"` { UnicodeChar | ByteValue } `"` |
`"""` { UnicodeChar | NewLine } `"""` |
`""""` { UnicodeChar | NewLine } `""""` | ...
"", "a", "a\x00", """a"""
"", "a", "a\x00", """a"""

Template Literals

TemplateLiterals = IdentifierPath StringLitWithInterpolation
IdentifierPath = Identifier { "." Identifier }
TemplateLiterals = IdentifierPath StringLitWithInterpolation
IdentifierPath = Identifier { "." Identifier }

String lit can contain InterpolationInterpolation and intepolation MUSTn’t contain nested string literals.

Interpolation = "${" Expression (":" Formatter) "}"
Formatter = { AnyCharOtherThanBrace }
Interpolation = "${" Expression (":" Formatter) "}"
Formatter = { AnyCharOtherThanBrace }
s"${name} is ${age} years old"
s"price is ${price:0.2f}"
s"${name} is ${age} years old"
s"price is ${price:0.2f}"

Char Literals

Creating a character literal by template with cc prefix.

CharLiterals = "c" StringLit
CharLiterals = "c" StringLit
c"a", c"\x00"
c"a", c"\x00"

Bytes Literals

Creating a bytes literal by template with bb prefix.

BytesLiterals = "b" StringLit
BytesLiterals = "b" StringLit
b"a", b"\x00"
b"a", b"\x00"

Char Literals

Creating a ascii literal by template with aa prefix.

BytesLiterals = "a" StringLit
BytesLiterals = "a" StringLit
bc"a", bc"\x00"
bc"a", bc"\x00"

Rune Literals

Creating a rune literal by template with cc prefix.

BytesLiterals = "c" StringLit
BytesLiterals = "c" StringLit
bc"a", bc"\x00"
bc"a", bc"\x00"

Constant Literals

BoolLit = "true" | "false"
BoolLit = "true" | "false"

Argument Like

ArgsLike = "(" ")" | ("(" ArgLike { "," ArgLike } [","] ")")
ArgLike = Expression | ".." ArgsLike | (ArgsLike [ ":" Expression ] [ "=" Expression ])
ArgsLike = "(" ")" | ("(" ArgLike { "," ArgLike } [","] ")")
ArgLike = Expression | ".." ArgsLike | (ArgsLike [ ":" Expression ] [ "=" Expression ])

Argument Clause

ArgsArgs is subset of ArgsLikeArgsLike with only allowing following syntax:

Args = "(" ")" | ("(" Arg { "," Arg } [","] ")")
Arg = Expression | Destructuring | ".." Args | (Args [ ":" Type ] [ "=" Expression ])
Args = "(" ")" | ("(" Arg { "," Arg } [","] ")")
Arg = Expression | Destructuring | ".." Args | (Args [ ":" Type ] [ "=" Expression ])

Array Literals

ArrayLitArrayLit is subset of ArgsLikeArgsLike with only allowing following syntax:

ArrayLit = "(" ")" | ("(" Expression { "," Expression } [","] ")")
ArrayLit = "(" ")" | ("(" Expression { "," Expression } [","] ")")
(), (1,), (1, 2, 3)
(), (1,), (1, 2, 3)

Dict Literals

DictLitDictLit is subset of ArgsLikeArgsLike with only allowing following syntax:

DictLit = "(" DictEntry { "," DictEntry } [","] ")"
DictEntry = IdentifierPath ":" Expression
DictLit = "(" DictEntry { "," DictEntry } [","] ")"
DictEntry = IdentifierPath ":" Expression
(), (a: 1), (a: 1, b: 2)
(), (a: 1), (a: 1, b: 2)

Lambda Literal

LambdaLit = (Identifier | Args) "=>" Expression
LambdaLit = (Identifier | Args) "=>" Expression

Part 2: Declarations

Declarations

Declarations = VarDecl | ClassDecl | DefDecl
Declarations = VarDecl | ClassDecl | DefDecl

Destructuring Clause

DestructuringDestructuring is subset of ArgsLikeArgsLike with only allowing following syntax:

Destructuring = ("(" DestructureEntry { "," DestructureEntry } [","] ")")
DestructureEntry = Identifier | (IdentifierPath ":" Destructuring) | Destructuring
Destructuring = ("(" DestructureEntry { "," DestructureEntry } [","] ")")
DestructureEntry = Identifier | (IdentifierPath ":" Destructuring) | Destructuring

Var/Val/Type Declaration

VarDecl = VarDeclHeader ["=" Expression]
VarDeclHeader = VarKeywords (Identifier | Destructuring) [ ":" Type ]
VarKeywords = "val" | "var" | "type"
VarDecl = VarDeclHeader ["=" Expression]
VarDeclHeader = VarKeywords (Identifier | Destructuring) [ ":" Type ]
VarKeywords = "val" | "var" | "type"
val name = "cosmo"
var age = 18
type Age = int
val (a, b) = (1, 2)
val (a: b) = (a: 1)
val name = "cosmo"
var age = 18
type Age = int
val (a, b) = (1, 2)
val (a: b) = (a: 1)

Class/Trait Declaration

ClassDecl = ClassKeywords [Identifier] [Args] Block
ClassKeywords = "class" | "trait"
ClassDecl = ClassKeywords [Identifier] [Args] Block
ClassKeywords = "class" | "trait"

Def (Function) Declaration

DefDecl = "def" Identifier [Args] [ ":" Type ] ["=" Expression]
DefDecl = "def" Identifier [Args] [ ":" Type ] ["=" Expression]

Part 3: Expressions

types and expressions shares same expression syntax.

Expression = Type = Expressions | Declarations | Literals
Expression = Type = Expressions | Declarations | Literals

Binary Expressions

BinaryExpr = Expression BinaryOp Expression
BinaryOp = "+" | "-" | "*" | "/" | "%" | "and" | "or" | "==" | "!=" | "<" | ">" | "<=" | ">=" | "<<" | ">>" | "&" | "|" | "^"
BinaryExpr = Expression BinaryOp Expression
BinaryOp = "+" | "-" | "*" | "/" | "%" | "and" | "or" | "==" | "!=" | "<" | ">" | "<=" | ">=" | "<<" | ">>" | "&" | "|" | "^"

Pattern matching is a special binary expression:

PatternMatch = Expression "match" CaseBlock
CaseBlock = "{" { CaseClause } "}"
CaseClause = "case" Args [ "if" Expression ] "=>" Expression
PatternMatch = Expression "match" CaseBlock
CaseBlock = "{" { CaseClause } "}"
CaseClause = "case" Args [ "if" Expression ] "=>" Expression

Cast is a special binary expression:

CastExpr = Expression "as" Type
CastExpr = Expression "as" Type

Range is a special binary expression:

RangeExpr = Expression ".." Expression
RangeExpr = Expression ".." Expression

Unary Expressions

UnaryExpr = PrefixUnaryOp Expression | Expression PostfixUnaryOp
PrefixUnaryOp = "+" | "-" | "not" | "~"
PostfixUnaryOp = "?" | "!"
UnaryExpr = PrefixUnaryOp Expression | Expression PostfixUnaryOp
PrefixUnaryOp = "+" | "-" | "not" | "~"
PostfixUnaryOp = "?" | "!"

Term Expressions

TermExpr = Identifier | Expression "." Identifier | CallExpr | "(" Expression ")"
TermExpr = Identifier | Expression "." Identifier | CallExpr | "(" Expression ")"

Call (Apply) Expressions

CallExpr = Expression Args
ForComprehension = CallExpr [Block]
CallExpr = Expression Args
ForComprehension = CallExpr [Block]

If Expression

IfStmt = "if" "(" Expression ")" Block { ElseIfStmt } [ "else" Block ]
ElseIfStmt = "else" "if" "(" Expression ")" Block
IfStmt = "if" "(" Expression ")" Block { ElseIfStmt } [ "else" Block ]
ElseIfStmt = "else" "if" "(" Expression ")" Block

Block Expression

Block = [ Tag ] "{" { Statements | CaseClause } "}"
Tag = "'" Identifier
Block = [ Tag ] "{" { Statements | CaseClause } "}"
Tag = "'" Identifier

Decorated (Macro) Expression

functions, including macros, can be used for decorating syntax structures.

DecoratedExpr = { "@" CallExpr "\n" } (Declarations | Statements))
DecoratedExpr = { "@" CallExpr "\n" } (Declarations | Statements))

Example:

@nomangle
def add(a: int, b: int) = a + b
@nomangle
def add(a: int, b: int) = a + b
class A {
@json("theName")
val the_name = "cosmo"
}
class A {
@json("theName")
val the_name = "cosmo"
}

Part 4: Statements

Statements cannot be used as expressions.

Statements = Statement { (";" | newline) Statement [";"] }
Statement = Expression | Declarations | ...
Statements = Statement { (";" | newline) Statement [";"] }
Statement = Expression | Declarations | ...

Expression Statement

ExprStmt = Expression ";"
ExprStmt = Expression ";"

Import Statement

ImportStmt = ImportPathStmt | ImportBindStmt
ImportPathStmt = "import" IdentifierPath
ImportBindStmt = "import" ImportDest from Expression
ImportDest = Identifier ["," Destructuring]
ImportStmt = ImportPathStmt | ImportBindStmt
ImportPathStmt = "import" IdentifierPath
ImportBindStmt = "import" ImportDest from Expression
ImportDest = Identifier ["," Destructuring]

Infinite Loop Statement

LoopStmt = [ Tag ] "loop" Block
LoopStmt = [ Tag ] "loop" Block

While Loop Statement

WhileStmt = [ Tag ] "while" "(" Expression ")" Block
WhileStmt = [ Tag ] "while" "(" Expression ")" Block

Range Loop Statement

ForRangeStmt = [ Tag ] "for" [ForClause] Block
ForClause = "(" [ VarDeclHeader "in" Expression ] ")"
ForRangeStmt = [ Tag ] "for" [ForClause] Block
ForClause = "(" [ VarDeclHeader "in" Expression ] ")"

Break/Continue/Return Statement

BreakContinueStmt = ("break" | "continue") [ Tag ] [ Expression ]
ReturnStmt = "return" [ Expression ]
BreakContinueStmt = ("break" | "continue") [ Tag ] [ Expression ]
ReturnStmt = "return" [ Expression ]

Pub Statement

Which MUST occur in generated header.

PubStmt = "pub" Declaration
PubStmt = "pub" Declaration

Part 5: Macros

DeerivedMacroDeerivedMacro can only generate extra syntax structures.

Macro = CallMacro | BlockMacro | DeerivedMacro
CallMacro = CallExpr ArgLike
BlockMacro = CallExpr Block
DeerivedMacro = DecoratedExpr
Macro = CallMacro | BlockMacro | DeerivedMacro
CallMacro = CallExpr ArgLike
BlockMacro = CallExpr Block
DeerivedMacro = DecoratedExpr
@derive(Debug)
class A {
val name = "cosmo"
}
@derive(Debug)
class A {
val name = "cosmo"
}
val (Q, R) = decompositeMatrix(M) ( // format: 2c
Q, 0,
0, R,
)
val I_4 = matrix(4, 4) (
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
)
val (Q, R) = decompositeMatrix(M) ( // format: 2c
Q, 0,
0, R,
)
val I_4 = matrix(4, 4) (
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
)
shell {
for (val i in 0..10) {
exec "mkdir $i"
}
}
shell {
for (val i in 0..10) {
exec "mkdir $i"
}
}