chore: Initial wiki push
Signed-off-by: erick-alcachofa <erick@artichoke.dev>
commit
e38e2baf59
286
Home.md
Normal file
286
Home.md
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
# The `artichoke` Programming Language: A Technical Overview
|
||||||
|
|
||||||
|
## 1. Introduction
|
||||||
|
|
||||||
|
`artichoke` is a statically-typed, general-purpose programming language designed
|
||||||
|
with an emphasis on performance, safety, and expressive syntax. It combines
|
||||||
|
low-level control over memory with modern, high-level features like generics,
|
||||||
|
algebraic data types, and integrated error handling. This document provides an
|
||||||
|
overview of the language's features as defined by its core grammar.
|
||||||
|
|
||||||
|
Is highly inspired by C, C++, Rust, and mostly Zig.
|
||||||
|
|
||||||
|
## 2. Basic Syntax & Structure
|
||||||
|
|
||||||
|
### Modules, Imports, and Aliases
|
||||||
|
|
||||||
|
`artichoke` code is organized into modules. The `import` statement is used to bring
|
||||||
|
symbols from other modules into the current scope.
|
||||||
|
|
||||||
|
* **Importing a specific element:** `import my_module::some_function;`
|
||||||
|
* **Importing all direct elements of a module:** `import std::*;`
|
||||||
|
* **Importing an entire submodule:** `import std::memory;`
|
||||||
|
|
||||||
|
The `using` keyword creates a local, more convenient alias for a type, function,
|
||||||
|
or module name.
|
||||||
|
|
||||||
|
```
|
||||||
|
using mem = std::memory;
|
||||||
|
using FileHandle = std::fs::File;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Comments
|
||||||
|
|
||||||
|
The language uses C-style block comments.
|
||||||
|
|
||||||
|
```
|
||||||
|
/* This is a multi-line
|
||||||
|
comment. */
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. The Type System
|
||||||
|
|
||||||
|
`artichoke`'s type system is strong and static, with a rich set of features for
|
||||||
|
defining complex data structures.
|
||||||
|
|
||||||
|
### Type Qualifiers
|
||||||
|
|
||||||
|
Qualifiers modify the type to their immediate right, allowing for precise and
|
||||||
|
complex type definitions.
|
||||||
|
|
||||||
|
* **`*` (Pointer):** Creates a pointer to a type. Pointers cannot be `null`.
|
||||||
|
* **`$` (Mutable):** Marks a type as mutable. This is used for function
|
||||||
|
parameters, local variables, and struct fields to allow modification.
|
||||||
|
* **`?` (Optional):** Marks a type as nullable. An optional type can hold either a
|
||||||
|
value of its underlying type or `null`.
|
||||||
|
* **`[]` (Slice):** A "fat pointer" representing a view into a contiguous
|
||||||
|
sequence of elements. It contains both a pointer to the data and a length.
|
||||||
|
|
||||||
|
These qualifiers can be combined. For example, `*$?int` defines a **pointer to a
|
||||||
|
mutable optional integer**.
|
||||||
|
|
||||||
|
### Generics
|
||||||
|
|
||||||
|
Generics allow for writing flexible, reusable code that can operate on multiple
|
||||||
|
types. They are defined using `<typename T>`.
|
||||||
|
|
||||||
|
```
|
||||||
|
/* A generic struct */
|
||||||
|
struct Point<typename T> {
|
||||||
|
x: T,
|
||||||
|
y: T
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A generic function */
|
||||||
|
fn scale<typename T>(lhs: *Point<T>, rhs: T) -> Point {
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## 4. Declarations
|
||||||
|
|
||||||
|
### Variables
|
||||||
|
|
||||||
|
Variables are declared using the `let` (mutable) and `def` (immutable/constant)
|
||||||
|
keywords.
|
||||||
|
|
||||||
|
* **Type inference** is supported when the type can be determined from the initializer.
|
||||||
|
* Variables must be initialized with either a type, a value, or both.
|
||||||
|
|
||||||
|
```
|
||||||
|
/* Mutable variable with explicit type */
|
||||||
|
let x: i32 = 10;
|
||||||
|
|
||||||
|
/* Immutable variable with type inference */
|
||||||
|
def do_you_get_it = meaning_of_life();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Structs
|
||||||
|
|
||||||
|
Structs are composite data types that group together variables under one name.
|
||||||
|
They support generics.
|
||||||
|
|
||||||
|
```
|
||||||
|
struct Rectangle {
|
||||||
|
top: Point<i32>,
|
||||||
|
bot: Point<i32>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Initialization:** Structs can be initialized using positional or named fields,
|
||||||
|
but not a mix of both.
|
||||||
|
|
||||||
|
```
|
||||||
|
/* Positional initialization */
|
||||||
|
def top_left = Point<i32>{ 0, 10 };
|
||||||
|
|
||||||
|
/* Named-field initialization */
|
||||||
|
def top_right = Point<i32>{ x: 10, y: 10 };
|
||||||
|
```
|
||||||
|
|
||||||
|
### Enums (Tagged Unions)
|
||||||
|
|
||||||
|
Enums define a type that can be one of several different variants. Variants can
|
||||||
|
optionally hold data.
|
||||||
|
|
||||||
|
```
|
||||||
|
enum AssetType {
|
||||||
|
Texture,
|
||||||
|
Model,
|
||||||
|
Sound,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Result<typename T, typename E> {
|
||||||
|
Ok(T),
|
||||||
|
Err(E)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Initialization:** Enum variants are accessed using scope resolution (`::`).
|
||||||
|
|
||||||
|
```
|
||||||
|
def my_asset = AssetType::Texture;
|
||||||
|
def success = Result<i32, string>::Ok(100);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Functions
|
||||||
|
|
||||||
|
Functions are defined with the fn keyword. The return type is specified after
|
||||||
|
the parameter list with `->`.
|
||||||
|
|
||||||
|
```
|
||||||
|
fn meaning_of_life() -> i32 {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Member Functions (`this` parameter)
|
||||||
|
|
||||||
|
If the first parameter of a function is declared with the `this` keyword, it can
|
||||||
|
be called using "member function" syntax.
|
||||||
|
|
||||||
|
```
|
||||||
|
/* Definition */
|
||||||
|
fn add<typename T>(this *$Point<T>, other: *Point<T>) {
|
||||||
|
this->x += other->x;
|
||||||
|
this->y += other->y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Can be called in two ways: */
|
||||||
|
/* Member function syntax */
|
||||||
|
my_point.add(&other_point);
|
||||||
|
|
||||||
|
/* Normal function syntax */
|
||||||
|
add(&my_point, &other_point);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 5. Control Flow
|
||||||
|
|
||||||
|
### `if`/`else` Statements
|
||||||
|
|
||||||
|
`artichoke` supports C-style `if`/`else` and `else if` chains. It also integrates a
|
||||||
|
powerful unwrapping feature for handling `Result` and optional (`?`) types.
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
/* Standard if/else */
|
||||||
|
if (argc < 2) {
|
||||||
|
return Result::Err(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unwrapping a Result */
|
||||||
|
if (foo()) |ok| {
|
||||||
|
/* `ok` holds the success value */
|
||||||
|
}
|
||||||
|
else |err| {
|
||||||
|
/* `err` holds the error value */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Loops
|
||||||
|
|
||||||
|
The language provides a comprehensive set of looping constructs.
|
||||||
|
|
||||||
|
* **C-Style `for`:** `for (let i \= 0; i \< 10; i \+= 1\) { ... }`
|
||||||
|
* **Range-based `for`:** `for (let e := arrSlice) { ... }`
|
||||||
|
* **`while` Loop:** Can optionally have an `else` block that executes when the loop
|
||||||
|
condition is no longer met.
|
||||||
|
* **Iterator `while`:** Supports unwrapping `Result`/optional types, executing as
|
||||||
|
long as the value is valid.
|
||||||
|
* **`do-while` Loop:** Guarantees the body executes at least once.
|
||||||
|
* **Infinite `loop`:** `loop { ... }`
|
||||||
|
|
||||||
|
#### Loop Labels and Control
|
||||||
|
|
||||||
|
Loops can be labeled. The `break` and `continue` statements can optionally specify a
|
||||||
|
label to control nested loops.
|
||||||
|
|
||||||
|
```
|
||||||
|
outer_loop := while (condition) {
|
||||||
|
inner_loop := for (...) {
|
||||||
|
break outer_loop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6. Expressions and Operators
|
||||||
|
|
||||||
|
### Pointer and Member Access
|
||||||
|
|
||||||
|
* **`&` (Address-of):** Gets a pointer to a variable.
|
||||||
|
* **`*` (Dereference):** Accesses the value a pointer points to.
|
||||||
|
* **`.` (Member Access):** Accesses a member of a struct value.
|
||||||
|
* **`->` (Pointer Member Access):** Dereferences a pointer and accesses a member
|
||||||
|
(`p->x` is shorthand for `(*p).x`).
|
||||||
|
|
||||||
|
### Slice Operators
|
||||||
|
|
||||||
|
Slices have a dedicated set of operators for manipulation.
|
||||||
|
|
||||||
|
* **`[start:end]` (Slicing):** Creates a new slice from an existing one.
|
||||||
|
* **`.*` (Pointer Access):** Gets the underlying raw pointer of the slice.
|
||||||
|
* **`.#` (Length Access):** Gets the number of elements in the slice.
|
||||||
|
* **`.[length]` (Slice from Pointer):** Creates a slice from a raw pointer and a length.
|
||||||
|
|
||||||
|
### Assignment
|
||||||
|
|
||||||
|
The language supports simple (`=`) and compound assignment (`+=`, `*=`, etc.)
|
||||||
|
operators.
|
||||||
|
|
||||||
|
## 7. Advanced Features
|
||||||
|
|
||||||
|
### Resource Management (`defer` and `errdefer`)
|
||||||
|
|
||||||
|
`artichoke` uses `defer` for deterministic resource management.
|
||||||
|
|
||||||
|
* **`defer`:** Schedules an expression or code block to be executed when the
|
||||||
|
current scope is exited. Deferred calls are executed in Last-In, First-Out
|
||||||
|
(LIFO) order.
|
||||||
|
* **`errdefer`:** Similar to `defer`, but the code is only executed if the scope is
|
||||||
|
exited due to a function returning an error (an `Err` variant of a `Result`).
|
||||||
|
|
||||||
|
```
|
||||||
|
defer call_cleanup();
|
||||||
|
|
||||||
|
errdefer {
|
||||||
|
log("An error occurred!");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reflection (`.@`)
|
||||||
|
|
||||||
|
The language provides a compile-time reflection mechanism via the `.@` operator.
|
||||||
|
It can be applied to values, types, and static members to query metadata.
|
||||||
|
|
||||||
|
* **On values:** `my_variable.@type`
|
||||||
|
* **On types:** `Point<u32>.@size, Point<u32>.@alignment`
|
||||||
|
* **On static members:** `Point<u32>::x.@offset`
|
||||||
|
|
||||||
|
```
|
||||||
|
/* Gets size in bytes */
|
||||||
|
def size_bytes = Point<u32>.@size;
|
||||||
|
|
||||||
|
/* Gets string representation of the type */
|
||||||
|
def point_name = Point<u32>.@typename;
|
||||||
|
```
|
||||||
348
grammar.ebnf
Normal file
348
grammar.ebnf
Normal file
@ -0,0 +1,348 @@
|
|||||||
|
/*
|
||||||
|
================================================================================
|
||||||
|
| |
|
||||||
|
| The Artichoke Programming Language |
|
||||||
|
| Official EBNF Grammar |
|
||||||
|
| |
|
||||||
|
================================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* --- Program Structure --- */
|
||||||
|
/* A program is a sequence of top-level declarations and statements. */
|
||||||
|
|
||||||
|
<program> =
|
||||||
|
( <import_statement>
|
||||||
|
| <module_statement>
|
||||||
|
| <alias_statement>
|
||||||
|
| <struct_declaration>
|
||||||
|
| <enum_declaration>
|
||||||
|
| <function_declaration> )*
|
||||||
|
|
||||||
|
<module_statement> =
|
||||||
|
"export"? "module" <namespaced_identifier> "{"
|
||||||
|
( <module_statement>
|
||||||
|
| <alias_statement>
|
||||||
|
| <struct_declaration>
|
||||||
|
| <enum_declaration>
|
||||||
|
| <function_declaration> )*
|
||||||
|
"}"
|
||||||
|
|
||||||
|
<import_statement> =
|
||||||
|
"import" <import_target> ";"
|
||||||
|
|
||||||
|
<import_target> =
|
||||||
|
<namespaced_identifier>
|
||||||
|
| <namespaced_identifier> "::" "*"
|
||||||
|
|
||||||
|
<alias_statement> =
|
||||||
|
"using" <identifier> "=" <namespaced_identifier> ";"
|
||||||
|
|
||||||
|
|
||||||
|
/* --- Declarations --- */
|
||||||
|
/* Rules for defining functions, structs, enums, and their components. */
|
||||||
|
|
||||||
|
<function_declaration> =
|
||||||
|
"export"? "fn" <identifier> <generic_params> "(" <fn_params> ")" ( "->" <type> )? <code_block>
|
||||||
|
|
||||||
|
<fn_params> =
|
||||||
|
<fn_params_list>?
|
||||||
|
|
||||||
|
<fn_params_list> =
|
||||||
|
"this" <type> ("," <fn_param> ( "," <fn_param> )* )?
|
||||||
|
| <fn_param> ( "," <fn_param> )*
|
||||||
|
|
||||||
|
<fn_param> =
|
||||||
|
<identifier> ":" <type>
|
||||||
|
|
||||||
|
<struct_declaration> =
|
||||||
|
"export"? "struct" <identifier> <generic_params> "{" <struct_members> "}"
|
||||||
|
|
||||||
|
<struct_members> =
|
||||||
|
<struct_member> ( "," <struct_member> )*
|
||||||
|
|
||||||
|
<struct_member> =
|
||||||
|
<identifier> ":" <type>
|
||||||
|
|
||||||
|
<enum_declaration> =
|
||||||
|
"export"? "enum" <identifier> <generic_params> "{" <enum_members> "}"
|
||||||
|
|
||||||
|
<enum_members> =
|
||||||
|
<enum_member> ( "," <enum_member> )*
|
||||||
|
|
||||||
|
<enum_member> =
|
||||||
|
<identifier> ( "(" <type> ")" )?
|
||||||
|
|
||||||
|
<generic_params> =
|
||||||
|
( "<" <generic_params_list> ">" )?
|
||||||
|
|
||||||
|
<generic_params_list> =
|
||||||
|
<generic_param> ( "," <generic_param> )*
|
||||||
|
|
||||||
|
<generic_param> =
|
||||||
|
"typename" <identifier>
|
||||||
|
|
||||||
|
|
||||||
|
/* --- Statements & Control Flow --- */
|
||||||
|
/* Rules for code blocks, variable declarations, and control structures. */
|
||||||
|
|
||||||
|
<code_block> =
|
||||||
|
"{" <statements>? "}"
|
||||||
|
|
||||||
|
<statements> =
|
||||||
|
<statement> ( <statement> )*
|
||||||
|
|
||||||
|
<statement> =
|
||||||
|
<variable_declaration> ";"
|
||||||
|
| <if_statement>
|
||||||
|
| <loop_statement>
|
||||||
|
| <defer_statement> ";"
|
||||||
|
| <errdefer_statement> ";"
|
||||||
|
| <return_statement> ";"
|
||||||
|
| <break_statement> ";"
|
||||||
|
| <continue_statement> ";"
|
||||||
|
| <expression_statement>
|
||||||
|
| <alias_statement>
|
||||||
|
| <match_statement>
|
||||||
|
| <switch_statement>
|
||||||
|
|
||||||
|
<variable_declaration> =
|
||||||
|
<variable_declarator> <identifier> ( ":" <type> )? "=" <expression>
|
||||||
|
| <variable_declarator> <identifier> ":" <type> ( "=" <expression> )?
|
||||||
|
|
||||||
|
<variable_declarator> =
|
||||||
|
"let"
|
||||||
|
| "def"
|
||||||
|
|
||||||
|
<if_statement> =
|
||||||
|
"if" "(" <expression> ")" <variable_unwrapper>? <code_block>
|
||||||
|
<else_statement>?
|
||||||
|
|
||||||
|
<else_statement> =
|
||||||
|
"else" <variable_unwrapper>? <code_block>
|
||||||
|
| "else" <if_statement>
|
||||||
|
|
||||||
|
<variable_unwrapper> =
|
||||||
|
"|" <identifier> "|"
|
||||||
|
|
||||||
|
<loop_statement> =
|
||||||
|
(<identifier> ":=")? (
|
||||||
|
<c_for_statement>
|
||||||
|
| <range_for_statement>
|
||||||
|
| <while_statement>
|
||||||
|
| <do_while_statement>
|
||||||
|
| <inf_loop_statement>
|
||||||
|
)
|
||||||
|
|
||||||
|
<c_for_statement> =
|
||||||
|
"for" "(" <variable_declaration>? ";" <expression> ";" <expression> ")"
|
||||||
|
<code_block>
|
||||||
|
|
||||||
|
<range_for_statement> =
|
||||||
|
"for" "(" <variable_declarator> <identifier> ":=" <expression> ")"
|
||||||
|
<code_block>
|
||||||
|
|
||||||
|
<while_statement> =
|
||||||
|
"while" "(" <expression> ")" <variable_unwrapper>? <code_block>
|
||||||
|
<else_statement>?
|
||||||
|
|
||||||
|
<do_while_statement> =
|
||||||
|
"do" <code_block> "while" "(" <expression> ")"
|
||||||
|
|
||||||
|
<inf_loop_statement> =
|
||||||
|
"loop" <code_block>
|
||||||
|
|
||||||
|
<match_statement> =
|
||||||
|
"match" "(" <expression> ")" "{" <match_case>* <default_case>? "}"
|
||||||
|
|
||||||
|
<switch_statement> =
|
||||||
|
"switch" "(" <expression> ")" "{" <switch_case>* <default_case>? "}"
|
||||||
|
|
||||||
|
<match_case> =
|
||||||
|
( <type_name> | <scoped_access_expression> ) ( "(" <identifier> ")" )? "->" <code_block>
|
||||||
|
|
||||||
|
<switch_case> =
|
||||||
|
<expression> "->" <code_block>
|
||||||
|
|
||||||
|
<default_case> =
|
||||||
|
"_" "->" <code_block>
|
||||||
|
|
||||||
|
<break_statement> =
|
||||||
|
"break" <identifier>?
|
||||||
|
|
||||||
|
<continue_statement> =
|
||||||
|
"continue" <identifier>?
|
||||||
|
|
||||||
|
<defer_statement> =
|
||||||
|
"defer" ( <expression> | <code_block> )
|
||||||
|
|
||||||
|
<errdefer_statement> =
|
||||||
|
"errdefer" ( <expression> | <code_block> )
|
||||||
|
|
||||||
|
<return_statement> =
|
||||||
|
"return" <expression>?
|
||||||
|
|
||||||
|
<expression_statement> =
|
||||||
|
<expression> ";"
|
||||||
|
|
||||||
|
|
||||||
|
/* --- Expressions & Operator Precedence --- */
|
||||||
|
/* The full expression hierarchy, from lowest to highest precedence. */
|
||||||
|
|
||||||
|
<expression> =
|
||||||
|
<assign_expression>
|
||||||
|
|
||||||
|
<assign_expression> =
|
||||||
|
<bool_or_expression> ( ( <assign_op> | <compound_assign_op> ) <expression> )?
|
||||||
|
|
||||||
|
<bool_or_expression> =
|
||||||
|
<bool_and_expression> ( ( "||" | "or" ) <bool_and_expression> )*
|
||||||
|
|
||||||
|
<bool_and_expression> =
|
||||||
|
<compare_expression> ( ( "&&" | "and" ) <compare_expression> )*
|
||||||
|
|
||||||
|
<compare_expression> =
|
||||||
|
<bitwise_expression> ( <compare_op> <bitwise_expression> )?
|
||||||
|
|
||||||
|
<bitwise_expression> =
|
||||||
|
<bitwise_shift_expression> ( <bitwise_op> <bitwise_shift_expression> )*
|
||||||
|
|
||||||
|
<bitwise_shift_expression> =
|
||||||
|
<addition_expression> ( <bitshift_op> <addition_expression> )*
|
||||||
|
|
||||||
|
<addition_expression> =
|
||||||
|
<multiply_expression> ( <addition_op> <multiply_expression> )*
|
||||||
|
|
||||||
|
<multiply_expression> =
|
||||||
|
<prefix_expression> ( <multiply_op> <prefix_expression> )*
|
||||||
|
|
||||||
|
<prefix_expression> =
|
||||||
|
<prefix_op>* <primary_expression>
|
||||||
|
|
||||||
|
<primary_expression> =
|
||||||
|
<primary_type_expression> ( <suffix_op> | <fn_call_arguments> )*
|
||||||
|
|
||||||
|
|
||||||
|
/* --- Primary Expressions & Literals --- */
|
||||||
|
/* The highest-precedence expressions, including literals and grouped expressions. */
|
||||||
|
|
||||||
|
<primary_type_expression> =
|
||||||
|
<char_literal>
|
||||||
|
| <null_literal>
|
||||||
|
| <string_literal>
|
||||||
|
| <number_literal>
|
||||||
|
| <boolean_literal>
|
||||||
|
| <grouped_expression>
|
||||||
|
| <identifier>
|
||||||
|
| <struct_literal>
|
||||||
|
| <scoped_access_expression>
|
||||||
|
| <reflection_expression>
|
||||||
|
|
||||||
|
<grouped_expression> =
|
||||||
|
"(" <expression> ")"
|
||||||
|
|
||||||
|
<scoped_access_expression> =
|
||||||
|
<type_name> "::" <identifier>
|
||||||
|
|
||||||
|
<reflection_expression> =
|
||||||
|
( <primary_expression> | <type_name> | <scoped_access_expression> ) ".@" <identifier>?
|
||||||
|
|
||||||
|
<fn_call_arguments> =
|
||||||
|
"(" <expression_list> ")"
|
||||||
|
|
||||||
|
<expression_list> =
|
||||||
|
(<expression> ",")* <expression>?
|
||||||
|
|
||||||
|
<struct_literal> =
|
||||||
|
<type> "{" ( <named_field_list> | <positional_field_list> )? ","? "}"
|
||||||
|
|
||||||
|
<named_field_list> =
|
||||||
|
<named_field_init> ( "," <named_field_init> )*
|
||||||
|
|
||||||
|
<named_field_init> =
|
||||||
|
<identifier> ":" <expression>
|
||||||
|
|
||||||
|
<positional_field_list> =
|
||||||
|
<expression> ( "," <expression> )*
|
||||||
|
|
||||||
|
<null_literal> =
|
||||||
|
"null"
|
||||||
|
|
||||||
|
<boolean_literal> =
|
||||||
|
"true"
|
||||||
|
| "false"
|
||||||
|
|
||||||
|
<number_literal> = /* Assumed to be defined by the tokenizer */
|
||||||
|
<string_literal> = /* Assumed to be defined by the tokenizer */
|
||||||
|
<char_literal> = /* Assumed to be defined by the tokenizer */
|
||||||
|
|
||||||
|
|
||||||
|
/* --- Operators --- */
|
||||||
|
/* Definitions for all operator token sets. */
|
||||||
|
|
||||||
|
<assign_op> = "="
|
||||||
|
<compound_assign_op> = "+=" | "-=" | "*=" | "/=" | "%=" | "&=" | "|=" | "<<=" | ">>=" | "||=" | "&&="
|
||||||
|
<compare_op> = "==" | "!=" | ">" | "<" | ">=" | "<="
|
||||||
|
<bitwise_op> = "&" | "^" | "|"
|
||||||
|
<bitshift_op> = "<<" | ">>"
|
||||||
|
<addition_op> = "+" | "-"
|
||||||
|
<multiply_op> = "*" | "/" | "%"
|
||||||
|
<prefix_op> = "!" | "-" | "~" | "&" | "*"
|
||||||
|
|
||||||
|
<suffix_op> =
|
||||||
|
"[" <expression>? ":" <expression>? "]"
|
||||||
|
| "[" <expression> "]"
|
||||||
|
| ".[" <expression> "]"
|
||||||
|
| "." <identifier>
|
||||||
|
| "->" <identifier>
|
||||||
|
| ".#"
|
||||||
|
| ".*"
|
||||||
|
|
||||||
|
/* --- Type System --- */
|
||||||
|
/* Rules for defining types, type names, and type qualifiers. */
|
||||||
|
|
||||||
|
<type> =
|
||||||
|
<type_qualifier_chain> <type_name>
|
||||||
|
|
||||||
|
<type_qualifier_chain> =
|
||||||
|
( "*" | "[]" ) <type_qualifier_chain>?
|
||||||
|
| "$" <type_qualifier_chain_after_mutable>?
|
||||||
|
| "?" <type_qualifier_chain_after_optional>?
|
||||||
|
|
||||||
|
<type_qualifier_chain_after_optional> =
|
||||||
|
( "*" | "[]" ) <type_qualifier_chain>?
|
||||||
|
| "$" <type_qualifier_chain_after_mutable>?
|
||||||
|
|
||||||
|
<type_qualifier_chain_after_mutable> =
|
||||||
|
( "*" | "[]" ) <type_qualifier_chain>?
|
||||||
|
| "?" <type_qualifier_chain_after_optional>?
|
||||||
|
|
||||||
|
<type_name> =
|
||||||
|
<namespaced_identifier> ( "<" <types_list> ">" )?
|
||||||
|
|
||||||
|
<namespaced_identifier> =
|
||||||
|
<identifier>
|
||||||
|
| <identifier> "::" <namespaced_identifier>
|
||||||
|
|
||||||
|
<types_list> =
|
||||||
|
<type> ( "," <types_list> )*
|
||||||
|
|
||||||
|
|
||||||
|
/* --- Lexical Tokens & Base Definitions --- */
|
||||||
|
/* The lowest-level building blocks of the language. */
|
||||||
|
|
||||||
|
<identifier> =
|
||||||
|
<nondigit> <identifier_tail>
|
||||||
|
|
||||||
|
<identifier_tail> =
|
||||||
|
<empty>
|
||||||
|
| <nondigit> <identifier_tail>
|
||||||
|
| <digit> <identifier_tail>
|
||||||
|
|
||||||
|
<nondigit> = "_" | [a-z] | [A-Z]
|
||||||
|
<digit> = <zero> | <nonzero_digit>
|
||||||
|
<zero> = "0"
|
||||||
|
<nonzero_digit> = [1-9]
|
||||||
|
|
||||||
|
<empty> = E /* Represents an empty terminal string */
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user