さて、ここまでの六式言語までは、コンパイル結果をC言語として出力して行ってきました。
しかし、C言語に限る必要はありません。JAVAでもGo言語でもアセンブラでももちろん構いません。
そこで、ここからはJavascriptに変換する言語について説明しましょう。
Javascriptは、Webブラウザ上で使われることの多い特別な言語です。 しかし、言語の構文としてはC言語とJavascriptはそんなに大きくは変わりません。
ここで作成する七式言語ではPL/0言語を、C言語とJavascriptの共通する部分はそのまま使い、異なる部分を変更することにより実現します。
例えば、次のようなC言語のプログラムを見てください。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int x, y;
x = 1;
y = 2;
printf("%d", x+y);
printf("\n");
}
これは、Javascriptに書き換えると一例として次のようになります。
var x, y;
x = 1;
y = 2;
document.write(x+y);
document.write("<br>");
#include や main関数とか不要なのですっきりとしていますが、プログラムの要素は変わっていません。
これをブラウザ上で実行しやすいように次のように前後にHTMLのタグをつけてみましょう。
<HTML>
<HEAD>
<TITLE>PL/0 to javascript</TITLE>
</HEAD>
<BODY>
<SCRIPT type="text/javascript">
<!--
var x, y;
x = 1;
y = 2;
document.write(x+y);
document.write("<br>");
// -->
</SCRIPT>
</BODY>
</HTML>
<!-- の次の行から // --> の前の行までがJavascriptの部分です。
これをa.htmlと名前をつけて保存してください。 このファイルをダブルクリックしたり、ブラウザで読み込んで実行してください。
3と表示されたでしょうか?
C言語を出力するPL/0言語で構文は変えずに、Javascriptを出力するように改造しましょう。
予想よりも簡単に対応できてしまいます。
改造による変更は大きく分けると、データ型の変更、文字列の出力関数の変更、およびHTMLタグの追加を行います。
データ型の変更は次のようになります。
まず、PL/0のconstで定義される型は次のように変更されます。
C言語 定数型定義 const int ↓ Javascript 定数型定義 var
Javascriptには、共通の規格としての定数の定義がないので、とりあえずvarで型定義するようにします。 本来ならば、代入文の左辺に現れないように意味解析時にチェックすれば定数として充分よいのですが、今回は特に対応しません。 (後の章で対応した新言語を紹介する予定です)
次にPL/0のvarで定義される整数データ型は次のように変更されます。
C言語 整数型定義 int ↓ Javascript 整数型定義 var
Javascriptだからvar型にすればどんな型でも使えるので、整数データ型として使っても大丈夫です。
次にPL/0の手続き定義の型は次のように変更されます。
C言語 手続き定義 void 手続き名() ↓ Javascript 手続き定義 function 手続き名()
これだけでデータ型の変更は終わりです。
次は、文字列の出力関数の変更です。
C言語
printf("%d", データ)
↓
Javascript
document.write(データ)
document.write()を使うとWeb上の画面に自由にデータ出力を表示することができます。
最後に、次のようにHTMLタグをJavascriptの出力の前後に付けるようにPL/0を改造します。
<HTML> <HEAD> <TITLE>PL/0 to javascript</TITLE> </HEAD> <BODY> <SCRIPT type="text/javascript"> <!-- Javascriptの出力 // --> </SCRIPT> </BODY> </HTML>
さて、これで準備OKです。次の項ではソースを示しましょう。
元のC言語出力のPL/0からの変更部分はソース上に注釈行で入れてみましょう。
// Compiler of PL/0 by descartes (translator)
<program>
<setVar Line 1>
// ここからhtml形式になるようにHTMLタグを出力させます。
<print '<HTML>'>
<print "<HEAD>">
<print "<TITLE>PL/0 to javascript</TITLE>">
<print "</HEAD>">
<print "<BODY>">
<print '<SCRIPT type="text/javascript">'>
<print "<!--">
// ここからは、PL/0ソースの解析とコンパイル結果の出力
<block> <emsg "'.' is missing.">
"."
// ここからはHTMLタグの後半を出力
<print "// -->">
<print "</SCRIPT>">
<print "</BODY>">
<print "</HTML>">
;
<block> [ "const" <emsg "constant name.">
<printf "var "> // const型はvarに変換
<ident> <emsg "constant definition.">
"=" <printf " = ">
<number>
{"," <printf ", ">
<ident> <emsg "constant definition.">
"=" <printf " = ">
<number>
} <emsg "';' is missing.">
";" <print ";">
]
[ "var" <emsg "variable name.">
<printf "var "> // var型はvarのまま
<ident> <emsg "variable definition.">
{"," <printf ", ">
<ident> <emsg "variable definition.">
} ";" <print ";">
]
{ "procedure" <emsg "procedure name.">
<printf "function "> // procedure手続き型はfunction型に変換
<ident> <emsg "procedure definition.">
<print "()">
";"
<print "{">
<block> ";" <print "}">
}
<statement>
;
<statement> <SKIPSPACE> ::sys <line #Line> <setVar Line #Line>
[
<ident>
(":=" | "=")
<emsg "expression.">
<printf " = ">
<expression> <print ";">
| "call" <emsg "procedure.">
<ident> <print "();">
| "begin" <print "{">
<statement> {";" <statement>}
"end" <print "}">
| "if" <emsg "if sentence.">
<printf "if (">
<condition>
"then" <print ") ">
<statement>
| "while" <emsg "while sentence.">
<printf "while (">
<condition>
"do" <print ")">
<statement>
|
"print" <emsg "print sentence. ">
[
// print出力はdocument.write()を出力して使う。
(
<ident #id> <print 'document.write(' #id ');'>
| <number #s #n> <print 'document.write(' #s #n ');'><print>
| <strings #str> <print 'document.write("' #str '");'><print>
)
{ ","
(
<ident #id2> <print 'document.write(' #id2 ');'>
| <number #s2 #n2> <print 'document.write(' #s2 #n2 ');'><print>
| <strings #str2> <print 'document.write("' #str2 '");'><print>
)
}
]
];
<condition> "odd" <emsg "odd syntax.">
<printf "((">
<expression> <printf ") & 1)">
|
<expression>
("=" <printf " == ">
|"#" <printf " != ">
|"<=" <printf " <= ">
|"<" <printf " < ">
|">=" <printf " >= ">
|">" <printf " > ">
)
<expression> ;
<expression> [ "+" <printf "+">
|"-" <printf "-">
] <term> {
("+" <printf "+">
|"-" <printf "-">
) <term>};
<term> <factor> {
("*" <printf "*">
|"/" <printf "/">
) <factor>};
<factor> <ident> | <number>
| "(" <printf "(">
<expression>
")" <printf ")">
;
<ident #id> <ID #id>
<reserved #id>
;
<ident> <ident #id>
<printf #id>
;
<number #sign #n>
["+" <is #sign "">
|
"-" <is #sign "-">
|
<is #sign "">
]
<NUM #n>
;
<number> <number #sign #n>
<printf #sign #n>
;
<strings #str> <STRINGS #str>
;
<strings> <strings #str>
<printf #str>
;
<reserved #id>
<not ::sys <member #id
(var procedure begin end if then while do call print odd)>>
;
<emsg #x>
<x <getVar #Line Line>
<warn "error : " #Line ":" #x>
<exit>>
;
<compile>
::sys<args #x>
::sys<nth #inputfile #x 1>
::sys<suffix #outputfile #inputfile html> // 出力ファイルの拡張子を.htmlにする
<print inputfile #inputfile>
<print outputfile #outputfile>
::sys<openw #outputfile
::sys<openr #inputfile <program>>>
;
? <compile>;