構文規範
本ファイルは YaoXiang プログラミング言語の構文規範を定義ものであり字句構造、構文規則、演算子優先順位を含みます。
第1章:字句構造
1.1 ソースファイル
YaoXiang ソースファイルは UTF-8 エンコーディングを使用する必要があります。ソースファイルは通常 .yx を拡張子とします。
1.2 字句トークン分類
| カテゴリ | 説明 | 例 |
|---|---|---|
| 識別子 | 文字またはアンダースコアで開始 | x, _private, my_var |
| キーワード | 言語定義の予約語 | Type, pub, use |
| リテラル | 固定値 | 42, "hello", true |
| 演算子 | 演算記号 | +, -, *, / |
| 区切り子 | 構文区切り | (, ), {, }, , |
1.3 キーワード
YaoXiang は極めて少数のキーワードを定義しています:
pub use spawn
ref mut if else
else match while for return
break continue as in unsafeこれらのキーワードは任意のコンテキストにおいて特殊意味を持ち、識別子として使用できません。
1.4 予約語
YaoXiang の「予約語」は3層構成であり、パーサー(parser)と型検査器(type checker)が異なる段階で識別します:
1.4.1 リテラルの予約語
パーサーが独立したトークンを持つリテラル識別子は通常の識別子として使用できません:
| 識別子 | 所属型 | 説明 |
|---|---|---|
Type | — | メタ型キーワード |
true | Bool | ブール真値 |
false | Bool | ブール偽値 |
void | Void | Void リテラル(Unit 値)。小文字 void は値リテラル、大文字 Void は型名(§1.4.3 参照)。 |
1.4.2 構築子式
以下の構築子はパターン照合および式のコンテキストでパーサーによって識別されます:
| 構築子 | 所属型 | 説明 |
|---|---|---|
some(T) | Option | Option 値変体構築 |
ok(T) | Result | Result 成功変体 |
err(E) | Result | Result エラー変体 |
1.4.3 組み込み型名
以下の型名は型検査器によって事前登録されており、インポートなしで使用できます。パーサーはこれらを通常の識別子として扱います——予約語ではなく、局所束縛で shadow 可能(推奨はしません)。
| 型名 | 論理対応 | 説明 |
|---|---|---|
Void | ⊤(真/Unit) | 零フィールド積型、ちょうど1つの常住者(void リテラル、§1.4.1 参照) |
Never | ⊥(偽/空型) | 零バリアントを持つ型で常住者が存在しない。任何の式も Never 値を生成できません。Never <: T は全ての T に対して成立(爆発原理)。 |
Int | — | 符号付き整数 |
Float | — | 浮動小数点数 |
Bool | — | ブール値:true / false |
Char | — | Unicode 文字 |
String | — | 文字列 |
1.5 識別子
識別子は文字またはアンダースコアで開始し、後続の文字は文字、数字、またはアンダースコアを使用できます。識別子は大小文字を区別します。
特殊識別子:
_はプレースホルダーとして使用され、特定の値を無視することを示します- アンダースコアで始まる識別子はプライベートメンバーを示します
1.6 リテラル
1.6.1 整数
Decimal ::= [0-9][0-9_]*
Octal ::= 0o[0-7][0-7_]*
Hex ::= 0x[0-9a-fA-F][0-9a-fA-F_]*
Binary ::= 0b[01][01_]*1.6.2 浮動小数点数
Float ::= [0-9][0-9_]* '.' [0-9][0-9_]* ([eE][+-]?[0-9][0-9_]*)?1.6.3 文字列
String ::= '"' ([^"\\] | EscapeSequence)* '"'
Escape ::= '\\' ([nrt'"\\] | UnicodeEscape)
Unicode ::= 'u' '{' HexDigit+ '}'1.6.4 コレクション
List ::= '[' Expr (',' Expr)* ']'
Dict ::= '{' String ':' Expr (',' String ':' Expr)* '}'
Set ::= '{' Expr (',' Expr)* '}'1.6.5 リスト内包表記
ListComp ::= '[' Expr 'for' Identifier 'in' Expr (',' Expr)* ('if' Expr)? ']'1.6.6 メンバー検査
Membership ::= Expr 'in' Expr1.7 コメント
// 単一行コメント
/* 複数行コメント
複数行にまたがる可能 */1.8 インデント規則
コードは4スペースのインデントを使用する必要があります。Tab 文字の使用は禁止です。これは強制的な構文規則です。
第2章:構文規則
2.1 式分類
Expr ::= Literal
| Identifier
| FnCall
| MemberAccess
| IndexAccess
| UnaryOp
| BinaryOp
| TypeCast
| RangeExpr
| ErrorPropagate
| RefExpr
| IfExpr
| MatchExpr
| Block
| Lambda2.2 演算子優先順位
| 優先順位 | 演算子 | 結合性 |
|---|---|---|
| 1 | () [] . ? | 左から右 |
| 2 | as | 左から右 |
| 3 | * / % | 左から右 |
| 4 | + - | 左から右 |
| 5 | .. | 左から右 |
| 6 | << >> | 左から右 |
| 7 | & | ^ | 左から右 |
| 8 | == != < > <= >= | 左から右 |
| 9 | not | 右から左 |
| 10 | and or | 左から右 |
| 11 | if...else | 右から左 |
| 12 | = += -= *= /= | 右から左 |
2.3 関数呼び出し
FnCall ::= Expr '(' ArgList? ')'
ArgList ::= Expr (',' Expr)* (',' NamedArg)* | NamedArg (',' NamedArg)*
NamedArg ::= Identifier ':' Expr2.4 メンバーアクセス
MemberAccess::= Expr '.' Identifier2.5 インデックスアクセス
IndexAccess ::= Expr '[' Expr ']'2.6 型キャスト
TypeCast ::= Expr 'as' TypeExpr2.7 条件式
IfExpr ::= 'if' Expr Block ('else' 'if' Expr Block)* ('else' Block)?2.8 パターン照合
MatchExpr ::= 'match' Expr '{' MatchArm+ '}'
MatchArm ::= Pattern ('|' Pattern)* ('if' Expr)? '=>' Expr ','
Pattern ::= Literal
| Identifier
| Wildcard
| StructPattern
| TuplePattern
| EnumPattern
| OrPattern2.9 ブロック式
Block ::= '{' Stmt* Expr? '}'統一セマンティクス:全ての {} ブロックの return セマンティクスは一貫しています:
| ブロック型 | return セマンティクス | デフォルト返り値 |
|---|---|---|
通常 {} | 値を返す | Void |
unsafe {} | 型定義を返す | Void |
spawn {} | 結果を返す | Void |
基本原則:
{}内のreturnは常に内容を上位スコープに返しますreturnがない場合のデフォルト返り値はVoid- 式形式
= exprは直接値を返します
// 通常 {} ブロック:return で値を返す
result = {
x = compute()
return x // 上位スコープに値を返す
}
// unsafe {} ブロック:return で型定義を返す
SqliteDb = unsafe {
SqliteDb: Type = {
handle: *Void
}
return SqliteDb // 型定義を上位スコープに返す
}
// spawn {} ブロック:return で結果を返す
(a, b) = spawn {
result1 = fetch("url1"),
result2 = fetch("url2")
return (result1, result2) // 結果を上位スコープに返す
}2.10 ラムダ式
Lambda ::= '(' ParamList? ')' '=>' Expr
| '(' ParamList? ')' '=>' Block2.11 エラー伝播演算子
ErrorPropagate ::= Expr '?'? 演算子は後置演算子であり、優先順位は . と同レベルです。Result(T, E) 型に対して:
Ok(v)の場合は値vを抽出して続行Err(e)の場合はエラーを上位に伝播(return Err(e))
process: (data: Data) -> Result(Data, Error) = {
validated = validate(data)? // 成功時:値を抽出、失敗時:上位に伝播
transform(validated)
}2.12 範囲式
RangeExpr ::= Expr '..' Expr.. は範囲型を作成し、for ループとスライスに使用されます。
for i in 0..10 { print(i) }
slice = array[0..5]2.13 ref 式
RefExpr ::= 'ref' Exprref は共有所有権を作成します。コンパイラが自動的に Rc(単一タスク)または Arc(タスク間)を選択するため、ユーザーは実装詳細を気にする必要はありません。
data = ref heavy_data
spawn { use(data) } // タスク間:コンパイラが自動的に Arc を選択2.14 unsafe 式
UnsafeExpr ::= 'unsafe' Blockunsafe ブロックは不透明型和裸ポインタ操作の定義に使用されます。return を使用して型定義を上位スコープに返します。
セマンティクス:
unsafe {}内で型和裸ポインタ操作を定義できます- 返された型は
unsafe {}外で使用可能 - 型のフィールドアクセスには unsafe 権限が必要
// unsafe ブロック内で不透明型を定義
SqliteDb = unsafe {
SqliteDb: Type = {
handle: *Void // 裸ポインタ
}
return SqliteDb
}
// SqliteDb は unsafe ブロック外で使用可能
db = sqlite3_open("test.db")2.15 スコープ
基本規則:
- 各
{}ブロックはスコープを作成します - 内側スコープは外側スコープの変数にアクセス可能
- 外側スコープは内側スコープの変数にアクセス不可
- 変数宣言は「代入優先」原則に従います
// ブロックスコープ
{
x = 10
// x はこのスコープ内で可視
}
// x はこのスコープ外で不可視
// 関数スコープ
add: (a: Int, b: Int) -> Int = {
result = a + b
return result
}
// result は関数外で不可視変数宣言とシャドーイング:
x = value:スコープチェーンを外に向かって検索し、x が見つかれば代入、なければ新規宣言mut x = value:明示的な新規可変宣言。上位スコープの同名変数を禁止- 同一スコープ内で同じ名前は一度のみ宣言可能
詳細定義:スコープの完全な規則、変数宣言およびシャドーイング機構の詳細についてはモジュールシステム規範を参照してください。
第3章:文
3.1 文分類
Stmt ::= LetStmt
| ExprStmt
| ReturnStmt
| BreakStmt
| ContinueStmt
| IfStmt
| MatchStmt
| WhileStmt
| ForStmt
| SpawnStmt3.2 変数宣言
LetStmt ::= ('mut')? Identifier (':' TypeExpr)? '=' Expr3.3 return 文
ReturnStmt ::= 'return' Expr?セマンティクス:return はコードブロックから値を返すために使用されます。return がない場合、コードブロックはデフォルトで Void を返します。
3.4 break 文
BreakStmt ::= 'break' Identifier?3.5 continue 文
ContinueStmt::= 'continue'3.6 if 文
IfStmt ::= 'if' Expr Block ('else' 'if' Expr Block)* ('else' Block)?3.7 match 文
MatchStmt ::= 'match' Expr '{' MatchArm+ '}'3.8 while 文
WhileStmt ::= 'while' Expr Block3.9 for 文
ForStmt ::= 'for' 'mut'? Identifier 'in' Expr Block3.9.1 セマンティクス:各イテレーションは新しい値を束縛
YaoXiang の for ループは従来の言語異なります:各イテレーションは新しい値を束縛であり、同じ変数を変更するものではありません。
// 例:for i in 1..5
for i in 1..5 {
print(i)
}実行プロセス:
| イテレーション | ループ変数の動作 |
|---|---|
| 1回目 | 新規束縛 i = 1 を作成、ループ本体実行、1 を出力 |
| 2回目 | 新規束縛 i = 2 を作成(以前の束縛は破棄済み)、ループ本体実行、2 を出力 |
| 3回目 | 新規束縛 i = 3 を作成、ループ本体実行、3 を出力 |
| 4回目 | 新規束縛 i = 4 を作成、ループ本体実行、4 を出力 |
| 終了 | ループ本体終了、束縛破棄 |
要点:各イテレーション終了後、そのイテレーションで作成された束縛は破棄されます。次のイテレーションは前回の束縛とは全く関係のない新規の束縛です。
3.9.2 for と for mut の違い
| 構文 | ループ変数の可変性 | 説明 |
|---|---|---|
for i in 1..5 | 不変 | ループ本体内で束縛を変更不可 |
for mut i in 1..5 | 可変 | ループ本体内で束縛を変更可能 |
// 有効:各イテレーションで新しい値を束縛するため、変更の必要なし
for i in 1..5 {
print(i) // i の値を読み取り
}
// 誤り:不変束縛なので変更不可
for i in 1..5 {
i = i + 1 // 誤り:不変束縛は変更不可
}
// 有効:for mut を使用すると束縛の変更を許可
for mut i in 1..5 {
i = i + 1 // 許可
}3.9.3 シャドーイング検査
YaoXiang は変数のシャドーイングを禁止します。for ループ変数は上位スコープの変数と同じ名前を使用できません:
// 誤り:i はすでに外部で宣言済み
i = 10
for i in 1..5 {
print(i)
}
// 正しい:異なる変数名を使用
i = 10
for j in 1..5 {
print(j)
}この規則は全てのコードブロックに適用されます。詳細については4.3 シャドーイング規則を参照してください。
3.9.4 他の言語との比較
| 言語 | for ループ変数のセマンティクス |
|---|---|
| YaoXiang | 各イテレーションで新しい値を束縛 |
| Rust | 同じ変数を変更(mut が必要) |
| Python | 同じ変数を変更(mut 不要) |
| C/C++ | 同じ変数を変更(ポインタまたは参照が必要) |
設計理由:YaoXiang が束縛セマンティクスを選択したのは:
より自然なセマンティクスに符合 自然言語では「集合内の各要素 x について」は、各 x が独立した存在であることを意味します。YaoXiang の
for i in 1..5は「1 から 5 の中の各 i について」と読み、各イテレーションの i は全く新しい束縛であり、人間の直感と一致します。偶発的な変更を回避 デフォルトで不変の束縛セマンティクスは、ループ本体内でループ変数を偶発的に変更できないことを意味します。複雑なループ本体内でうっかり
i = ...と書いて追跡困難なバグを発生させる心配がありません。高性能ソリューションが簡単に利用可能 イテレーション間で変数を再利用する必要がある場合(例:アキュムレータ、キャッシュ)、
for mutを使用して可変束縛モードに切り替えられます。これは暗黙の共有状態より明確です——意図は構文で明示的に表現され、ランタイム動作に隠されません。
3.10 spawn 文
SpawnBlock ::= '(' Pattern (',' Pattern)* ')' '=' 'spawn' '{' Expr (',' Expr)* '}'
SpawnFor ::= Identifier '=' 'spawn' 'for' 'mut'? Identifier 'in' Expr '{' Expr '}'
SpawnStmt ::= SpawnBlock | SpawnForspawn ブロック:並行領域を明示的に宣言し、ブロック内の式は並行実行されます。
(result_a, result_b) = spawn {
parse(fetch("url1")),
parse(fetch("url2"))
}spawn ループ:データ並列ループ。
results = spawn for item in items {
process(item)
}付録:構文クイックリファレンス
A.1 制御フロー
if Expr Block (else if Expr Block)* (else Block)?
match Expr { MatchArm+ }
while Expr Block
for 'mut'? Identifier 'in' Expr BlockA.2 エラー処理
Expr '?' // エラー伝播(Result 型)A.3 match 構文
match value {
pattern1 => expr1,
pattern2 if guard => expr2,
_ => default_expr,
}