Lex 0.1
囲碁の棋譜フォーマット SGF の構文解析処理 (parsing / syntactic analysis) を作る前段階として、字句解析 (lexical analysis) のクラス Lex を作成し、Jasmine という単体テストのフレームワークを使ってテストしてみました。
ドキュメント
JsDoc Toolkit で作成したドキュメントはこちら。
ソース
lextest01.html
このソースコードは Jasmine のサンプル SpecRunner.html から大部分を持ってきました。前半はスタイルシートとスクリプトを読み込んでいる部分です。
<head>
<meta charset="UTF-8">
<title>JavaScriptでプログラミング - Lex 0.1</title>
<link type="text/css" rel="stylesheet" href="lib/jasmine-1.3.1/jasmine.css">
<link type="text/css" rel="stylesheet" href="css/spec.css">
<link type="text/css" rel="stylesheet" href="css/shCoreEclipse.css">
<link type="text/css" rel="stylesheet" href="css/shThemeEclipse.css">
<script type="text/javascript" src="js/XRegExp.js"></script>
<script type="text/javascript" src="js/shCore.js"></script>
<script type="text/javascript" src="js/shBrushJScript.js"></script>
<script type="text/javascript" src="js/shBrushXml.js"></script>
<script type="text/javascript" src="js/shBrushCss.js"></script>
<script type="text/javascript" src="lib/jasmine-1.3.1/jasmine.js"></script>
<script type="text/javascript" src="lib/jasmine-1.3.1/jasmine-html.js"></script>
<!-- include source files here... -->
<script type="text/javascript" src="js/lex01/lex01.js"></script>
<!-- include spec files here... -->
<script type="text/javascript" src="js/lex01/lexspec01.js"></script>
後半は Jasmine によるテスト結果を HTML 上で展開するレポーターと呼ばれる部分です。
<script type="text/javascript">
SyntaxHighlighter.all();
(function() {
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
var htmlReporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter(htmlReporter);
jasmineEnv.specFilter = function(spec) {
return htmlReporter.specFilter(spec);
};
var currentWindowOnload = window.onload;
window.onload = function() {
if (currentWindowOnload) {
currentWindowOnload();
}
execJasmine();
};
function execJasmine() {
jasmineEnv.execute();
}
})();
</script>
lex01.js
クラス Lex のソースコードです。字句解析のためのツールです。
リンク先をご覧下さい。
lexspec01.js
このソースでは Lex のテスト仕様を定義しています。Jasmine のサンプル PlayerSpec.js を参考に作成しました。
describe("Lex 仕様 0.1", function() {
var exp = "1+2=";
var la;
var retval;
beforeEach(function() {
la = new Lex(exp); // Lexical Analiser
});
it("eod() は false を返す", function() {
expect(la.eod()).toBeFalsy();
});
it("digit() は '1' を返す", function() {
expect(la.digit()).toEqual('1');
});
it("upper() は null を返す", function() {
expect(la.upper()).toBeNull();
});
it("lower() は null を返す", function() {
expect(la.lower()).toBeNull();
});
it("ch('1') は '1' を返す", function() {
expect(la.ch('1')).toEqual('1');
});
describe("3文字読んだ時点で、", function() {
beforeEach(function() {
la.rewind();
la.digit();
la.ch('+');
la.digit();
});
it("eod() は false を返す", function() {
expect(la.eod()).toBe(false);
});
it("digit() は null を返す", function() {
expect(la.digit()).toBe(null);
});
it("upper() は null を返す", function() {
expect(la.upper()).toBe(null);
});
it("lower() は null を返す", function() {
expect(la.lower()).toEqual(null);
});
it("ch('=') は '=' を返す", function() {
expect(la.ch('=')).toBe('=');
});
});
describe("4文字読んだ時点で、", function() {
beforeEach(function() {
la.rewind();
la.digit();
la.ch('+');
la.digit();
la.ch('=');
});
it("eod() は true を返す", function() {
expect(la.eod()).toBeTruthy();
});
});
});
テスト結果