Improved grammar

This commit is contained in:
2026-04-13 14:33:48 +02:00
parent 2ef7c1c184
commit 9882626397
2 changed files with 84 additions and 57 deletions
+43 -16
View File
@@ -13,40 +13,65 @@ string_lit = { "\"" ~ inner_str ~ "\"" }
inner_str = @{ (!"\"" ~ ANY)* } inner_str = @{ (!"\"" ~ ANY)* }
// top level // top level
import_decl = { "import" ~ string_lit } import_decl = { "import" ~ string_lit ~ ";" }
struct_decl = { "struct" ~ identifier ~ "{" ~ struct_field* ~ "}" }
class_decl = { "class" ~ identifier ~ "{" ~ class_member* ~ "}" } struct_decl = {
"struct" ~ identifier ~ "{" ~ struct_field* ~ "}"
}
class_decl = {
"class" ~ identifier ~ "{" ~ class_member* ~ "}"
}
class_member = _{ struct_field | function_decl } class_member = _{ struct_field | function_decl }
function_decl = { "fn" ~ identifier ~ "(" ~ param_list? ~ ")" ~ ("->" ~ type_expr)? ~ block } function_decl = {
"fn" ~ identifier ~ "(" ~ param_list? ~ ")" ~ ("->" ~ type_expr)? ~ block
}
struct_field = { identifier ~ ":" ~ type_expr } // struct fields (NO commas, Go-style)
param_list = { param ~ ("," ~ param)* } struct_field = { identifier ~ ":" ~ type_expr ~ ";" }
param = { identifier ~ ":" ~ type_expr }
// params (allow trailing comma)
param_list = { param ~ ("," ~ param)* ~ ","? }
param = { identifier ~ ":" ~ type_expr }
// statements // statements
block = { "{" ~ statement* ~ "}" } block = { "{" ~ statement* ~ "}" }
statement = _{ statement = _{
let_stmt let_stmt
| return_stmt | return_stmt
| if_stmt | if_stmt
| for_stmt | for_stmt
| assign_stmt | assign_stmt
| expression | expression_stmt
} }
assign_stmt = { identifier ~ "=" ~ expression } expression_stmt = { expression ~ ";" }
let_stmt = { "let" ~ identifier ~ (":" ~ type_expr)? ~ "=" ~ expression }
return_stmt = { "return" ~ expression? } assign_stmt = { identifier ~ "=" ~ expression ~ ";" }
if_stmt = { "if" ~ expression ~ block ~ ("else" ~ block)? }
for_stmt = { "for" ~ identifier ~ "in" ~ expression ~ block } let_stmt = {
"let" ~ identifier ~ (":" ~ type_expr)? ~ "=" ~ expression ~ ";"
}
return_stmt = { "return" ~ expression? ~ ";" }
if_stmt = {
"if" ~ expression ~ block ~ ("else" ~ block)?
}
for_stmt = {
"for" ~ identifier ~ "in" ~ expression ~ block
}
// types // types
type_expr = { base_type ~ "?"? } type_expr = { base_type ~ "?"? }
base_type = _{ array_type | identifier } base_type = _{ array_type | identifier }
array_type = { "[" ~ type_expr ~ "]" } array_type = { "[" ~ type_expr ~ "]" }
// expressions (still simple, no precedence yet) // expressions (still no precedence yet)
expression = { term ~ (bin_op ~ term)* } expression = { term ~ (bin_op ~ term)* }
bin_op = _{ bin_op = _{
@@ -78,6 +103,7 @@ and = { "&&" }
or = { "||" } or = { "||" }
// literals // literals
struct_literal = { struct_literal = {
identifier ~ "{" ~ struct_init_list? ~ "}" identifier ~ "{" ~ struct_init_list? ~ "}"
} }
@@ -94,7 +120,7 @@ array_literal = {
"[" ~ (expression ~ ("," ~ expression)*)? ~ ","? ~ "]" "[" ~ (expression ~ ("," ~ expression)*)? ~ ","? ~ "]"
} }
// expressions continuation // chaining
term = { primary ~ (field_access | call_suffix)* } term = { primary ~ (field_access | call_suffix)* }
field_access = { "." ~ identifier } field_access = { "." ~ identifier }
@@ -103,6 +129,7 @@ call_suffix = {
"(" ~ (expression ~ ("," ~ expression)*)? ~ ","? ~ ")" "(" ~ (expression ~ ("," ~ expression)*)? ~ ","? ~ ")"
} }
// primary
primary = _{ primary = _{
struct_literal struct_literal
| array_literal | array_literal
+41 -41
View File
@@ -1,120 +1,120 @@
import "fmt" import "fmt";
import "strings" import "strings";
// structs are plain data // structs are plain data
struct Point { struct Point {
x: float x: float;
y: float y: float;
} }
// classes have fields and methods // classes have fields and methods
class Animal { class Animal {
name: string name: string;
age: int age: int;
fn speak() -> string { fn speak() -> string {
return "..." return "...";
} }
fn describe() -> string { fn describe() -> string {
return "I am " + self.name return "I am " + self.name;
} }
} }
class Dog { class Dog {
name: string name: string;
age: int age: int;
fn speak() -> string { fn speak() -> string {
return "Woof!" return "Woof!";
} }
fn fetch(item: string) -> string { fn fetch(item: string) -> string {
return self.name + " fetched the " + item return self.name + " fetched the " + item;
} }
} }
// basic function // basic function
fn add(a: int, b: int) -> int { fn add(a: int, b: int) -> int {
return a + b return a + b;
} }
// optional return type // optional return type
fn find(name: string) -> string? { fn find(name: string) -> string? {
if name == "mist" { if name == "mist" {
return name return name;
} }
return null return null;
} }
// array types // array types
fn sum(numbers: [int]) -> int { fn sum(numbers: [int]) -> int {
let total: int = 0 let total: int = 0;
for n in numbers { for n in numbers {
total = total + n total = total + n;
} }
return total return total;
} }
// multiple params, no return // multiple params, no return
fn greet(first: string, last: string) { fn greet(first: string, last: string) {
let full: string = first + " " + last let full: string = first + " " + last;
print(full) print(full);
} }
// structs initialized with fields // structs initialized with fields
fn make_point(x: float, y: float) -> Point { fn make_point(x: float, y: float) -> Point {
return Point { return Point {
x: x, x: x,
y: y y: y,
} };
} }
// if / else // if / else
fn classify(n: int) -> string { fn classify(n: int) -> string {
if n < 0 { if n < 0 {
return "negative" return "negative";
} else { } else {
return "positive" return "positive";
} }
} }
// entry point // entry point
fn main() { fn main() {
// variables // variables
let x: int = 10 let x: int = 10;
let y: int = 20 let y: int = 20;
let result: int = add(x, y) let result: int = add(x, y);
// inferred (no type annotation) // inferred (no type annotation)
let message = "Hello from Mist!" let message = "Hello from Mist!";
print(message) print(message);
// struct usage // struct usage
let p: Point = make_point(1.5, 2.5) let p: Point = make_point(1.5, 2.5);
print(p.x) print(p.x);
// class usage // class usage
let dog: Dog = Dog { let dog: Dog = Dog {
name: "Rex", name: "Rex",
age: 3 age: 3,
} };
print(dog.speak()) print(dog.speak());
print(dog.fetch("ball")) print(dog.fetch("ball"));
// arrays // arrays
let nums: [int] = [1, 2, 3, 4, 5] let nums: [int] = [1, 2, 3, 4, 5];
let total: int = sum(nums) let total: int = sum(nums);
print(total) print(total);
// for loop // for loop
for n in nums { for n in nums {
print(n) print(n);
} }
// optional // optional
let found: string? = find("mist") let found: string? = find("mist");
if found { if found {
print(found) print(found);
} }
} }