Excel VBAをJavaScriptに翻訳 その４

# はじめに

[**前回**](https://qiita.com/pooshikin/items/bb32b661ced44e452008)は、VBAの関数をJavaScriptで実現する関数を作成しました。
今回は、VBAのソースを翻訳するにあたり最初の第一歩「**字句解析(Lexical Analysis)**」をやってみます。
**npm**から**Chiffon**パッケージをインストールして字句解析の簡単なプログラムを作成します。
翻訳の工程としては、以下のように想定しています。

**1. 字句解析 [Lexical Analysis]**
**2. 構文解析 [Syntactic Analysis]**
**3. 最適化 [Optimization]**
**4. コード生成 [Code Generation]**

# 前提
* OS : Windows7以上
* PoweShellのターミナルで実行
* VSCodeでコード編集
* node.js環境構築済み

# 字句解析とは

**ソースコードを読み込んで、トークン（字句）に分解する工程**

# Chiffon
[Chiffon:https://www.npmjs.com/package/chiffon](https://www.npmjs.com/package/chiffon)
字句解析するコンパクトなパーサーライブラリです。
ローカルにインストールします。

``` shell
npm install --save chiffon
```

## 字句解析タイプ
字句解析の**type:**として返却されるタイプ

|タイプ|説明|
|:--|:--|
|Comment|コメント|
|WhiteSpace|空白|
|LineTerminator|改行|
|Template|テンプレート|
|String|文字|
|Punctuator|句読点・疑問符・括弧|
|RegularExpression|正規表現|
|Numeric|数値|
|Identifier|識別子|
|Null|ヌル|
|Boolean|真偽値|
|Keyword|検索キー|
# tomparse.js
ソースの字句解析（パース）を行うJavaScriptです。

```JavaScript
var Chiffon = require('Chiffon');
/**
 * < Defined token type >
 *
 * Comment           - コメント
 * WhiteSpace        - 空白
 * LineTerminator    - 改行
 * Template          - テンプレート
 * String            - 文字
 * Punctuator        - 句読点・疑問符・括弧
 * RegularExpression - 正規表現
 * Numeric           - 数値
 * Identifier        - 識別子
 * Null              - ヌル
 * Boolean           - 真偽値
 * Keyword           - 検索キー
 *
 * <Tokenize Options>
 * 
 * comment : {boolean} default=false
 * Keep comment tokens.
 * 
 * whiteSpace : {boolean} default=false
 * Keep white space tokens.
 *
 * lineTerminator : {boolean} default=false
 * Keep line terminator tokens.
 *
 * range : {boolean} default=false
 * Include an index-based location range. (array)
 *
 * loc : {boolean} default=false
 * Include line number and column-based location info.
 * 
 */

var options = {
    comment: false,         // コメント
    whiteSpace: false,      // 空白
    lineTerminator: false   // 改行
};

function Parse(s) {
    return Chiffon.tokenize(s, options);
}
function UnParse(s) {
    return Chiffon.untokenize(s, options);
}

module.exports = { 
    Parse: Parse, 
    UnParse: UnParse
}; 
/*
// Test Demo
var demo = Parse('Debug.Print("Hello, World")');
console.log(demo);
*/
```
二つの関数を定義しています。
**Parse** : 引数（文字列）から字句解析を行い結果を返却します。
**UnParse** : 引数（文字列（字句解析結果））から元の文字列を復元し返却します。

# tomtest2.js
ソースを配列で定義、１行ずつ字句解析してコンソールに出力します。

```JavaScript
var f = require('./tomparse.js');

// VBA
var src = [
    'Debug.Print("Hello, World")',
    'MsgBox("Hello, World")',
    'Debug.Print(Date)'
];

// src Parse Output
for (i =0 ; i < src.length ; i++) {
    var Data = f.Parse(src[i]);
    console.log(Data);
}
```
# 実行

```shell
node tomtest2.js
```
Json形式で字句解析結果が返却されます。
結果には、**type:**と**value:**それぞれにパース結果がセットされています。

```shell
PS C:\**\tom> node tomtest2.js
[ { type: 'Identifier', value: 'Debug' },
  { type: 'Punctuator', value: '.' },
  { type: 'Identifier', value: 'Print' },
  { type: 'Punctuator', value: '(' },
  { type: 'String', value: '"Hello, World"' },
  { type: 'Punctuator', value: ')' } ]
[ { type: 'Identifier', value: 'MsgBox' },
  { type: 'Punctuator', value: '(' },
  { type: 'String', value: '"Hello, World"' },
  { type: 'Punctuator', value: ')' } ]
[ { type: 'Identifier', value: 'Debug' },
  { type: 'Punctuator', value: '.' },
  { type: 'Identifier', value: 'Print' },
  { type: 'Punctuator', value: '(' },
  { type: 'Identifier', value: 'Date' },
  { type: 'Punctuator', value: ')' } ]
S C:\**\tom>
```

# まとめ

パーサーパッケージを利用して簡単な字句解析のJavaScriptを作成しました。
字句解析結果から**type**が**Identifier**の部分を取り出すことで、次の工程の「構文解析」へ進むことができます。
次回は「構文解析」するためにVBAの予約語などを定義します。