修正日:2013年02月21日(作成日:2013年02月17日)


SynapseScript 言語マニュアル

はじめに

 本稿は、メトリクスのグラフ構造を表現するためのデータ記述言語「SynapseScript」に関するマニュアルである。 仕様や具体例の提示によって、SynapseScript利用時の補助を行うことが目的である。

図1 メトリクスグラフの例
図1 メトリクスグラフの例

 対象を何かしらの指標に基づいて計測する「メトリクス」は、図1のようなグラフ構造で表現することができる。 グラフのノードは、多入力多出力の関数に相当する「メトリクスプラグイン」として実現し、グラフのアークは、ノード同士の繋ぎ役として「SynapseScript」を提案するのである。

 ちなみに「SynapseScript」という名称は、メトリクスグラフが神経細胞の接続構造(ニューラルネットワーク)に似ていたことを由来としたものであり、 その構造の要となる「接続」の仕組み・構造を意味する「シナプス」という言葉を採用したのだ。

定義

 ここでは、本ガイドラインに記載されている用語の定義を行う。

記法

概要 ─ 具体例を添えて

 具体的なメトリクスグラフの例を挙げ、その構造を表すSynapseScriptの記述(スクリプト)を紹介しよう。

図2 サンプルのメトリクスグラフ
図2 サンプルのメトリクスグラフ
/*** Assignments ***/
sourceFile  = File("/path/to/Programs/program.py", "read");
language    = Value("Python");
codeMetrics = Metrics("/path/to/Plugins/CodeMetrics");
division    = Metrics("/path/to/Plugins/Division");
resultFile  = File("/path/to/Results/ResultFile.txt", "write");
transcript  = Transcript();

/*** Synapses ***/
sourceFile
    to: codeMetrics.code
    send: value1   to: division.dividend
    send: quotient to: resultFile;
language
    to: codeMetrics.lang
    send: value2    to: division.divisor
    send: remainder to: transcript;

 スクリプトは「代入文」と「シナプス文」の2種類で構成される。それぞれを以下に詳説する。

代入文

/*** Assignments ***/
sourceFile  = File("/path/to/Programs/program.py", "read");
language    = Value("Python");
codeMetrics = Metrics("/path/to/Plugins/CodeMetrics");
division    = Metrics("/path/to/Plugins/Division");
resultFile  = File("/path/to/Results/ResultFile.txt", "write");
transcript  = Transcript();

 代入文は、グラフのノードたちを定義するものである。等号「=」を挟み、右辺はノードのコンストラクタ、左辺は対応付ける変数を記述する。 ここで命名した変数名は、後述のシナプス文でグラフ構造を表現する際に用いることになる。

 単一の代入文は、次のように記述される。また、利用できるコンストラクタ名の例も示そう。

変数名 = コンストラクタ名 ( 引数群 );
コンストラクタ名役割
Valueデータのノードを生成
Fileファイルのノードを生成
Metricsメトリクスプラグインのノードを生成
Transcriptトランスクリプトのノードを生成

 以上、4種類のコンストラクタを示したが、処理系によっては「Transcript」を用意できない場合もあろう。つまり、これらは処理系に依存することになる。 また、この4種類以外のコンストラクタを用意することもあり得る。

シナプス文

/*** Synapses ***/
sourceFile
    to: codeMetrics.code
    send: value1   to: division.dividend
    send: quotient to: resultFile;
language
    to: codeMetrics.lang
    send: value2    to: division.divisor
    send: remainder to: transcript;

 シナプス文は、代入文で定義したノードたちの繋ぎ方を明記するものである。 「あるノードの出力」と「あるノードの入力」を繋げるために、to:文(またはsend:to:文)を記述することになる。

補遺

字句解析向けの正規表現

 字句解析器生成系の一「flex」向けに拵えた正規表現を掲載する。PDF形式の正規表現(rexp.lex.pdf)も用意している。

%{
#include "defs.h"
%}
%option nounput
%%
"send:"                         { return(SEND); }
"to:"                           { return(TO); }
[_a-zA-Z][_a-zA-Z0-9]*          { return(ID); }
"="                             { return(GETS); }
";"                             { return(SEMICOLON); }
"\."                            { return(PERIOD); }
"("                             { return(LPAR); }
")"                             { return(RPAR); }
","                             { return(COMMA); }
\"([^\"]|\"\")*\"               { return(STRING); }
"\r\n"|"\r"|"\n"|" "|"\t"       { }
"/*"([^*]|"*"+[^*/])*"*"+"/"    { return(COMMENT); }
.                               { return(UNKNOWN); }
%%
int yywrap(void) {
  return(1);
}

構文解析向けのBNF

 構文解析器生成系の一「Yacc」向けに拵えたBNF(バッカス・ナウア記法)を掲載する。 PDF形式のBNF(BNF.pdf)抽象構文木の生成を行う意味解析付きのBNF(syns.yac.pdf)も用意している。

%{
#include "defs.h"
#define YYSTYPE char *
char s[1024];
%}
%token  SEND TO GETS SEMICOLON PERIOD LPAR RPAR COMMA ID STRING COMMENT UNKNOWN
%%
Program
    : Statements                             { }
Statements
    :                                        { }
    | Statement                              { }
    | Statements Statement                   { }
Statement
    : Assignment SEMICOLON                   { }
    | Synapse SEMICOLON                      { }
    | Comment                                { }
Assignment
    : VariableName GETS Constructor          { }
Synapse
    : Variable Mappings                      { }
Mappings
    : Mapping                                { }
    | Mappings Mapping                       { }
Mapping
    : TO Variable                            { }
    | SEND MemberName TO Variable            { }
Variable
    : VariableName                           { }
    | VariableName PERIOD MemberName         { }
VariableName
    : ID                                     { }
MemberName
    : ID                                     { }
Constructor
    : ConstructorName LPAR RPAR              { }
    | ConstructorName LPAR Arguments RPAR    { }
ConstructorName
    : ID                                     { }
Arguments
    : Argument                               { }
    | Arguments COMMA Argument               { }
Argument
    : STRING                                 { }
Comment
    : COMMENT                                { }
%%
#include "lex.yy.c"
void yyerror(char *s) {
    fprintf(stderr, "\n%s at %d: nearby \"%s\"\n\n", s, linecounter, yytext);
    exit(EXIT_FAILURE);
}