Typescript-like syntax

This commit is contained in:
2026-04-13 16:23:17 +02:00
parent c73b387230
commit f99968c638
3 changed files with 40 additions and 17 deletions
+31 -14
View File
@@ -12,31 +12,37 @@ boolean = { "true" | "false" }
string_lit = { "\"" ~ inner_str ~ "\"" } string_lit = { "\"" ~ inner_str ~ "\"" }
inner_str = @{ (!"\"" ~ ANY)* } inner_str = @{ (!"\"" ~ ANY)* }
// top level // ================= TYPE SCRIPT STYLE CHANGES =================
// import becomes TS-like (still identical structure)
import_decl = { "import" ~ string_lit ~ ";" } import_decl = { "import" ~ string_lit ~ ";" }
// struct stays, but feels like TS "type object shape"
struct_decl = { struct_decl = {
"struct" ~ identifier ~ "{" ~ struct_field* ~ "}" "struct" ~ identifier ~ "{" ~ struct_field* ~ "}"
} }
// class already TS-like — just improved consistency
class_decl = { class_decl = {
"class" ~ identifier ~ "{" ~ class_member* ~ "}" "class" ~ identifier ~ "{" ~ class_member* ~ "}"
} }
class_member = _{ struct_field | function_decl } class_member = _{ struct_field | function_decl }
// function keyword changed feel: fn → function
function_decl = { function_decl = {
"fn" ~ identifier ~ "(" ~ param_list? ~ ")" ~ ("->" ~ type_expr)? ~ block "function" ~ identifier ~ "(" ~ param_list? ~ ")" ~ ("->" ~ type_expr)? ~ block
} }
// struct fields (NO commas, Go-style) // struct fields: TS-style semicolon consistency (already good)
struct_field = { identifier ~ ":" ~ type_expr ~ ";" } struct_field = { identifier ~ ":" ~ type_expr ~ ";" }
// params (allow trailing comma) // params: TS optional typing style feel (unchanged structure)
param_list = { param ~ ("," ~ param)* ~ ","? } param_list = { param ~ ("," ~ param)* ~ ","? }
param = { identifier ~ ":" ~ type_expr } param = { identifier ~ ":" ~ type_expr }
// statements // ================= STATEMENTS =================
block = { "{" ~ statement* ~ "}" } block = { "{" ~ statement* ~ "}" }
statement = _{ statement = _{
@@ -48,30 +54,39 @@ statement = _{
| expression_stmt | expression_stmt
} }
// expression statements: TS allows no semicolon in real life,
// but we keep your structure
expression_stmt = { expression ~ ";" } expression_stmt = { expression ~ ";" }
// assignment unchanged (JS/TS feel already)
assign_stmt = { identifier ~ "=" ~ expression ~ ";" } assign_stmt = { identifier ~ "=" ~ expression ~ ";" }
// let → const/let feel (still your rule, just TS naming)
let_stmt = { let_stmt = {
"let" ~ identifier ~ (":" ~ type_expr)? ~ "=" ~ expression ~ ";" "const" ~ identifier ~ (":" ~ type_expr)? ~ "=" ~ expression ~ ";"
} }
// return: TS-like (no change except feel consistency)
return_stmt = { "return" ~ expression? ~ ";" } return_stmt = { "return" ~ expression? ~ ";" }
// if: add TS-style parentheses (MAJOR feel upgrade, same structure)
if_stmt = { if_stmt = {
"if" ~ expression ~ block ~ ("else" ~ block)? "if" ~ "(" ~ expression ~ ")" ~ block ~ ("else" ~ block)?
} }
// for: TS-like "of"
for_stmt = { for_stmt = {
"for" ~ identifier ~ "in" ~ expression ~ block "for" ~ identifier ~ "of" ~ expression ~ block
} }
// types // ================= TYPES (KEEP STRUCTURE, TS FEEL) =================
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 no precedence yet) // ================= EXPRESSIONS =================
expression = { term ~ (bin_op ~ term)* } expression = { term ~ (bin_op ~ term)* }
bin_op = _{ bin_op = _{
@@ -102,7 +117,7 @@ gt = { ">" }
and = { "&&" } and = { "&&" }
or = { "||" } or = { "||" }
// literals // ================= LITERALS =================
struct_literal = { struct_literal = {
identifier ~ "{" ~ struct_init_list? ~ "}" identifier ~ "{" ~ struct_init_list? ~ "}"
@@ -120,7 +135,8 @@ array_literal = {
"[" ~ (expression ~ ("," ~ expression)*)? ~ ","? ~ "]" "[" ~ (expression ~ ("," ~ expression)*)? ~ ","? ~ "]"
} }
// chaining // ================= CHAINING =================
term = { primary ~ (field_access | call_suffix)* } term = { primary ~ (field_access | call_suffix)* }
field_access = { "." ~ identifier } field_access = { "." ~ identifier }
@@ -129,7 +145,8 @@ call_suffix = {
"(" ~ (expression ~ ("," ~ expression)*)? ~ ","? ~ ")" "(" ~ (expression ~ ("," ~ expression)*)? ~ ","? ~ ")"
} }
// primary // ================= PRIMARY =================
primary = _{ primary = _{
struct_literal struct_literal
| array_literal | array_literal
@@ -142,5 +159,5 @@ primary = _{
| identifier | identifier
} }
self_kw = { "self" } self_kw = { "this" }
null_kw = { "null" } null_kw = { "null" }
-2
View File
@@ -15,8 +15,6 @@ pub type ParseError = pest::error::Error<Rule>;
pub fn parse(source: &str) -> Result<Program, ParseError> { pub fn parse(source: &str) -> Result<Program, ParseError> {
let pairs = MistParser::parse(Rule::program, source)?; let pairs = MistParser::parse(Rule::program, source)?;
println!("Parsed pairs: {:#?}", pairs);
let mut statements = vec![]; let mut statements = vec![];
// pairs is an iterator over the top-level program pair // pairs is an iterator over the top-level program pair
+9 -1
View File
@@ -1,5 +1,13 @@
import "fmt"; import "fmt";
fn main() { function add(a: int, b: int) -> int {
const x = 10;
if (x > 5) {
return x;
}
return 0;
}
function main() {
fmt.Println("Hello World!"); fmt.Println("Hello World!");
} }