# CoffeeScript コードリーディングガイドライン

## はじめに

このガイドラインは、CoffeeScriptコンパイラのコードベースを効率的に理解するための手引きです。
CoffeeScriptに精通していないエンジニアでも、段階的に学習できるよう構成されています。

**対象読者:**
- プロジェクトに新規参画するエンジニア
- 他言語からの経験者
- コードレビューを行う担当者

---

## 1. 言語基礎

> このセクションでは、CoffeeScriptの基本構文と概念を解説します。

### 1.1 プログラム構造

CoffeeScriptはJavaScriptにコンパイルされる言語で、Pythonのような簡潔な構文が特徴です。セミコロンやブレースの多くが省略可能で、インデントでブロックを表現します。

**例: src/coffeescript.coffee:1-13**
```coffeescript
# CoffeeScript can be used both on the server, as a command-line compiler based
# on Node.js/V8, or to run CoffeeScript directly in the browser. This module
# contains the main entry functions for tokenizing, parsing, and compiling
# source CoffeeScript into JavaScript.

{Lexer}       = require './lexer'
{parser}      = require './parser'
helpers       = require './helpers'
SourceMap     = require './sourcemap'
# Require `package.json`, which is two levels above this file, as this file is
# evaluated from `lib/coffeescript`.
packageJson   = require '../../package.json'
```

**ポイント:**
- `#`で始まる行はコメント
- `{Lexer} = require './lexer'`は分割代入（destructuring）
- インデントがブロック構造を定義

### 1.2 データ型と変数

CoffeeScriptでは変数宣言に`var`、`let`、`const`を使わず、代入時に自動的に宣言されます。

**例: src/lexer.coffee:38-54**
```coffeescript
tokenize: (code, opts = {}) ->
  @literate   = opts.literate  # Are we lexing literate CoffeeScript?
  @indent     = 0              # The current indentation level.
  @baseIndent = 0              # The overall minimum indentation level.
  @ends       = []             # The stack for pairing up tokens.
  @tokens     = []             # Stream of parsed tokens
```

**主なデータ型:**
- 数値: `0`, `3.14`, `0x1A`
- 文字列: `'single'`, `"double"`, `"""heredoc"""`
- 配列: `[1, 2, 3]`
- オブジェクト: `{key: value}`
- 真偽値: `true`/`yes`, `false`/`no`

**CoffeeScript固有のエイリアス（src/lexer.coffee:1241-1250）:**
```coffeescript
COFFEE_ALIAS_MAP =
  and  : '&&'
  or   : '||'
  is   : '=='
  isnt : '!='
  not  : '!'
  yes  : 'true'
  no   : 'false'
  on   : 'true'
  off  : 'false'
```

### 1.3 制御構造

CoffeeScriptでは条件分岐やループも簡潔に書けます。

**条件分岐の例: src/lexer.coffee:69-80**
```coffeescript
while @chunk = code[i..]
  consumed = \
       @identifierToken() or
       @commentToken()    or
       @whitespaceToken() or
       @lineToken()       or
       @stringToken()     or
       @numberToken()     or
       @jsxToken()        or
       @regexToken()      or
       @jsToken()         or
       @literalToken()
```

**制御構造の特徴:**
- `if`/`unless`/`else`/`then`
- `for ... in`（配列）/ `for ... of`（オブジェクト）
- `while`/`until`/`loop`
- 後置形式: `action() if condition`

### 1.4 関数/メソッド定義

関数は`->`または`=>`（バインドされた関数）で定義します。

**例: src/coffeescript.coffee:44-50**
```coffeescript
withPrettyErrors = (fn) ->
  (code, options = {}) ->
    try
      fn.call @, code, options
    catch err
      throw err if typeof code isnt 'string'
      throw helpers.updateSyntaxError err, code, options.filename
```

**関数の形式:**
- `->`: 通常の関数（thisは呼び出し時に決定）
- `=>`: バインドされた関数（thisは定義時に固定）
- デフォルトパラメータ: `(arg = defaultValue) ->`

### 1.5 モジュール/インポート

Node.jsのCommonJSモジュールシステムを使用します。

**例: src/nodes.coffee:8-15**
```coffeescript
{Scope} = require './scope'
{isUnassignable, JS_FORBIDDEN} = require './lexer'

# Import the helpers we plan to use.
{compact, flatten, extend, merge, del, starts, ends, some,
addDataToNode, attachCommentsToNode, locationDataToString,
throwSyntaxError, replaceUnicodeCodePointEscapes,
isFunction, isPlainObject, isNumber, parseNumber} = require './helpers'
```

**エクスポートの例: src/nodes.coffee:33**
```coffeescript
exports.CodeFragment = class CodeFragment
  constructor: (parent, code) ->
    @code = "#{code}"
```

---

## 2. プロジェクト固有の概念

> このセクションでは、CoffeeScriptコンパイラ特有の概念を解説します。

### 2.1 コンパイルパイプライン

CoffeeScriptのコンパイルは以下のパイプラインで処理されます：

```
ソースコード → Lexer → Rewriter → Parser → Nodes → JavaScript
```

**1. Lexer（字句解析器）**: ソースコードをトークンに分割
**2. Rewriter**: 暗黙の構文を明示的なトークンに変換
**3. Parser**: トークンをAST（抽象構文木）に変換
**4. Nodes**: ASTを走査してJavaScriptコードを生成

**メインエントリポイント: src/coffeescript.coffee:62-80**
```coffeescript
exports.compile = compile = withPrettyErrors (code, options = {}) ->
  options = Object.assign {}, options
  generateSourceMap = options.sourceMap or options.inlineMap or not options.filename?
  filename = options.filename or helpers.anonymousFileName()
  checkShebangLine filename, code
  map = new SourceMap if generateSourceMap
  tokens = lexer.tokenize code, options
  # Pass a list of referenced variables
  options.referencedVars = (
    token[1] for token in tokens when token[0] is 'IDENTIFIER'
  )
```

### 2.2 トークン形式

トークンは3要素の配列として表現されます：

```coffeescript
[tag, value, locationData]
```

**例: src/lexer.coffee:1-10**
```coffeescript
# The CoffeeScript Lexer. Uses a series of token-matching regexes to attempt
# matches against the beginning of the source code. When a match is found,
# a token is produced, we consume the match, and start again. Tokens are in the
# form:
#
#     [tag, value, locationData]
#
# where locationData is {first_line, first_column, last_line, last_column, ...}
```

### 2.3 ASTノードクラス

すべてのASTノードは`Base`クラスを継承します。

**例: src/nodes.coffee:59-62**
```coffeescript
exports.Base = class Base
  compile: (o, lvl) ->
    fragmentsToText @compileToFragments o, lvl
```

主要なノードクラス：
- `Block`: 文のブロック
- `Literal`: リテラル値
- `Value`: 値（識別子やプロパティアクセスを含む）
- `Assign`: 代入式
- `Op`: 演算子
- `Code`: 関数定義
- `Class`: クラス定義
- `If`/`For`/`While`: 制御構造

### 2.4 Literate CoffeeScript

マークダウンとコードを混在させた`.litcoffee`形式をサポートしています。

**例: src/scope.litcoffee:1-8**
```markdown
The **Scope** class regulates lexical scoping within CoffeeScript. As you
generate code, you create a tree of scopes in the same shape as the nested
function bodies. Each scope knows about the variables declared within it,
and has a reference to its parent enclosing scope.

    exports.Scope = class Scope
```

インデントされた行がコードとして扱われます。

---

## 3. 命名規則

> このセクションでは、プロジェクト全体で使用される命名規則を解説します。

### 3.1 ファイル・ディレクトリ命名

| パターン | 意味 | 例 |
|---------|------|-----|
| `*.coffee` | CoffeeScriptソースファイル | `lexer.coffee`, `nodes.coffee` |
| `*.litcoffee` | Literate CoffeeScript | `scope.litcoffee`, `sourcemap.litcoffee` |
| `*.js` | コンパイル済みJavaScript | `lib/coffeescript/*.js` |
| 小文字スネークケース | ソースファイル | `option_parser.coffee` |

### 3.2 クラス・関数・変数命名

| プレフィックス/サフィックス | 意味 | 例 |
|---------------------------|------|-----|
| `@` | インスタンス変数/this参照 | `@tokens`, `@indent` |
| `_` | プライベート的な変数 | `_module`, `_require` |
| `UPPER_CASE` | 定数 | `JS_KEYWORDS`, `COFFEE_KEYWORDS` |
| `PascalCase` | クラス名 | `Lexer`, `Rewriter`, `Base` |
| `camelCase` | 関数・メソッド | `tokenize`, `compileNode` |
| `exports.` | エクスポートされる要素 | `exports.Lexer`, `exports.compile` |

### 3.3 主要な定数定義（src/lexer.coffee:1226-1270）

| 定数名 | 説明 |
|--------|------|
| `JS_KEYWORDS` | JavaScriptのキーワード |
| `COFFEE_KEYWORDS` | CoffeeScript固有のキーワード |
| `RESERVED` | 予約語 |
| `CALLABLE` | 関数呼び出し可能なトークン |
| `INDEXABLE` | インデックスアクセス可能なトークン |

---

## 4. ディレクトリ構造

> このセクションでは、プロジェクトのディレクトリ構造を解説します。

```
coffeescript/
├── bin/                    # CLIエントリポイント
│   ├── coffee              # coffeeコマンド
│   └── cake                # cakeコマンド（タスクランナー）
├── src/                    # CoffeeScriptソースコード
│   ├── coffeescript.coffee # メインAPI
│   ├── lexer.coffee        # 字句解析器
│   ├── parser.js           # パーサー（Jisonで生成）
│   ├── grammar.coffee      # 文法定義
│   ├── rewriter.coffee     # トークンリライター
│   ├── nodes.coffee        # ASTノードクラス
│   ├── scope.litcoffee     # スコープ管理
│   ├── helpers.coffee      # ユーティリティ関数
│   ├── command.coffee      # CLIコマンド処理
│   ├── optparse.coffee     # オプションパーサー
│   ├── index.coffee        # Node.js API
│   ├── register.coffee     # require拡張
│   ├── repl.coffee         # REPL実装
│   ├── browser.coffee      # ブラウザ対応
│   └── sourcemap.litcoffee # ソースマップ生成
├── lib/                    # コンパイル済みJS（配布用）
│   └── coffeescript/       # メインライブラリ
├── test/                   # テストスイート
├── documentation/          # ドキュメントソース
├── docs/                   # 生成されたドキュメント
├── Cakefile                # ビルドタスク定義
└── package.json            # npm設定
```

### 各ディレクトリの役割

| ディレクトリ | 役割 | 主要ファイル |
|-------------|------|-------------|
| `src/` | コンパイラのソースコード | `coffeescript.coffee`, `lexer.coffee`, `nodes.coffee` |
| `lib/` | コンパイル済みの配布用JS | `coffeescript/index.js` |
| `bin/` | CLI実行ファイル | `coffee`, `cake` |
| `test/` | テストスイート | `*.coffee` |
| `documentation/` | ドキュメントソース | `site/`, `sections/` |

---

## 5. アーキテクチャ

> このセクションでは、プロジェクトのアーキテクチャパターンを解説します。

### 5.1 全体アーキテクチャ

CoffeeScriptコンパイラは**パイプラインアーキテクチャ**を採用しています。

```
┌─────────────────────────────────────────────────────────────────┐
│                        CoffeeScript Compiler                     │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌─────────┐   ┌──────────┐   ┌────────┐   ┌───────┐   ┌─────┐ │
│  │ Source  │──▶│  Lexer   │──▶│Rewriter│──▶│ Parser│──▶│Nodes│ │
│  │  Code   │   │(tokenize)│   │        │   │(parse)│   │(AST)│ │
│  └─────────┘   └──────────┘   └────────┘   └───────┘   └──┬──┘ │
│                                                            │    │
│                                                            ▼    │
│                                            ┌───────────────────┐│
│                                            │   JavaScript      ││
│                                            │   Output          ││
│                                            └───────────────────┘│
└─────────────────────────────────────────────────────────────────┘
```

### 5.2 レイヤー構成

| レイヤー | 責務 | 代表的なファイル |
|---------|------|-----------------|
| CLI | コマンドライン処理 | `command.coffee`, `optparse.coffee` |
| API | 公開API提供 | `coffeescript.coffee`, `index.coffee` |
| 字句解析 | トークン生成 | `lexer.coffee`, `rewriter.coffee` |
| 構文解析 | AST生成 | `grammar.coffee`, `parser.js` |
| コード生成 | JS出力 | `nodes.coffee`, `scope.litcoffee` |
| ユーティリティ | 共通機能 | `helpers.coffee`, `sourcemap.litcoffee` |

### 5.3 データフロー

1. **入力**: CoffeeScriptソースコード（文字列）
2. **字句解析**: `Lexer.tokenize()` → トークン配列
3. **トークン変換**: `Rewriter.rewrite()` → 暗黙構文の明示化
4. **構文解析**: `parser.parse()` → ASTノードツリー
5. **コード生成**: `nodes.compile()` → JavaScriptコード片（fragments）
6. **出力**: JavaScript文字列（+ ソースマップ）

---

## 6. 主要コンポーネント

> このセクションでは、主要なコンポーネントとその連携を解説します。

### 6.1 エントリーポイント

**CLIエントリーポイント: bin/coffee**
```javascript
var potentialPaths = [
  path.join(process.cwd(), 'node_modules/coffeescript/lib/coffeescript'),
  path.join(__dirname, '../lib/coffeescript')
];
// ...
require(potentialPaths[i] + '/command').run();
```

**Node.js API: src/index.coffee:24-31**
```coffeescript
CoffeeScript.compile = (code, options) ->
  if options?.transpile
    options.transpile.transpile = CoffeeScript.transpile
  universalCompile.call CoffeeScript, code, options
```

### 6.2 Lexer（字句解析）

字句解析器は正規表現を使ってソースコードをトークンに分割します。

**主要メソッド: src/lexer.coffee:37-92**
```coffeescript
tokenize: (code, opts = {}) ->
  # 初期化
  @tokens = []
  i = 0
  while @chunk = code[i..]
    consumed = \
         @identifierToken() or
         @commentToken()    or
         @whitespaceToken() or
         # ...
    i += consumed
  @closeIndentation()
  return @tokens if opts.rewrite is off
  (new Rewriter).rewrite @tokens
```

### 6.3 Parser（構文解析）

Jisonパーサージェネレータを使用してパーサーを生成します。

**文法定義例: src/grammar.coffee:100-114**
```coffeescript
grammar =
  Root: [
    o '',                    -> new Root new Block
    o 'Body',                -> new Root $1
  ]
  Body: [
    o 'Line',                -> Block.wrap [$1]
    o 'Body TERMINATOR Line', -> $1.push $3
  ]
```

### 6.4 Nodes（コード生成）

各ASTノードクラスは`compileNode`メソッドでJavaScriptコード片を生成します。

**例: src/nodes.coffee:98-109**
```coffeescript
compileToFragments: (o, lvl) ->
  o        = extend {}, o
  o.level  = lvl if lvl
  node     = @unfoldSoak(o) or this
  node.tab = o.indent
  fragments = if o.level is LEVEL_TOP or not node.isStatement(o)
    node.compileNode o
  else
    node.compileClosure o
  @compileCommentFragments o, node, fragments
  fragments
```

### 6.5 ユーティリティ/共通機能

**src/helpers.coffee**の主要関数：

| 関数 | 説明 |
|------|------|
| `starts(string, literal)` | 文字列の先頭をチェック |
| `ends(string, literal)` | 文字列の末尾をチェック |
| `compact(array)` | falsyな値を除去 |
| `flatten(array)` | 配列を平坦化 |
| `merge(options, overrides)` | オブジェクトをマージ |
| `throwSyntaxError(message, location)` | 構文エラーを投げる |

---

## 7. よく使われるパターン

> このセクションでは、コード内で頻出するパターンを解説します。

### パターン一覧

| パターン | 説明 | 出現頻度 | 代表的なファイル |
|---------|------|---------|-----------------|
| ビジターパターン | ASTノード走査 | 高 | `nodes.coffee` |
| ファクトリーパターン | トークン生成 | 高 | `lexer.coffee` |
| チェーンメソッド | 連続処理 | 中 | `rewriter.coffee` |
| テンプレートメソッド | 継承での拡張 | 高 | `nodes.coffee` |

### 各パターンの詳細

#### パターン1: ビジターパターン（ASTトラバーサル）

**目的:** ASTツリーを再帰的に走査して処理を適用する

**実装例:**
```coffeescript
# ファイル: src/nodes.coffee:253-259
contains: (pred) ->
  node = undefined
  @traverseChildren no, (n) ->
    if pred n
      node = n
      return no
  node
```

**解説:** `traverseChildren`で子ノードを再帰的に走査し、条件に一致するノードを検索します。

#### パターン2: トークンファクトリー

**目的:** 統一された形式でトークンを生成する

**実装例:**
```coffeescript
# ファイル: src/lexer.coffee:1107-1112
makeToken: (tag, value, {offset: offsetInChunk = 0, length = value.length, origin, generated} = {}) ->
  token = [tag, value, @makeLocationData {offsetInChunk, length}]
  token.origin = origin if origin
  token.generated = yes if generated
  token
```

**解説:** トークンの生成を一箇所に集約し、位置情報の付与を統一的に行います。

#### パターン3: 暗黙構文の変換（Rewriter）

**目的:** CoffeeScriptの省略記法を明示的なトークンに変換する

**実装例:**
```coffeescript
# ファイル: src/rewriter.coffee:43-64
rewrite: (@tokens) ->
  @removeLeadingNewlines()
  @closeOpenCalls()
  @closeOpenIndexes()
  @normalizeLines()
  @tagPostfixConditionals()
  @addImplicitBracesAndParens()
  # ...
  @tokens
```

**解説:** 複数のパスでトークンストリームを変換し、パーサーが処理しやすい形式にします。

---

## 8. 業務フロー追跡の実践例

> このセクションでは、実際の処理フローをコードで追跡する方法を解説します。

### 8.1 フロー追跡の基本手順

1. エントリーポイントを特定
2. 処理の流れを追跡（呼び出し関係を追う）
3. データの変換を確認
4. 最終的な出力を確認

### 8.2 フロー追跡の実例

#### 例1: 単純なコードのコンパイル

**概要:** `square = (x) -> x * x` をJavaScriptにコンパイルする流れ

**処理フロー:**
```
compile() → lexer.tokenize() → rewriter.rewrite() → parser.parse() → nodes.compile()
```

**詳細な追跡:**

1. **APIエントリ** (`src/coffeescript.coffee:62-73`)
   ```coffeescript
   exports.compile = compile = withPrettyErrors (code, options = {}) ->
     options = Object.assign {}, options
     tokens = lexer.tokenize code, options
   ```

2. **字句解析** (`src/lexer.coffee:37-92`)
   ```coffeescript
   tokenize: (code, opts = {}) ->
     @tokens = []
     while @chunk = code[i..]
       consumed = @identifierToken() or @literalToken() or ...
   ```

   生成されるトークン（簡略化）:
   ```
   ['IDENTIFIER', 'square'], ['=', '='], ['(', '('],
   ['IDENTIFIER', 'x'], [')', ')'], ['->', '->'],
   ['IDENTIFIER', 'x'], ['*', '*'], ['IDENTIFIER', 'x']
   ```

3. **トークン変換** (`src/rewriter.coffee:43-64`)
   ```coffeescript
   rewrite: (@tokens) ->
     @addImplicitBracesAndParens()  # 暗黙の括弧を追加
   ```

4. **構文解析** (`src/coffeescript.coffee:88`)
   ```coffeescript
   nodes = parser.parse tokens
   ```

   生成されるAST（簡略化）:
   ```
   Assign
   ├── variable: Identifier('square')
   └── value: Code
       ├── params: [Param('x')]
       └── body: Op('*', Identifier('x'), Identifier('x'))
   ```

5. **コード生成** (`src/coffeescript.coffee:109-133`)
   ```coffeescript
   fragments = nodes.compileToFragments options
   js = (fragment.code for fragment in fragments).join('')
   ```

   出力:
   ```javascript
   var square;
   square = function(x) {
     return x * x;
   };
   ```

### 8.3 フロー追跡チェックリスト

- [ ] エントリーポイントを特定したか
- [ ] 呼び出し関係を把握したか
- [ ] データの変換ポイントを確認したか
- [ ] エラーハンドリングを確認したか
- [ ] 最終的な出力を確認したか

---

## 9. 設計書の参照順序

> このセクションでは、プロジェクト理解のための設計書参照順序を案内します。

### 9.1 目的別ロードマップ

#### 全体像を把握したい場合
1. `README.md` - プロジェクト概要
2. `src/coffeescript.coffee` - メインAPIと処理フロー
3. 本ガイドラインのアーキテクチャセクション

#### 字句解析を理解したい場合
1. `src/lexer.coffee` - トークン生成ロジック
2. `src/rewriter.coffee` - トークン変換ロジック
3. `test/lexer.coffee` - テストケースで動作確認

#### 構文解析を理解したい場合
1. `src/grammar.coffee` - 文法定義
2. `lib/coffeescript/parser.js` - 生成されたパーサー
3. `src/nodes.coffee` - ASTノードクラス

#### コード生成を理解したい場合
1. `src/nodes.coffee` - `compileNode`メソッド群
2. `src/scope.litcoffee` - 変数スコープ管理
3. `src/sourcemap.litcoffee` - ソースマップ生成

#### 改修作業を行う場合
1. 対象機能の関連ファイル特定
2. `test/`配下の対応テスト確認
3. `Cakefile`でビルド・テスト方法確認

### 9.2 ドキュメント一覧

| ドキュメント | 概要 | 参照タイミング |
|-------------|------|---------------|
| `README.md` | プロジェクト概要・インストール方法 | 初回参加時 |
| `CONTRIBUTING.md` | コントリビュートガイド | PR作成前 |
| `docs/v2/annotated-source/` | アノテーション付きソース | 詳細理解時 |
| `documentation/` | 公式ドキュメントソース | 言語仕様確認時 |

---

## 10. トラブルシューティング

> このセクションでは、コードリーディング時によくある問題と解決法を解説します。

### よくある疑問と回答

#### Q: `@`プレフィックスは何を意味しますか？
A: `this`の省略形です。`@tokens`は`this.tokens`と同等です。

#### Q: `?`演算子（存在演算子）の動作は？
A: `a?.b`は`a`が`null`/`undefined`でなければ`a.b`を返します。安全なプロパティアクセスに使用します。

#### Q: `#{}`は何ですか？
A: 文字列補間です。`"Hello #{name}"`はJavaScriptの`` `Hello ${name}` ``に相当します。

#### Q: `...`（スプラット）の使い方は？
A: 可変長引数や配列展開に使用します。`(args...) ->`や`[first, rest...]`

#### Q: ビルド方法は？
A: `cake build`でソースをコンパイル、`cake test`でテスト実行、`cake build:full`でフルビルド＋テストです。

### デバッグのヒント

1. **トークンストリームの確認**:
   ```bash
   coffee --tokens your_code.coffee
   ```

2. **ASTの確認**:
   ```bash
   coffee --nodes your_code.coffee
   ```

3. **コンパイル結果の確認**:
   ```bash
   coffee --print your_code.coffee
   ```

4. **デバッグモードの有効化**:
   ```bash
   DEBUG_TOKEN_STREAM=true coffee --compile file.coffee
   ```

---

## 付録

### A. 用語集

| 用語 | 説明 |
|-----|------|
| AST | Abstract Syntax Tree - 抽象構文木 |
| Token | ソースコードの最小単位（識別子、演算子など） |
| Lexer | 字句解析器 - ソースをトークンに分割 |
| Parser | 構文解析器 - トークンをASTに変換 |
| Fragment | 生成されるJSコードの断片 |
| SourceMap | ソースとコンパイル結果の対応情報 |
| Jison | JavaScriptパーサージェネレータ |
| Literate | マークダウンとコードを混在させた形式 |

### B. 主要ファイル一覧

| ファイル/ディレクトリ | 説明 | 主な内容 |
|---------------------|------|---------|
| `src/coffeescript.coffee` | メインAPI | compile, tokens, nodes関数 |
| `src/lexer.coffee` | 字句解析器 | Lexerクラス、トークン定義 |
| `src/rewriter.coffee` | トークン変換 | Rewriterクラス、暗黙構文処理 |
| `src/grammar.coffee` | 文法定義 | Jison文法規則 |
| `src/nodes.coffee` | ASTノード | 全ノードクラス、コード生成 |
| `src/scope.litcoffee` | スコープ管理 | Scopeクラス、変数管理 |
| `src/helpers.coffee` | ユーティリティ | 共通関数群 |
| `src/command.coffee` | CLI処理 | コマンドラインオプション処理 |
| `src/index.coffee` | Node.js API | Node.js固有の機能 |
| `Cakefile` | ビルド定義 | ビルドタスク、テスト実行 |

### C. 参考資料

- [CoffeeScript公式サイト](https://coffeescript.org/)
- [CoffeeScript GitHub](https://github.com/jashkenas/coffeescript)
- [Jison Parser Generator](https://github.com/zaach/jison)
- [Babel](https://babeljs.io/) - トランスパイラ連携
- [ECMAScript仕様](https://tc39.es/ecma262/)
