From f2b9a083814f2e91f13860ae4a239630ee50040c Mon Sep 17 00:00:00 2001 From: JJ Date: Mon, 24 Jul 2023 21:37:23 -0700 Subject: docs: initial formal description of grammar (missing scope) --- README.md | 6 +-- docs/SYNTAX.md | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 docs/SYNTAX.md diff --git a/README.md b/README.md index 67080fd..aa569be 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ A place where I can make some bad decisions. -Puck is an experimental, memory safe, strongly typed, multi-paradigm programming language. -It aims to be clean and succinct while performant: having the flexibility/metaprogramming of [Nim](https://nim-lang.org/) with the performance/safety guarantees of [Rust](https://www.rust-lang.org/) and the error handling of [Swift](https://www.swift.org/). +Puck is an experimental, memory safe, strongly typed, imperative and functional programming language. +It aims to be clean and succinct while performant: having the flexibility/metaprogramming of [Nim](https://nim-lang.org/) with the error handling of [Swift](https://www.swift.org/) and the performance/safety guarantees of [Rust](https://www.rust-lang.org/). You may judge for yourself if Puck meets these ideals. @@ -28,7 +28,7 @@ This is the language I keep in my head. It sprung from a series of unstructured ## How do I learn more? - The [basic usage](docs/BASIC.md) document lays out the fundamental grammar of Puck. -- The [syntax](docs/SYNTAX.md) document provides a deeper and formal look into the syntax choices made. +- The [syntax](docs/SYNTAX.md) document provides a deeper and formal look into the grammar of Puck. - The [type system](docs/TYPES.md) document gives an in-depth analysis of Puck's extensive type system. - The [memory management](docs/MEMORY_MANAGEMENT.md) document gives an overview of Puck's memory model. - The [metaprogramming](docs/METAPROGRAMMING.md) document explains how using metaprogramming to extend the language works. diff --git a/docs/SYNTAX.md b/docs/SYNTAX.md new file mode 100644 index 0000000..ecf7c6d --- /dev/null +++ b/docs/SYNTAX.md @@ -0,0 +1,141 @@ +# Syntax: A Casual and Formal Look + +... + +## A Formal Look + +We now shall take a look at a more formal description of Puck's syntax. Syntax rules are described in extended Backus–Naur form (EBNF) - but most rules surrounding whitespace, and scope, and line breaks, are modified to how they would appear after a lexing step (whitespace is removed, line breaks are normalized, scope is switched to use `{` and `}`). + +### Identifiers +``` +IDENT ::= LETTER (LETTER | DIGIT | '_')* +LETTER ::= 'A'..'Z' | 'a'..'z' | '\x80'..'\xff' # todo +DIGIT ::= '0'..'9' +``` + +### Literals +``` +INT_LIT ::= '-'? (DEC_LIT | HEX_LIT | OCT_LIT | BIN_LIT) +BIN_LIT ::= '0b' BIN_DIGIT ('_'? BIN_DIGIT)* +OCT_LIT ::= '0o' OCT_DIGIT ('_'? OCT_DIGIT)* +HEX_LIT ::= '0x' HEX_DIGIT ('_'? HEX_DIGIT)* +DEC_LIT ::= DIGIT ('_'? DIGIT)* +BIN_DIGIT ::= '0'..'1' +OCT_DIGIT ::= '0'..'7' +HEX_DIGIT ::= DIGIT | 'A'..'F' | 'a'..'f' +``` + +### Operators +``` +OPERATOR ::= 'and' | 'or' | 'not' | 'xor' | 'shl' | 'shr' | # todo: more? + 'div' | 'mod' | 'rem' | 'is' | 'isnot' | OPR+ +OPR ::= '=' | '+' | '-' | '*' | '/' | '<' | '>' | # todo: more? + '@' | '$' | '~' | '&' | '%' | '|' | + '!' | '?' | '^' | '.' | ':' | '\\' +``` + +### Chars, Strings, and Comments +``` +CHAR ::= '\'' (PRINT - '\'' | '\\\'')* '\'' +STRING ::= SINGLE_LINE_STRING | MULTI_LINE_STRING +COMMENT ::= SINGLE_LINE_COMMENT | MULTI_LINE_COMMENT | EXPRESSION_COMMENT +SINGLE_LINE_STRING ::= '"' (PRINT - '"' | '\\"')* '"' +MULTI_LINE_STRING ::= '"""' (PRINT | '\n' | '\r')* '"""' +SINGLE_LINE_COMMENT ::= '#' PRINT* +MULTI_LINE_COMMENT ::= '#[' (PRINT | '\n' | '\r' | MULTI_LINE_COMMENT)* ']#' +EXPRESSION_COMMENT ::= '#;' SINGLE_STMT +PRINT ::= LETTER | DIGIT | OPR | + '"' | '#' | "'" | '(' | ')' | # notably the dual of OPR + ',' | ';' | '[' | ']' | '_' | + '`' | '{' | '}' | ' ' | '\t' +``` + +### Values +``` +VALUE ::= INT_LIT | STRING | CHAR | +LIST_DECL ::= '[' (EXPR (',' EXPR)*)? ']' +ARRAY_DECL ::= '[' (EXPR (',' EXPR)*)? ']' +TUPLE_DECL ::= '(' (IDENT '=')? EXPR (',' (IDENT '=')? EXPR)* ')' +STRUCT_DECL ::= '{' IDENT '=' EXPR (',' IDENT '=' EXPR)* '}' +# note: no union or enum. should struct exist? only in a structural system. +``` + +### Variables +``` +DECL ::= LET_DECL | VAR_DECL | CONST_DECL +LET_DECL ::= 'let' GROUP (':' TYPE_DESC)? '=' EXPR +VAR_DECL ::= 'var' GROUP (':' TYPE_DESC)? ('=' EXPR)? +CONST_DECL ::= 'pub'? 'const' GROUP (':' TYPE_DESC)? '=' EXPR +GROUP ::= ('(' IDENT (',' IDENT)* ')') | IDENT +``` + +## Types and Functions +``` +FUNC_DECL ::= SIGNATURE '=' (EXPR | STMT) +SIGNATURE ::= 'pub'? ('pure' | 'yeet' | IDENT)? 'func' IDENT + ('(' (PARAMETER (',' PARAMETER)?)? ')')? + (':' TYPE_DESC)? +PARAMETER ::= (IDENT (':' ('var' | 'static')? TYPE_DESC)? +``` + +``` +TYPE_DECL ::= 'pub'? 'type' IDENT '=' 'ref'? 'distinct'? TYPE_DESC +TYPE_DESC ::= TUPLE_TYPE | STRUCT_TYPE | UNION_TYPE | ENUM_TYPE | INTERFACE | IDENT +TUPLE_TYPE ::= 'tuple' '[' (IDENT ':')? TYPE_DESC (',' (IDENT ':')? TYPE_DESC)* ']' +STRUCT_TYPE ::= 'struct' '[' 'pub'? IDENT ':' TYPE_DESC' (',' 'pub'? IDENT ':' 'TYPE_DESC')* ']' +# note: pub in structs conflicts w/ a structural system +UNION_TYPE ::= 'union' '[' IDENT ':' TYPE_DESC' (',' IDENT ':' 'TYPE_DESC')* ']' +ENUM_TYPE ::= 'enum' '[' IDENT ('=' EXPR)? (',' IDENT ('=' EXPR)?)* ']' +FUNC_TYPE ::= 'func' ('(' (PARAMETER (',' PARAMETER)?)? ')')? (':' TYPE_DESC)? +INTERFACE ::= 'interface' '[' SIGNATURE (',' SIGNATURE)* ('for' TYPE_DESC)? ']' +``` + +## Control Flow +``` +IF_EXPR ::= 'if' EXPR ':' EXPR ('elif' EXPR ':' EXPR)* 'else' ':' EXPR +IF_STMT ::= 'if' EXPR ':' STMT ('elif' EXPR ':' STMT)* ('else' ':' STMT)? +WHEN_EXPR ::= 'when' EXPR ':' EXPR ('else' ':' EXPR)? +WHEN_STMT ::= 'when' EXPR ':' STMT ('else' ':' STMT)? +BLOCK_EXPR ::= 'block' IDENT? ':' EXPR +BLOCK_STMT ::= 'block' IDENT? ':' STMT +MATCH_EXPR ::= 'match' EXPR ':' + ('case' EXPR ('where' EXPR)? (',' EXPR ('where' EXPR)?)* ':' EXPR)+ +MATCH_STMT ::= 'match' EXPR ':' + ('case' EXPR ('where' EXPR)? (',' EXPR ('where' EXPR)?)* ':' STMT)+ +LOOP_STMT ::= 'loop' ':' STMT +WHILE_STMT ::= 'while' EXPR ':' STMT +FOR_STMT ::= 'for' GROUP 'in' EXPR ':' STMT +``` + +## Modules +``` +IMPORT_STMT ::= 'import' IDENT? ('/' (IDENT | '[' (IDENT (',' IDENT)*)? ']'))* +EXPORT_STMT ::= 'export' IDENT? ('/' (IDENT | '[' (IDENT (',' IDENT)*)? ']'))* +MODULE_STMT ::= 'module' IDENT ':' STMT +``` + +## Macros +``` +MACRO_FUNC ::= IDENT '(' EXPR ')' +MACRO_BLOCK ::= IDENT ':' EXPR # todo +``` + +## Calls, Statements, and Expressions +``` +OPERATION ::= EXPR OPERATOR EXPR +PREFIX ::= OPERATOR EXPR +SUFFIX ::= EXPR OPERATOR +APPLICATION ::= IDENT EXPR | IDENT PARAMS? | (IDENT | APPLICATION) '.' IDENT PARAMS? +PARAMS ::= '(' ((IDENT '=')? EXPR (',' (IDENT '=')? EXPR)*)? ')' +``` + +``` +STMT ::= SINGLE_STMT | STMT+ +SINGLE_STMT ::= IF_STMT | WHEN_STMT | BLOCK_STMT | MATCH_STMT | + LOOP_STMT | WHILE_STMT | FOR_STMT | + IMPORT_STMT | EXPORT_STMT | MODULE_STMT | + TYPE_DECL | FUNC_DECL | (EXPR ';') +EXPR ::= IF_EXPR | WHEN_EXPR | BLOCK_EXPR | MATCH_EXPR | + MACRO_FUNC | MACRO_BLOCK | + VALUE | APPLICATION | (STMT EXPR) +``` -- cgit v1.2.3-70-g09d2