Syntax
Principles:
- Minimal Syntax Base
- Composition-first polymorphism.
- Consistent syntax.
- Modular design and C++ interoperability.
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.
Identifier = XIDStart { XIDContinue }
Identifier = XIDStart { XIDContinue }
name, _name, name1
name, _name, name1
IntLit = DecimalLit | BinaryLit | OctalLit | HexLit
IntLit = DecimalLit | BinaryLit | OctalLit | HexLit
0, 0b0, 0o0, 0x0
0, 0b0, 0o0, 0x0
FloatLit = DecimalFloatLit | HexFloatLit
FloatLit = DecimalFloatLit | HexFloatLit
0., 1., 1e2, 0x1p-2
0., 1., 1e2, 0x1p-2
StringLit = `"` { UnicodeChar | ByteValue } `"` | `"""` { UnicodeChar | NewLine } `"""` | `""""` { UnicodeChar | NewLine } `""""` | ...
StringLit = `"` { UnicodeChar | ByteValue } `"` | `"""` { UnicodeChar | NewLine } `"""` | `""""` { UnicodeChar | NewLine } `""""` | ...
"", "a", "a\x00", """a"""
"", "a", "a\x00", """a"""
TemplateLiterals = IdentifierPath StringLitWithInterpolationIdentifierPath = Identifier { "." Identifier }
TemplateLiterals = IdentifierPath StringLitWithInterpolationIdentifierPath = 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}"
Creating a character literal by template with cc prefix.
CharLiterals = "c" StringLit
CharLiterals = "c" StringLit
c"a", c"\x00"
c"a", c"\x00"
Creating a bytes literal by template with bb prefix.
BytesLiterals = "b" StringLit
BytesLiterals = "b" StringLit
b"a", b"\x00"
b"a", b"\x00"
Creating a ascii literal by template with aa prefix.
BytesLiterals = "a" StringLit
BytesLiterals = "a" StringLit
bc"a", bc"\x00"
bc"a", bc"\x00"
Creating a rune literal by template with cc prefix.
BytesLiterals = "c" StringLit
BytesLiterals = "c" StringLit
bc"a", bc"\x00"
bc"a", bc"\x00"
BoolLit = "true" | "false"
BoolLit = "true" | "false"
ArgsLike = "(" ")" | ("(" ArgLike { "," ArgLike } [","] ")")ArgLike = Expression | ".." ArgsLike | (ArgsLike [ ":" Expression ] [ "=" Expression ])
ArgsLike = "(" ")" | ("(" ArgLike { "," ArgLike } [","] ")")ArgLike = Expression | ".." ArgsLike | (ArgsLike [ ":" Expression ] [ "=" Expression ])
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 ])
ArrayLitArrayLit is subset of ArgsLikeArgsLike with only allowing following syntax:
ArrayLit = "(" ")" | ("(" Expression { "," Expression } [","] ")")
ArrayLit = "(" ")" | ("(" Expression { "," Expression } [","] ")")
(), (1,), (1, 2, 3)
(), (1,), (1, 2, 3)
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)
LambdaLit = (Identifier | Args) "=>" Expression
LambdaLit = (Identifier | Args) "=>" Expression
Declarations = VarDecl | ClassDecl | DefDecl
Declarations = VarDecl | ClassDecl | DefDecl
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
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 = 18type Age = intval (a, b) = (1, 2)val (a: b) = (a: 1)
val name = "cosmo"var age = 18type Age = intval (a, b) = (1, 2)val (a: b) = (a: 1)
ClassDecl = ClassKeywords [Identifier] [Args] BlockClassKeywords = "class" | "trait"
ClassDecl = ClassKeywords [Identifier] [Args] BlockClassKeywords = "class" | "trait"
DefDecl = "def" Identifier [Args] [ ":" Type ] ["=" Expression]
DefDecl = "def" Identifier [Args] [ ":" Type ] ["=" Expression]
types and expressions shares same expression syntax.
Expression = Type = Expressions | Declarations | Literals
Expression = Type = Expressions | Declarations | Literals
BinaryExpr = Expression BinaryOp ExpressionBinaryOp = "+" | "-" | "*" | "/" | "%" | "and" | "or" | "==" | "!=" | "<" | ">" | "<=" | ">=" | "<<" | ">>" | "&" | "|" | "^"
BinaryExpr = Expression BinaryOp ExpressionBinaryOp = "+" | "-" | "*" | "/" | "%" | "and" | "or" | "==" | "!=" | "<" | ">" | "<=" | ">=" | "<<" | ">>" | "&" | "|" | "^"
Pattern matching is a special binary expression:
PatternMatch = Expression "match" CaseBlockCaseBlock = "{" { CaseClause } "}"CaseClause = "case" Args [ "if" Expression ] "=>" Expression
PatternMatch = Expression "match" CaseBlockCaseBlock = "{" { 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
UnaryExpr = PrefixUnaryOp Expression | Expression PostfixUnaryOpPrefixUnaryOp = "+" | "-" | "not" | "~"PostfixUnaryOp = "?" | "!"
UnaryExpr = PrefixUnaryOp Expression | Expression PostfixUnaryOpPrefixUnaryOp = "+" | "-" | "not" | "~"PostfixUnaryOp = "?" | "!"
TermExpr = Identifier | Expression "." Identifier | CallExpr | "(" Expression ")"
TermExpr = Identifier | Expression "." Identifier | CallExpr | "(" Expression ")"
CallExpr = Expression ArgsForComprehension = CallExpr [Block]
CallExpr = Expression ArgsForComprehension = CallExpr [Block]
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 = [ Tag ] "{" { Statements | CaseClause } "}"Tag = "'" Identifier
Block = [ Tag ] "{" { Statements | CaseClause } "}"Tag = "'" Identifier
functions, including macros, can be used for decorating syntax structures.
DecoratedExpr = { "@" CallExpr "\n" } (Declarations | Statements))
DecoratedExpr = { "@" CallExpr "\n" } (Declarations | Statements))
Example:
@nomangledef add(a: int, b: int) = a + b
@nomangledef add(a: int, b: int) = a + b
class A { @json("theName") val the_name = "cosmo"}
class A { @json("theName") val the_name = "cosmo"}
Statements cannot be used as expressions.
Statements = Statement { (";" | newline) Statement [";"] }Statement = Expression | Declarations | ...
Statements = Statement { (";" | newline) Statement [";"] }Statement = Expression | Declarations | ...
ExprStmt = Expression ";"
ExprStmt = Expression ";"
ImportStmt = ImportPathStmt | ImportBindStmtImportPathStmt = "import" IdentifierPathImportBindStmt = "import" ImportDest from ExpressionImportDest = Identifier ["," Destructuring]
ImportStmt = ImportPathStmt | ImportBindStmtImportPathStmt = "import" IdentifierPathImportBindStmt = "import" ImportDest from ExpressionImportDest = Identifier ["," Destructuring]
LoopStmt = [ Tag ] "loop" Block
LoopStmt = [ Tag ] "loop" Block
WhileStmt = [ Tag ] "while" "(" Expression ")" Block
WhileStmt = [ Tag ] "while" "(" Expression ")" Block
ForRangeStmt = [ Tag ] "for" [ForClause] BlockForClause = "(" [ VarDeclHeader "in" Expression ] ")"
ForRangeStmt = [ Tag ] "for" [ForClause] BlockForClause = "(" [ VarDeclHeader "in" Expression ] ")"
BreakContinueStmt = ("break" | "continue") [ Tag ] [ Expression ]ReturnStmt = "return" [ Expression ]
BreakContinueStmt = ("break" | "continue") [ Tag ] [ Expression ]ReturnStmt = "return" [ Expression ]
Which MUST occur in generated header.
PubStmt = "pub" Declaration
PubStmt = "pub" Declaration
DeerivedMacroDeerivedMacro can only generate extra syntax structures.
Macro = CallMacro | BlockMacro | DeerivedMacroCallMacro = CallExpr ArgLikeBlockMacro = CallExpr BlockDeerivedMacro = DecoratedExpr
Macro = CallMacro | BlockMacro | DeerivedMacroCallMacro = CallExpr ArgLikeBlockMacro = CallExpr BlockDeerivedMacro = 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" }}