Improved grammar
This commit is contained in:
+43
-16
@@ -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
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user