Kuinの拡張バッカス・ナウア記法 (非公式)

Last Modified: 2020/02/10 23:46:18.
Only available in Japanese text.
Kuin関連情報の個人的まとめに戻る


概要

目次

このページで用いられている記法について
BNF
その他
定義文 ブロック文 単文
func構文 (関数)
var構文 (変数)
const構文 (定数)
alias構文 (型の別名)
class構文 (クラス)
enum構文 (列挙体)
if文
switch文
while文
for文
try文
block文
do文
break文
skip文
ret文
assert文
throw文
文字列リテラル
文字リテラル
Booleanリテラル
数値リテラル
識別子
演算子
関数呼び出し

値指定
コメント

[付録: Kuinの予約語リスト]


このページで用いられている記法について

Extensible Markup Language (XML) 1.0 (Fifth Edition)に準ずる表記法です。
BNFを拡張した表記法ですが、EBNF や ABNFではありません。
上記リンク先の記法と異なる点が4つあります。

  1. 終端記号をクオテーション で括る代わりに 赤色太字 で表記。
    例:"int"ではなく、int
  2. 終端記号としての空白類文字を明記していない。
    以下のルールで記述しています。
    • 定義中にスペースがない箇所 → スペース挿入不可。
    • 定義中にスペースがある箇所で、前後ともに[0-9A-Za-z_] → スペース必須。
    • その他 → スペースの存在は任意。
    • 文( Sentence )の終わりには改行文字\n(LF)が必要。
    • その他改行文字が必要な箇所ではBNFの定義中でも改行されている。逆に行の途中では改行不可能。
  3. 定義の終了を で示している。
    セミコロン( ; )で示す流儀もありますが、 の方が誤認識しにくいと考えました。
  4. 1行コメントを採用。
    例:// コメント

BNF

KuinSource ::= ( +? Definition )*  // 定義文の集まり
// Kuinのソースファイルの拡張子は.knです。
// Kuinのソースファイルは UTF-8 で書いてください。
// + ⇒ 他のファイルで参照可能な宣言。
	

Sentence  ::= Definition     |  // 定義文
              BlockSentence  |  // ブロック文
              SimpleSentence  // 単文
	

定義文

Definition ::= Func | Var | Const | Alias | Class | Enum 
	

func構文 (関数定義)

Func ::= func ([ DllName ])? FName ( (VName : &? Type( , VName : &? Type )*)? )( : Type)?
             Sentence*
         end func 
// & を付けなければ値渡し、& を付けると参照渡しになります。
//   参照渡しの際は、 関数定義の仮引数 と 関数呼び出しの実引数 の両方に & を付けます。
//   例:func f(x : &int) に対し、do f(&i) 
	

var構文 (変数定義)

Var ::= var VName : Type( :: Expr)? 
// 代入( :: Expr)を省略した場合、すべて0で初期化されます。  
// グローバル変数・メンバ変数では、定義時には値を代入できません。
//   定義と同時に値を代入できるのは、ローカル変数のみです。
	

const構文 (定数定義)

Const ::= const VName : Type :: ConstExpr 
	

alias構文 (型の別名定義)

Alias ::= alias Type : Type // alias 新しい型名: 既存の型名
	

class構文 (クラス定義)

Class ::= class CName ( ClassName? )
              ( +? *? Definition )*
          end class 
// 継承元( ClassName )を省略した場合、Kuin@CClass が継承されます。
//   全てのクラスは、ルートクラスである Kuin@CClass が継承されていると言えます。
//   例: class CCat : CAnimalとした場合、Kuin@CClass → CAnimal → CCat
// 多重継承はできません。
// 
// + ⇒ パブリックなメンバ。(※varとfuncのみに可能。)
// * ⇒ 親クラスのメンバのオーバーライドを許可。(funcのみに可能)

//   * は、+ の後に記述しなければエラーとなります。  
//   (誰が書いても同じようなコードにするため)
// オーバーライドできるのはメソッドのみです。
// 
// コンストラクタは、*func ctor()
// デストラクタは、*func dtor() 
// 
// { インスタンスを作って初期化(Init)する方法 } [出典: @yuhi_as]
//     { クラスのinitメソッドの宣言 } 
//     class MyClass()
//         var メンバ変数: ~
//         +func init(仮引数): MyClass
//             do me.メンバ変数 :: ~
//             ret me
//         end func
//     end class
//     { 呼び方 }
//     var c : MyClass :: (#MyClass).init(実引数) 
	

enum構文 (列挙体定義)

Enum ::= enum EName
             ( ConstName( :: ConstExpr)? )*
         end enum 
// :: Exprを指定しなかったときのデフォルト値は 0 から始まります。
// 値は自動的に 1 ずつ足されて設定されます。
// 下記の例では、red は 0、green は 1、yellow は 6に設定されます。
// enum Color
//     red
//     green
//     blue :: 5
//     yellow
// end enum
// 他の要素と値が重複した場合は、コンパイルエラーとなります。
	

ブロック文

BlockStatement ::= If | Switch | While | For | Try | Block 
// ブロック内で定義したローカル変数は、そのブロック内でのみ参照できます。
	

if文

If ::= if BlockName? ( Expr )
           Sentence*
       ( elif ( Expr )
           Sentence* )*
       ( else
           Sentence* )?
       end if 
// 条件式 (()の中身)は、bool型でなければなりません。
	

switch文

Switch ::= switch BlockName? ( Expr )
           ( case Value
               Sentence* )*
           ( default
               Sentence* )?
           end switch 
// case の最後に達した段階で自動でブロックを抜けます (フォールスルーできません)。
// Value は、カンマ区切りで複数指定できます。また、to により、範囲指定もできます。
// 上記のExprの型とValueの定義中のExprの型は一致しなければなりません。
// Exprに指定できる型: int、ビット型(bit16など)、char、enum、[]char
// Value は、コンパイル時に定数とならなくても構いません。
// 複数の case条件に合致する場合、その中の最初のcaseに捕捉されます。
	

while文

While ::= while BlockName? ( ( Expr( , skip )? )? )
              Sentence*
          end while 
// 条件式を省略すると無限ループになります。
// 条件式は bool型でなくてはなりません。
// skipを指定した場合、初回の条件比較をスキップします (C言語のdo-whileの代替)。
	

for文

For ::= for BlockName? ( Expr , Expr( , ConstExpr)? )
            Sentence*
        end for 
// BlockNameがループカウンタ変数の役割をします。(int型)
// 括弧内(()内)は順に、初期値、終値、増減値です(全てint型)。
// 
// 増減値が正の数ならば i <= 終値 がループ続行の条件となります。
// 増減値が負の数ならば i >= 終値 がループ続行の条件となります。
// 増減値が0の場合はコンパイルエラーになります。
// 増減値を省略した場合、増減値は1になります。
	

try文

Try ::= try BlockName?
            Sentence*
        ( catch Value?
            Sentence* )+
        ( finally
            Sentence* )?
        end try 
// 上記のValueで例外コード(int型)を指定します(複数指定可能)。
// Valueを省略すると、1000以上のすべての例外コードが捕捉されます。
// catchで指定する例外コードは、コンパイル時に定数とならなくてはなりません。
// 例外の情報は、ブロック名(ここではeとします)を用いて、e.Code、e.Msg のように参照できます。
//   eはKuin@CExcptクラスに属しており、例外が発生したソースコード上の箇所がこの変数に格納されています。
//   e.Code は例外コード(int型)、e.Msg はメッセージ([]char型)です。
// tryやcatch中でbreakした場合、finallyを通ります。
//   finally内で そのtry文をbreakすると、無限ループになってしまうので注意してください。
	

block文

Block ::= block BlockName?
              Sentence*
          end block 
// 単純に、ブロック構造を作りたいときに有効です。
	

単文

SimpleSentence ::= Do | Break | Skip | Return | Assert | Throw 
	

do文

Do ::= do Variable OpSubstitution Expr | // 代入
       do Variable OpSwap Variable | // 値の交換
       do FunctionCall  // 関数呼び出し
// 代入文では、両辺が参照型の場合、値ではなくアドレスが代入されます。
// do文は副作用のある演算子で終わる必要があります。 [出典: Kuinのコンパイルエラー一覧(非公式) #E0054]
// do true ?(f(&a), f(&b))はコンパイルエラーになります。(do の直後が代入でも関数呼び出しでもなく条件演算)
//   上記のような場合はifを使うべきです。
	

break文

Break ::= break BlockName 
// BlockNameで指定したブロックを抜けます。
// 全てのブロック文でbreak可能です。
	

skip文

Skip ::= skip BlockName 
// BlockNameで指定したブロックの終端(end)直前にジャンプします。
// skip可能なブロックは、while、forです。
	

ret文

Return ::= ret Expr? 
// 戻り値が無い関数では、値を省略して ret のみを記述します。
	

assert文

Assert ::= assert Expr 
// 上記のExprはbool型でなければなりません。
//   例: assert a >= 2
//   このとき、デバッグ実行時に a が 2以上でなければ、例外が投げられます。
//   a が 2以上であることが保証されるべき場面での、テストに用いられます。
// リリース時にはコンパイルから外されますので、最終的な動作速度に影響しません。
	

throw文

Throw ::= throw Expr( , Expr)? 
// 1つ目のExprは例外コード( int型 )
// 2つ目のExprは例外メッセージ( []char型 )
// 例外メッセージを省略した場合、例外メッセージに null が入ります。
	

式・変数

Expr ::= ( Expr ) |
         String | Char | Boolean | Number |    // リテラル
         Variable | ConstantName | // 変数・定数
         BlockName |                   // (Forなどの)ブロック名
              Op1 Expr |               // 単項演算
         Expr Op2 Expr |               // 二項演算
              OpType1 Type |           // インスタンスの作成(#)
         Expr OpType2 Type |           // キャスト演算($)
         Expr OpClass2 ClassName |     // クラスチェック(=:、<>:)
         Expr ?( Expr , Expr ) |       // 条件演算
         FunctionCall                // 関数呼び出し
// 条件演算の ? と ( の間にスペースを入れてはいけません。
// true ?(A, B)の場合はAのみ、false ?(A, B)の場合はBのみが評価されます。

ConstExpr ::= Expr 
// コンパイル時に定数となる式を、ここではConstExprと表記しています。

Variable ::= VariableName |
			 Variable [ Expr ]  // 配列アクセス
// デバッグ実行時に配列の範囲外をアクセスすると、例外が投げられます。
//   例えば、s[5]まで定義されている配列があるとして、 s[-1] や s[6] は例外発生です。
//   これにより、バグによるメモリ破壊を未然に防止できます。
	

文字列リテラル

String ::= " ( [^"] | \" )* " |
           null 
	

文字リテラル

Char  ::= ' ( [^'\] | EscapedCh ) ' 

EscapedCh ::= \\ | // 「\」
              \" | // 「"」
              \' | // 「'」
              \0 | // 文字コード0の文字
              \n | // 改行文字
              \t | // タブ文字
              \u???? | // 指定した文字コードの文字。 「????」には数字または大文字アルファベットで4桁の16進数を指定
              \{式} | // 式の結果を文字列化したもの。 例えば、int型変数nに3が格納されているとき、
                      //「"\{n+5}"」と記述すると「"8"」と解釈される。 「(式).toStr()」と等しい
	

Booleanリテラル

Boolean ::= true | false 
	

数値リテラル

Number ::= [+-]?NonNegativeNumber |
           inf
// inf は float型 のリテラルです。
NonNegativeNumber ::= Base10 | Base16   // 10進数, 16進数
Base10 ::=   [0-9]+(.[0-9]+(e[+-][0-9]+)?)? 
Base16 ::= 0x[0-9A-F]+ 
	

ビット型リテラル

数値の後ろに、b8, b16, b32, b64 を付けるとビット型のリテラルになります。

その他

識別子

Name ::= [A-Za-z_][0-9A-Za-z_]* 
SourceName ::= Name  // ソースコード名
BlockName  ::= Name  // ブロック名
ClassName  ::= Name  // 定義時のクラス名
ConstName  ::= Name  // 定義時の定数名
AName      ::= Name  // 定義時の別名
FName      ::= Name  // 定義時の関数名
VName      ::= Name  // 定義時の変数名
EName      ::= Name  // 定義時の列挙体名
FunctionName ::= (SourceName?@)?(ClassName.)*FName  // アクセス時の関数名
VariableName ::= (SourceName?@)?(ClassName.)*VName  // アクセス時の変数名
EnumName     ::= (SourceName?@)?((ClassName.)*ClassName#)?EName  // アクセス時の列挙体名
ConstantName ::= (SourceName?@)?((ClassName.)*ClassName#)?ConstName |
                 EnumName#ConstName 
// 別のファイルで定義された識別子のアクセス時には「SourceName@」が必要です。
// 同じファイルで定義されたグローバル変数のアクセス時には「@」のみが必要です。
// enumの要素にアクセスする記法の例: Test@C#E#Hoge 
//   (ソースTest 内のクラスC 内の列挙体E 内の要素Hogeにアクセス)
//   ドットではなく#を使用する理由は、Kuinでは、静的なものは静的に処理したいので、
//   字句解析の段階で名前を決定しているためです。
	

演算子

// 代入演算子が = ではなく、::なのが特徴的です。
// C言語の ==, !=, &&, || は、Kuinではそれぞれ、=, <>, &, | に対応します。
// &, | はC言語の&&, ||と同様に短絡評価される論理演算子です。
// インクリメント演算子はありません。i :+ 1 で代用してください。

Op1 ::= + | - | ! | ^  // 単項演算子 (符号, 論理否定, 要素数演算子)
Op2 ::= + | - | * | / |   // 二項演算子 (加減乗除)
        % | ^ |           // 剰余、累乗
        < | > | <= | >= | // 比較
        = | <> |          // 等価、不等価
        =& | <>& |        // 参照の等価、参照の不等価 (nullと比較するときはこれ)
        & | | |           // 論理積、論理和
        ~               // 配列連結
OpType1 ::= # | // インスタンスの作成
            #[ ... ] | // 配列のインスタンス生成。 例: #[5]int
            [ ... ] | // 動的配列のインスタンス生成。 例: var a: []int :: [1, 2, 3]int
                                                          {※Kuin 1.01では[1, 2, 3]intではなく[1, 2, 3]と書く。}
            ##  // 参照型変数のディープコピー
OpType2 ::= $  // キャスト演算子
OpClass2 ::= =$ | <>$  // 型比較演算子
                            Kuin 1.00のReadme.pdfで「要素比較演算子」(is, nisに相当)と書かれてる =#と同じものだとすると、
                            例えば、 a =$ c で変数aのクラスがcの場合に真となります。}
OpSubstitution ::= :: | // 代入演算子
                   :+ | :- | :* | :/ | :% | :^ | :~  // 複合代入演算子
OpSwap ::= :$  // swap演算子 (a :$ bで、変数a と 変数b の値が入れ替わります。)
// 代入演算やswap演算の戻り値はvoidです。
OpFunctionCall ::= ( ... )  // 関数呼び出し
OpArrayAccess ::= [ ... ]  // 配列の要素アクセス
OpMemberAccess ::= .  // メンバアクセス
OpCondition ::= ?( ... , ... )  // 条件演算
	

関数呼び出し

FunctionCall ::= Function ( (&? Expr( , &? Expr)*)? ) |
                 Expr . FunctionCall  // (2).toStr()などのメソッド呼び出し
// 数値型のメソッドを利用する際、例えば5.toStr() ではなく、
//   (5).toStr() または 5 .toStr() とする必要があります。

Function ::= FunctionName |
             Variable | ConstantName // 関数型で定義された変数・定数
	

Type ::= int | float | char | bool | // 符号付整数型・浮動小数点型・文字型・論理型
         bit8 | bit16 | bit32 | bit64 | // ビット型
         list  < Type > | // リスト構造
         stack < Type > | // スタック構造
         queue < Type > | // キュー構造
         dict  < Type , Type > | // 辞書型 (Kuin 1.01以降で使えます)
         func  < ( (&? Type( , &? Type)*)? ) (: Type)? > | // 関数型
         EnumName | ClassName | // 列挙体・クラス
         [ ] Type  // 動的配列
// complex/money/ratio型 はしばらく仕様から外れることになりました。[詳細: @b2]
// Kuinでは型が厳密に扱われます。暗黙の型変換はできません。
// 配列は、var array:[]int :: @new [5]int のように宣言でき、
//   array :~ @new [2]int のように要素数を増やせます。
//   ※2016/03/20追記 : Kuin 1.01では @newの代わりに#を使うのが正しい?(ちゃんと確認していません。うろ覚え。)
	

値指定

Value ::= Expr( to Expr)?( , Value)* 
// switch文・try文で用いる値の指定方法です。
// Exprの型はそれぞれの文で制限されています。
	

コメント

Comment ::= { ( [^"'{}]+ | String | Char | Comment )* } |
            ; .* 
// Kuinでは、コメントがネストできます。
// また、コメント内部に文字列リテラル、文字リテラルを含み得ます。
// 例えば、{ " }" {  } }は全体がコメント扱いされます。
// 行頭以降のタブ文字と半角空白以外に登場する文字が「;」である行は一行コメントになります。
	

このページの誤りについて

誤表記等を発見された場合、@tatt61880にご連絡頂けると幸いです。


#Kuin Kuinの拡張バッカス・ナウア記法 (非公式) http://t.co/kw06gJLQ 完成しました! 非公式ですが、Kuinの文法のまとめとしてもご利用頂けると思います。

— たっと (@tatt61880) 2012年8月18日

Kuin関連情報の個人的まとめに戻る
This page has been described by Tatt (tatt61880) ---- Twitter: @tatt61880

ツイート