top

文法の解説
スクリプトを構成する字面の説明。
概要
紹介 ――― スクリプトの紹介
サンプル ――― 簡素なソースコードの例
字句
注釈 ――― 「 ; 」 以降は注釈(コメント)である
予約語 ――― if-else, loop, while, for, break, continue, return, sub, struct, null
識別子 ――― 変数名, 関数名, 構造体名, 構造体メンバ名, モジュール名
定数 ――― 数値, 文字列
演算子 ――― =, +, -, *, /, %, !, &, |, ==, !=, <, >, <=, >=
区切り子 ――― ()[]{}"'.,;
構文
モジュール ――― 1つのファイルのこと
大域 ――― 関数, 構造体, ブロック, などの外側
ブロック ――― 「 { 」 と 「 } 」の間
変数定義 ――― 新たに変数を定義する
if-else ――― 条件分岐
loop ――― 繰り返し - loop
while ――― 繰り返し - while
for ――― 繰り返し - for
break ――― 繰り返しの最後まで飛ぶ(繰り返しの中断)
continue ――― 繰り返しの先頭まで飛ぶ
return ――― 終了
sub ――― 関数の定義
struct ――― 構造体の定義
null ――― データの破棄
式文
代入 ――― 「 = 」 で代入
演算 ――― 演算規則
条件式 ――― if-else, while, for などで使う条件式


概要
スクリプトの雰囲気。
紹介
スクリプトのソースコードはテキストファイルである。
テキストファイルの始めの行から終わりの行に向かって文法規則に従って順に実行される。
プログラムの構造として、関数を使うことができ、ファイルごとのモジュール化がある。
実行順の制御として if-else による条件分岐と loop, while, for による繰り返しがある。
データの表現として、整数、文字列、配列、構造体、(その他に拡張データ)がある。
変数には型がなく、データに型がある。
データを格納するメモリ領域は自動で回収される。
(現状では設計のバグで特定の状況でメモリを回収できない。参照 構文-null)
サンプル
次は 1 から 10 まで足すと幾つになるか計算。
sum = 0

for (i = 1; i <= 10; i = i + 1)
	sum = sum + i

print("answer - ", sum, "\n")
次は階乗の計算。
print("4 * 3 * 2 * 1 - ", factorial(4), "\n")

sub factorial(n)
{
	if (1 >= n)
		return 1

	return n * factorial(n-1)
}


字句
ソースを構成する文字列。
注釈
「 ; 」 以降その1行は注釈(コメント)である。
ただし、for ( ; ; ) で使われる 「 ; 」 は注釈とは扱われない。
例えば、注釈は次のように使われる。
; サンプルコード - ここはコメント
; 画面に 「 hello, world 」 と出力
print("hello, world\n")
予約語
予約語はソースコード中で変数名や関数名などに使用できない。
予約語は大文字と小文字が区別されない。例えば break と BREAK は等しく扱われる。
現在は以下の11個である。
break continue else for if loop null return sub struct while
現在は他に以下が予約語と同じようにソースコード中で新たに使うことができない。
基本変数
arg stdin stdout
基本関数
load int str time clock rand srand open close seek tell print input gets puts getc putc read write string length index substr trim upcase downcase chop chomp annex join regex match replace scan split array push pop unshift shift splice reverse list cons car cdr concat hash regist lookup delete
識別子
識別子は _ か a-z で始まり _ か a-z0-9 のみで構成される単語である。
識別子は大文字と小文字が区別されない。例えば ident Ident IDENT 何れも等しく扱われる。
識別子が使用されるのは変数名、関数名、構造体名、構造体メンバ名、モジュール名である。
例えば識別子は以下のように使用される。
; 構造体名 - point
struct point {
	; 構造体メンバ名 - x, y
	x
	y
}

main()

; 関数名 - main
sub main()
{
	; 変数名 - a
	a = point(0, 0);

	print("(", a.x, ",", a.y, ")", "\n");
}
定数
定数には数値定数と文字列定数がある。
数値定数は10進整数と16進整数がある。
10進整数は 0-9 のみから構成される単語である。
12 12345 1020
16進整数は 0x で始まり, 0-9a-fA-F のみから構成される単語である。
0x11 0x15af 0xff33 0xFF33
文字列定数は 「'」 または 「"」 で囲まれた文字列である。
「'」 で囲まれた文字列定数は特殊文字が展開されない。
'hello\n' ; hello\n - '((abc).+\2)' ; ((abc).+\2)
「"」 で囲まれた文字列定数は特殊文字が展開される。
"hello\n" ; hello(改行) - "((abc).+\2)" ; ((abc).+2)
「"」 で展開される特殊文字は以下である。
\n         改行
\r         復帰
\t         タブ
\\         \
\"         "
\'         '
\xhh       文字コードの16進表記
\X         X ( その他、X は任意文字 )
演算子
演算子は式文で使用される。
代入以外の算術演算子は数値に使用される。
論理演算子は条件式で 数値、文字列、null との比較に使用される。
算術演算子
=        代入、等号(条件式のとき)
+        加算、単項プラス
-        減算、単項マイナス
*        乗算
/        除算
%        余算
論理演算子
!        論理NOT
&        論理AND
|        論理OR
==       等号
!=       不等号
<        小なり
>        大なり
<=       以下
>=       以上
演算子の優先順位は以下である。
[] ( ) . 配列インデックス、式の括弧括り、構造体メンバ指定
+ -      単項プラス、単項マイナス
* / %    乗算、除算、余算
+ -      加算、減算
=        代入
== !=    比較演算
< > <= >=
!        論理NOT
& |      論理AND, 論理OR
区切り子
単語の区切りに以下の文字が使われる。
( ) [ ] { } " ' . , ;
用途は式中の括弧、関数の引数リスト、配列インデックス、ブロック、文字列定数、 構造体メンバ指定、引数区切り、for 文の式区切りなどである。


構文
構文規則。プログラムの構成要素。
モジュール
プログラムを構成する1つのファイルのことをモジュールと呼ぶことにする。
あるファイルに書かれた関数は他のファイルからも、そのモジュールを読み込むことで呼び出すことができる。
モジュールを読み込む際は、モジュールの大域が実行された後に関数を呼び出すことができるようになる。
; モジュール a の読み込み
load("a")


; リスト node の作成
node = a.append(null, "aaa")
node = a.append(node, "bbb")
node = a.append(node, "ccc")

; リスト node の内容を順に表示
while (null != node) {
	print(node.name, "\n")
	node = node.next
}
モジュール a のソースコード。ファイル名は 「 a 」 とする。
; モジュール名 a のソースコード

; 構造体 node
struct node {
	next
	name
}

; 関数 append
sub append (head, name)
{
	a = node(null, name)

	if (null == head)
		return a

	tmp = head
	while (null != tmp.next)
		tmp = tmp.next

	tmp.next = a

	return head
}
大域
大域は、関数、構造体、ブロック、などの外側である。
プログラムは大域の始めから順に実行される。
関数、構造体の定義は大域にのみ配置できる。
break、continue は大域には配置できない。
; ココは大域
print("here is global\n")

{
	; ココは局所ブロック
	print("here is local block\n")
}

; ココは大域
func()

struct hoge {
	; ココは構造体
	message
}

sub func()
{
	; ココは関数
	a = hoge("hello, world.")

	print(a.message, "\n")
}
ブロック
ブロックは 「 { 」 と 「 } 」 で囲まれた部分である。
構造体定義、関数定義、局所ブロック、if、else、loop、while、for のブロックに使われる。
構造体定義では構造体メンバを定義するのに使用される。
それ以外では複数の文をまとめて実行単位を定義するのに使用される。
これら実効単位のブロック内で定義された変数は、定義されたブロック内でのみ有効である。
局所ブロックでは break, continue による繰り返し操作が loop, while, for によらず可能である。
; 局所ブロックによる繰り返しとブロックによる変数の有効範囲

i = 0
{
	; ココは局所ブロック
	if (10 == i)
		break

	; a はこの局所ブロック内でのみ有効
	a = i
	print(a, "\n")

	; i はこのブロックより外側で定義されているので
	; a と扱いが違うことに注意
	i = i + 1
	continue
}

; a は有効でないのでエラーになる
print(a, "\n")

; i は有効なのでエラーにならない
print(i, "\n")
変数定義
変数が定義されるのは、その変数に始めて代入されたときである。
以下はエラーになる。
; a は定義されていない
print(a, "\n")

; ココで a が定義される
a = "hello"
以下はエラーにならない。
; ココで a が定義される
a = "hello"

; a は定義されている
print(a, "\n")
すでに定義されている変数を上書きすることはできない。
内側のブロックで代入があったとしてもすでに定義されている変数に代入されるだけだ。
; ココで a が定義される
a = 100

{
	; すでに定義されている a に代入されるだけ
	a = 10
}

; 10 が表示される
print(a, "\n")
if-else
条件分岐で、以下のような形式である。
if ( 条件式 ) 実行単位
if ( 条件式 ) 実行単位 else 実行単位
実行単位は1文またはブロックである。
else の次に if ... と続けることができる。
; if-else 文の例
a = "hello"
b = 2

; if ( ... ) ブロック
if ("hello" == a) {
	print("true\n")
}

; if ( ... ) 1文
if (null != a)
	print("true\n")

; if ( ... ) ブロック else ブロック
if (0 == b) {
	print("true\n")
} else {
	print("false\n")
}

; else if ...
if (0 == b) {
	print("b is 0\n")
} else if (1 == b) {
	print("b is 1\n")
} else if (2 == b) {
	print("b is 2\n")
} else {
	print("b is other\n")
}
loop
繰り返しで、以下のような形式である。
loop ブロック
ブロックの内容を意図的に停止されるまで永遠と繰り返し実行する。
繰り返しの停止には break 文を使用する。
; loop 文の例
i = 0
loop {
	if (10 == i)
		break

	print(i, "\n")

	i = i + 1
}
while
繰り返しで、以下のような形式である。
while ( 条件式 ) 実行単位
条件式が真である間、実行単位の内容を繰り返し実行する。
実行単位は1文またはブロックである。
; while 文の例
i = 0
while (i < 10) {
	print(i, "\n")
	i = i + 1
}
for
繰り返しで、以下のような形式である。
for ( 式1 ; 条件式 ; 式2 ) 実行単位
条件式が真である間、実行単位の内容を繰り返し実行する。
実行単位は1文またはブロックである。
式1は最初に1度だけ実行される。
次に条件式が評価され、偽なら実行位置は for 文の次に移動する。
条件式が真なら実行単位が実行され、次に式2が実行される。
その後、条件式の評価に戻って繰り返される。
; for 文の例
for (i = 0; i < 10; i = i + 1) {
	print(i, "\n")
}
break
繰り返しの最後まで飛ぶ。(繰り返しの中断)
局所ブロック、loop、while、for のブロック、また if 文と組み合わせて使用される。
; break 文の例
loop {
	buf = input()
	chomp(buf)

	if ("" == buf | null == buf)
		break

	print(buf, "\n");
}
continue
繰り返しの先頭まで飛ぶ
局所ブロック、loop、while、for のブロック、また if 文と組み合わせて使用される。
; continue 文の例
sum = 0
loop {
	buf = input()
	chomp(buf)

	if ("" == buf | null == buf)
		break

	if (0 == match('\d+', buf))
		continue

	print(buf, "\n")
}
return
関数の内側で使われた時は関数の呼び出し元に戻る。
関数の外側で使われた時はプログラムの実行を終了する。
形式は以下のようで return より return 式文 が優先される。
return 式文
return
return 文を使用すると関数の呼び出し元に戻るときに値を持たすことができる。
; return 文の例
a = add(10, 5)
print(a, "\n")

sub add(a, b)
{
	return a + b
}
sub
関数を定義する。
形式は以下のようである。
sub 関数名 ( 仮引数リスト ) 関数ブロック
関数は再帰的に呼び出すことができる。
; sub 文の例 - 最大公約数を探す

print("Greatest common divisor - ", gcd(35,42), "\n");

sub abs(n)
{
	if (0 > n)
		return -n
	return n
}

sub gcd(m, n)
{
	if (0 == n)
		return abs(m)
	else
		return gcd(n, m % n)
}
struct
構造体を定義する。
形式は以下のようである。
struct 構造体名 { 構造体メンバリスト }
構造体は定義した位置以降の行でしか使用することはできない。
以下はエラーになる。
; 構造体を使う
a = point(10,10)
print("(", a.x, ",", a.y, ")", "\n")

; 構造体の定義
struct point {
	x
	y
}
以下はエラーにはならない。
; 構造体の定義
struct point {
	x
	y
}

; 構造体を使う
a = point(10,10)
print("(", a.x, ",", a.y, ")", "\n")
null
変数に代入することでデータへの参照を破棄する。
データを格納するメモリは参照カウントで管理されている。
例えば、以下のように書く。
a = null
メモリ管理は参照カウントで行っているが、現在これに不備がある。
以下のように自身を参照するようなところがあるとメモリが回収されない。
a = array(1)
a[0] = a
a = null


式文
代入から加減乗除余まで。
代入
代入によって変数に新たに値を結び付けることができる。
変数は最初に代入されたときに定義される。
例えば、以下のようである。
a = 100
a = "hello"
a = array(10)
a = null
演算
演算は、加減乗除余があり、数値にのみ適要される。(現状は文字列では連結のみでき + を使う)
演算子には優先順位があり、また括弧によって演算順序を変えることができる。
例えば、以下のようである。
a = 100 + 2 * 3
a = 2 * (10 - 6) + a * 6 / 3
a = 2 + (2 * a - 10 / 5) * 6 / 3 - 2
条件式
条件式は if、while、for で使われる。
数値-数値, 文字列-文字列, また null との比較が可能である。
配列は条件式で数値として扱われ配列のサイズとなる。
例えば以下、1 + 2 == a - 4 が条件式である。
a = 7

if (1 + 2 == a - 4)
	print("true\n")
else
	print("false\n")
配列を条件式で使うと以下のようになる。
a = array(2)

if (2 > a)
	print("true\n")
else
	print("false\n")
条件式を書くところに単に演算を書くことはできない。
以下はエラーである。
a = 2

if ( a - 1 )
	print("ture\n")
else
	print("false\n")

2002/03/22 by Gaku
gaku_geo@geocities.co.jp