Stream language specification


[stream](https://github.com/matz/streem)の文法をBNFを拡張したEBNFで定義します。
（書きかけ)
字句解析は [lex.l](https://github.com/matz/streem/blob/master/src/lex.l) を、構文解析は  [parser.y](https://github.com/matz/streem/blob/master/src/parse.y) を参考にしています。

`symbol ::= expression` の形式で文法要素を表します。`( ... )` はグループを `(^ ... )` は否定、`|`は選択、`{ ... }` は0回以上の繰り返し、`{^ ... }` が0回以上の繰り返しの否定、`+` は1回以上の繰り返しを表します。



## 字句解析


```
TRAIL ::= {('\t' | ' ' | '\n') | '#' {^ '\n' } '\n' }

op_plus  ::= "+" { TRAIL }
op_minus ::= "-" { TRAIL }
op_mult  ::= "*" { TRAIL }
op_div   ::= "/" { TRAIL }
op_mod   ::= "%" { TRAIL }
op_eq    ::= "=="{ TRAIL }
op_neq   ::= "!="{ TRAIL }
op_lt    ::= "<" { TRAIL }
op_le    ::= "<="{ TRAIL }
op_gt    ::= ">" { TRAIL }
op_ge    ::= ">="{ TRAIL }
op_and   ::= "&&"{ TRAIL }
op_or    ::= "||"{ TRAIL }
op_bar   ::= "|" { TRAIL }
op_amper ::= "&" { TRAIL }
op_lasgn ::= "<-"{ TRAIL }
op_rasgn ::= "->"{ TRAIL }
'='      ::= "=" { TRAIL }
op_colon2::= "::"{ TRAIL }

keyword_if     ::= "if"     { TRAIL }
keyword_else   ::= { TRAIL } "else" { TRAIL }
keyword_break  ::= "break"  { TRAIL }
keyword_emit   ::= "emit"   { TRAIL }
keyword_return ::= "return" { TRAIL }
keyword_nil    ::= "nil"    { TRAIL }
keyword_true   ::= "true"   { TRAIL }
keyword_false  ::= "false"  { TRAIL }

identifier     ::= ('A' ... 'Z' | 'a' ... 'z' | '_') { ('A' ... 'Z' | 'a' ... 'z' | '0' ... '9' | '_' }

'.'            ::= { TRAIL } '.' { TRAIL }

'(' ::= '(' { TRAIL }
'[' ::= '[' { TRAIL }
'{' ::= '{' { TRAIL }
',' ::= ',' { TRAIL }
';' ::= ';' { TRAIL }
':' ::= ':' { TRAIL }
')' ::= ')' { TRAIL }
']' ::= ']' { TRAIL }
'}' ::= '}' { TRAIL }

'\n' ::= '\n' | '#' {^ '\n' } '\n'

lit_number ::= ('1' ... '9' {'0' ... '9'} | '0')[ '.' {'0' ... '9'} ]

lit_string ::= '"' { (^ '\"') | '\\' _ } '"'

white_space ::= ' ' | '\t' 
```

## 構文解析

### キーワード

```
if else do break emit return nil true false
```

### 演算子優先順位

| 優先順位 | 結合性 | 演算子 |
| --- | --- | --- |
| 1 | 左結合 | ２項演算子 '&' |
| 2 | 左結合 | ２項演算子 '\|' |
| 3 | 左結合 | ２項演算子 '\|\|' |
| 4 | 左結合 | ２項演算子 '&&' |
| 5 | なし   | ２項演算子 '==' '!=' |
| 6 | 左結合 | ２項演算子 '<' '<=' '>' '>=' |
| 7 | 左結合 | ２項演算子 '+' '-' |
| 8 | 左結合 | ２項演算子 '*' '/' '%' |
| 9 | 右結合 | 単項演算子 '+' '-' '!' '~' |


###文法

#### プログラム

```
program       ::= compstmt
compstmt      ::= stmts { ';' | '\n' }
stmts         ::= [ stmt { ( ';' | '\n' )+ stmt } ]
```

プログラム `program` は 合成文 `compstmt` です。
合成文 `compstmt` はコンポジットステートメント(合成文)の略です。
文の列 `stmts` は ';' または '\n' の列によって区切られた0個以上の 文 `stmt` の列です。

#### 文

```
stmt          ::= var '=' expr
                | keyword_emit [args]
                | keyword_return [args]
                | keyword_break
                | expr
```

`stmt` は変数の設定、 `emit` 文、 `return` 文、 `break` 文、式を記述出来ます。

```
var           ::= identifier
```

`var` は変数を表す識別子 (identifier) です。

#### 式

```
expr          ::= expr op_plus expr
                | expr op_minus expr
                | expr op_mult expr
                | expr op_div expr
                | expr op_mod expr
                | expr op_bar expr
                | expr op_amper expr
                | expr op_gt expr
                | expr op_ge expr
                | expr op_lt expr
                | expr op_le expr
                | expr op_eq expr
                | expr op_neq expr
                | op_plus expr                 %prec '!'
                | op_minus expr                %prec '!'
                | '!' expr
                | '~' expr
                | expr op_and expr
                | expr op_or expr
                | primary
```

式 `expr` は ２項演算子の `+` `-` `*` `/` `%` `|` `&` `>` `>=` `<` `<=` `==` `!=` `&&` `||` と 単項演算子の `+` `-` `!` `~` を用いる事が出来ます。

#### プライマリ式

```
primary       ::= primary0
                | block
                | identifier block
                | identifier '(' [args] ')' [block]
                | primary '.' identifier ['(' [args] ')'] [block]

block         ::= '{' [bparam] compstmt '}'
bparam        ::= [f_args] op_rasgn
f_args        ::= [f_args ','] identifier
```

プライマリ式はプライマリ0式以外に関数呼び出しやメンバへのアクセス、ブロックを渡す事が出来ます。

#### コンディション式

```
condition     ::= condition op_plus condition
                | condition op_minus condition
                | condition op_mult condition
                | condition op_div condition
                | condition op_mod condition
                | condition op_bar condition
                | condition op_amper condition
                | condition op_gt condition
                | condition op_ge condition
                | condition op_lt condition
                | condition op_le condition
                | condition op_eq condition
                | condition op_neq condition
                | op_plus condition            %prec '!'
                | op_minus condition           %prec '!'
                | '!' condition
                | '~' condition
                | condition op_and condition
                | condition op_or condition
                | cond

cond          ::= primary0
                | identifier '(' [args] ')'
                | cond '.' identifier [ '(' [args] ')' ]
```

`condition` は `if else` 式内の条件を表す式です。
２項演算子の `+` `-` `*` `/` `%` `|` `&` `>` `>=` `<` `<=` `==` `!=` `&&` `||` と 単項演算子の `+` `-` `!` `~` を用いる事が出来ます。

`cond` は `condition` 内の `primary` に対応する物ですがブロックを使う事が出来ません。

#### プライマリ0式 primary0

```
primary0      ::= lit_number
                | lit_string
                | identifier
                | '(' expr ')'
                | '[' [args] ']'
                | '[' map_args ']'
                | '[' ':' ']'
                | keyword_if condition '{' compstmt '}' opt_else
                | keyword_nil
                | keyword_true
                | keyword_false
```

プライマリ0式 (primary0) は数値リテラルや文字列リテラル、識別子、括弧 `(` `)` で括られた式、`[` `]` で括られた配列とマップ、 `if` 式、 `nil`、 `true`、 `false` を指定出来ます。

```
args          ::= [args ','] expr

map           ::= (lit_string | identifier) ':' expr
map_args      ::= [map_args ','] map
```

`args` は式をカンマ `,` で区切った式の連続です。
`map` はコロン `:` で区切った文字列か識別子と式のペアで、連想配列の１要素です。
`map_args` はカンマで区切った `map` 要素の連続です。
`[ ]` は空の配列、`[ : ]` は空の連想配列を表します。

```
elsif         ::= [elsif] keyword_else keyword_if condition '{' compstmt '}'
opt_else      ::= [elsif] [ keyword_else '{' compstmt '}' ]
```

`elseif` と `opt_else` で `if else` 式を表します。