プログラミング言語を自作してみる②

# 前回の続き

[前回](https://qiita.com/johnny-shaman/items/042d8fb5016db00fab9f)からの続きです。
言語処理系などについての事前知識を勉強しながら、~~chatGPT~~ Claude3.5Sonnet とともに、設計をpest.rsで対話的に作成していきました。
~~ここまで大体３日ほどでしょうか？~~
まだまだ策定してるようなので、鋭意更新中です。
最初の設計からはずいぶん変わりました。
本来の言語設計のイメージを固めると、別の言語が出来てので①も更新しました。
(^_^;)

実装段階でなにか問題が出れば、もちろん見直す部分ですが、使用する記号などは明確化されています。

```rust,should_panic
WHITESPACE = _{ " " | "\r" | "\n"}

program = { SOI ~ expression* ~ EOI }

expression = { export }

export = { f_export? ~ assign }
assign = { lambda ~ (f_assign ~ assign)? }
lambda = { product+ ~ (f_lambda ~ lambda)? }
product = { spread ~ (f_product ~ product)? }
spread = { lift ~ (f_spread ~ lift)? }
lift = { f_spread* ~ or_xor }
or_xor = { and ~ ((f_or | f_xor) ~ or_xor)? }
and = { not ~ (f_and ~ and)? }
not = { f_not* ~ compare }
compare = { add ~ (compare_op ~ compare)? }
add = { mul ~ ((f_add | f_sub) ~ add)? }
mul = { power ~ ((f_mul | f_div | f_mod) ~ mul)? }
power = { factorial ~ (f_power ~ power)? }
factorial = { flat ~ f_factorial* }
flat = { apply ~ f_spread* }
apply = { get ~ apply? }
get = { import ~ (f_get ~ get)? }
import = { f_import? ~ block }

block = {
  (f_block* ~ primary)
  | "(" ~ expression ~ ")"
  | "[" ~ expression ~ "]"
  | "{" ~ expression ~ "}"
}

primary = {
    literal
  | point_free
  | partial_application
  | "(" ~ lambda ~ ")"
  | "{" ~ lambda ~ "}"
  | "[" ~ lambda ~ "]"
  | "(" ~ point_free ~ ")"
  | "{" ~ point_free ~ "}"
  | "[" ~ point_free ~ "]"
  | "(" ~ partial_application ~ ")"
  | "{" ~ partial_application ~ "}"
  | "[" ~ partial_application ~ "]"
}

point_free = {
    prefix
  | postfix_point_free
  | infix
  | infix_l
  | infix_r
  | (literal | identifier) ~ infix
  | (literal | identifier) ~ infix_l
  | (literal | identifier) ~ infix_r
  | infix ~ (literal | identifier)
  | infix_l ~ (literal | identifier)
  | infix_r ~ (literal | identifier)
}

postfix_point_free = @{ "_" ~ postfix }
partial_application = { (identifier | point_free) ~ primary* ~ unit }

prefix = { f_not | f_spread }
infix_l = { f_product | f_or | f_xor | f_and | f_add | f_sub | f_mul | f_div | f_mod | f_get }
infix_r = { f_assign | f_lambda | f_power }
postfix = { f_factorial | f_spread }

infix = { compare_op | f_spread}
compare_op = { f_less | f_less_eq | f_eq | f_neq | f_more_eq | f_more }

f_export = { "#" }
f_assign = { ":" }
f_lambda = { "?" }
f_or = { "|" }
f_xor = { ";" }
f_and = { "&" }
f_less = { "<" }
f_less_eq = { "<=" }
f_eq = { "=" | "==" }
f_neq = { "!=" }
f_more_eq = { ">=" }
f_more = { ">" }
f_add = { "+" }
f_sub = { "-" }
f_mul = { "*" }
f_div = { "/" }
f_mod = { "%" }
f_power = { "^" }
f_product = { "," }
f_not = { "!" }
f_spread = { "~" }
f_factorial = { "!" }
f_get = { "'" }
f_import = { "@" }
f_block = { "\t" }

literal = { number | string | char | unit | identifier }
number = { hex | oct | bit | float | uint | int}
uint = @{ ASCII_DIGIT+ }
int = @{ "-"? ~ ASCII_DIGIT+ ~ !(("." ~ ASCII_DIGIT*) | "e" | "E") }
float = @{ 
    "-"? ~ (
        (ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT* ~ (^"e" ~ ("+" | "-")? ~ ASCII_DIGIT+)?) |
        (ASCII_DIGIT+ ~ ^"e" ~ ("+" | "-")? ~ ASCII_DIGIT+) |
        ("." ~ ASCII_DIGIT+ ~ (^"e" ~ ("+" | "-")? ~ ASCII_DIGIT+)?)
    )
}
hex = @{ "0x" ~ ASCII_HEX_DIGIT+ }
oct = @{ "0o" ~ ASCII_OCT_DIGIT+ }
bit = @{ "0b" ~ ASCII_BIN_DIGIT+ }
string = { "`" ~ (!("`" | "\n") ~ (" " | ANY))* ~ "`" }
char = @{ "\\" ~ (NEWLINE | " " | ANY) }
identifier = @{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC | "_")* }
unit = { "_" | "[]" }

```

式指向の言語であるための仕様がモリモリです😂
この言語の最大の特徴の一つは、文字列にエスケープシーケンスが必要ないことです。

```
 `文字列` `は簡単に` `結合できる` \
 `改行も、簡単に…`
```

次回から、実装にかかりたいと思います。