DEC社 TOPS-20を使う方法 SNOBOL言語使用編

SNOBOL

SNOBOL

TOPS-20 で使うSNOBOL言語

2018年4月、歴史的に貴重なDEC社 TOPS-20を使用しています。Panda TOPS-20 distribution にSNOBOL言語処理系がインストールされていました。

SNOBOL言語は、1977年に私が大学生のときにDEC社 SYSTEM-20 (TOPS-20)で出会ったすばらしい言語です。4回生のとき、特別研究でシステムプログラムを専攻してBASIC風のインタプリターをSNOBOL言語で作成しました。SNOBOL言語の日本語の解説書などありませんでしたから、図書館からSNOBOL言語を解説した英語の文献を借りてきて勉強しました。

特研 システムプログラム論

特研 システムプログラム論

KLH10エミュレーターをインストールしてDEC社 TOPS-20を使う目的のひとつが、懐かしいSNOBOL言語にもう一度触れることでした。

SNOBOLとは

SNOBOLは、1960年代に米国AT&Tベル研究所で開発した「文字列指向の記号言語」
(SNOBOL : StriNg Oriented symBOlic Language)です。

構造化プログラミングが提唱される前の言語なので、分岐指定による GoTo文によるプログラム制御構造しかありません。しかし、パターンマッチングに優れていることや連想配列が使えます。

1977年当時、FOTRAN/COBOL/ALGOL/アセンブラー言語などを使っていました。SNOBOL言語でパターンマッチが簡単に行えることや配列の添え字に文字列を使う連想配列は、カルチャーショックでした。後にAWKスクリプト言語を勉強したときは、SNOBOL言語の知識が役に立ち簡単に修得できました。

SNOBOLプログラムの起動方法

TOPS-20 SNOBOL

TOPS-20 SNOBOL

SNOBOLを起動するとプロンプト(SITBOL>)が表示されます。「/EXIT」と入力すると、SNOBOLを終了します。

@SNOBOL
SITBOL>/EXIT
EXIT

SNOBOLプログラムの起動方法はいくつかの方法があります。


【起動方法1】SNOBOLプロンプト(SITBOL>)で TTY: を指定して直接入力

@SNOBOL
SITBOL>TTY:
         OUTPUT = "Hello, World!"
END
Hello, World!
SITBOL>/exit
EXIT

【起動方法2】SNOBOLプロンプト(SITBOL>)でファイル名を指定

@TYPE PROGRAM1.SNO
         OUTPUT = "Hello, World!"
END

@SNOBOL
SITBOL>PROGRAM1.SNO
Hello, World!
SITBOL>/EXIT
EXIT

【起動方法3】SNOBOLコマンドラインでファイル名を指定

@TYPE PROGRAM1.SNO
         OUTPUT = "Hello, World!"
END

@SNOBOL PROGRAM1.SNO
HELLO, WORLD!
EXIT
@

SNOBOL 簡単なプログラム

SNOBOL言語の簡単なサンプルコードを示します。

@type program2.sno
* Sample Program
LOOP     OUTPUT = "Your name? "
         NAME = INPUT                                  :F(DONE)
         OUTPUT = "      Hello " NAME                  :(LOOP)
DONE
         OUTPUT = "Finished"
END
SAYURI
HANAKO

SNOBOL言語の書式は、次のようになります。

ラベル △  式  △ :(分岐先ラベル)

ただし、△は一つ以上のスペースです。

1カラム目 ラベル
2カラム目以降 代入文
パターンマッチ
パターン置換
コロンの後ろ 分岐先ラベル S(成功時) F(失敗時)
:(label)
:S(label)
:F(label)
:S(label1) F(label2)

1カラム目が「*」の行は、コメント行です。
ENDラベルは、SNOBOLプログラムの終わりを示します。

SNOBOLの構文では、スペースは重要です。代入文の “=”の両側にスペースが必要です。また、”+” や “-” などの算術演算子の周りにはスペースが必要です。(例、I = I + 1)

標準入出力はINPUT/OUTPUTという変数に代入処理を行うことで実行されます。
INPUTは、ENDラベルの次の行から入力します。EOFになるとINPUTは失敗し :F(ラベル)に分岐します。

それでは、実行してみます。

@SNOBOL PROGRAM2.SNO
Your name?
      Hello SAYURI
Your name?
      Hello HANAKO
Your name?
Finished
EXIT
@

INPUT()関数でファイル入力

SNOBOLは、INPUT()関数とOUTPUT()関数を使用して詳細な入出力制御ができます。

INPUT( ‘name’, ‘device/file’, ‘format option’)
OUTPUT(‘name’, ‘device/file’, ‘format option’)

データをファイルから入力します。

@TYPE PROGRAM3.SNO
* Example of INPUT()
         INPUT('DEV_INPUT', 'DSK:DATA.TXT')
LOOP     OUTPUT = "Your name? "
         NAME   = DEV_INPUT                           :F(DONE)
         OUTPUT = "      Hello " NAME                 :(LOOP)
DONE
         OUTPUT = "Finished"
END

INPUT()関数で、変数 ‘DEV_INPUT’にファイル’DSK:DATA.TXT’を割り付けます。

@TYPE DATA.TXT
SAYURI
HANAKO

実行します。

@SNOBOL PROGRAM3.SNO
Your name?
      Hello SAYURI
Your name?
      Hello HANAKO
Your name?
Finished
EXIT
@

DATA.TXTファイルから入力できました。

INPUT()関数 / OUTPUT()関数でTTY:入出力

コンソール出力とキーボード入力を行います。

@TYPE PROGRAM4.SNO
* Example of INPUT() and OUTPUT() parameters.
* The 'T' format option will prevent a line-feed from
         OUTPUT('Screen' , 'TTY:' ,'T')
         OUTPUT('Console', 'TTY:' )
         INPUT('Keyboard', 'TTY:')
LOOP     Screen = "Your name? "
         NAME    = Keyboard                            :F(DONE)
         Console = "      Hello " NAME                 :(LOOP)
DONE
         Console = "Finished"
END

標準入出力を TTY: に割り付けます。

  • Screenは、デバイス TTY: 出力です。’T’オプション(ターミナルモード)で、 出力に改行文字は追加されません。
  • Consoleは、デバイス TTY: 出力です。
  • Keyboardは、デバイス TTY: 入力です。

実行してみます。

@SNOBOL PROGRAM4.SNO
Your name? Sayuri
      Hello Sayuri
Your name? Hanako
      Hello Hanako
Your name? ^ZFinished
EXIT
@

Screenで、「Your name?」と改行なしで表示します。
Keyboardで、キーボード入力となります。CTRL+Zを入力するとEOFとなります。
Consoleで、「Hello NAME」を表示して改行します。

パターンマッチング

SNOBOL言語の特徴のひとつに強力なパターンマッチングがあります。


■ パターンマッチングステートメントの形式を下記に示します。

Subject Pattern

各フィールドはひとつ以上のスペースで区切ります。

  • Subjectは、検査対象文字列
  • Patternは、パターン文字列

この文は、Subject文字列の左からPattern文字列をスキャンして出現するか検査し、成功/失敗フラグを設定します。成功/失敗フラグは、分岐文の S(ラベル)/F(ラベル)で参照します。


■ 置換ステートメントの形式を下記に示します。

Subject Pattern = Object

各フィールドはひとつ以上のスペースで区切ります。

  • Subjectは、検査対象文字列
  • Patternは、パターン文字列
  • Objectは、置換文字列

パターンマッチングを行い成功した場合は、Subject文字列の一致した部分文字列をObject文字列に置き換えます。

パターンマッチングの使用例

このパターンマッチング機能を使用して、Word Count (Linuxコマンドの wc)を作ります。

@TYPE WC.SNO
      CNT_CHARS = 0
      CNT_WORDS = 0
      CNT_LINES = 0
      WORDUAZ  = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
      WORDLAZ  = "abcdefghijklmnopqrstuvwxyz"
      WORDNUM  = "0123456789"
      WORD    = "'-" WORDNUM WORDUAZ WORDLAZ
      PAT     = SPAN(WORD) . ITEM
NEXTL DATA = TRIM(INPUT)               :F(DONE)
      CNT_CHARS = CNT_CHARS + SIZE(DATA)
      CNT_LINES = CNT_LINES + 1
NEXTW DATA  PAT  =                     :F(NEXTL)
      CNT_WORDS = CNT_WORDS + 1
      OUTPUT = ITEM
      :(NEXTW)
DONE  OUTPUT = CNT_LINES " lines, " CNT_WORDS " words , " CNT_CHARS " characters"
END
          TOPS-20 version 7 includes all the  facilities  of  previous
     versions  of  TOPS-20 and enhancements through autopatch tape 18.
     It includes the new software capabilities and  components  listed
     in this document.

END文の後ろにテストデータを並べます。

それでは、プログラムを説明します。

      CNT_CHARS = 0
      CNT_WORDS = 0
      CNT_LINES = 0

最初に、文字カウンター(CNT_CHARS)、単語カウンター(CNT_WORDS)、行カウンター(CNT_LINES)をリセットします。

      WORDUAZ  = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
      WORDLAZ  = "abcdefghijklmnopqrstuvwxyz"
      WORDNUM  = "0123456789"
      WORD    = "'-" WORDNUM WORDUAZ WORDLAZ
      PAT     = SPAN(WORD) . ITEM

単語のパターン(PAT)を定義します。
単語の構成は、SPAN()関数によりWORD文字列で指定したひとつ以上の任意文字が連続するシーケンスと一致します。そして、パターンにマッチした部分をドット演算子(.)でITEMに設定します。
WORD文字列は、英大文字(WORDUAZ)/英小文字(WORDLAZ)/数字(WORDNUM)/”‘-“です。

NEXTL DATA = TRIM(INPUT)               :F(DONE)

標準入力(INPUT)から1行入力します。TRIM()関数で余分な末尾のスペースを削除して変数DATAに設定します。標準入力がEOFになれば、DONEラベルに分岐します。

      CNT_CHARS = CNT_CHARS + SIZE(DATA)
      CNT_LINES = CNT_LINES + 1

文字カウンター(CNT_CHARS)に、変数DATAのサイズを加算します。
行カウンター(CNT_LINES)をインクリメントします。

NEXTW DATA  PAT  =                     :F(NEXTL)

変数DATAをパターン(PAT)でマッチングして、一致部分をヌル文字で置換して消去します。一致部分は、変数ITEMに設定します。
パターがマッチしなければ、NEXTLラベルに分岐して次の行を読み込みます。

      CNT_WORDS = CNT_WORDS + 1
      OUTPUT = ITEM
      :(NEXTW)

単語カウンター(CNT_WORDS)をインクリメントします。分解した単語を確認するため、変数ITEMを出力します。NEXTWラベルに分岐して、次の単語を探します。

DONE  OUTPUT = CNT_LINES " lines, " CNT_WORDS " words , " CNT_CHARS " characters

最後に、文字カウンター(CNT_CHARS)、単語カウンター(CNT_WORDS)、行カウンター(CNT_LINES)を出力します。

パターンマッチングの実行例

テストデータを下記に示します。

TOPS-20 version 7 includes all the facilities of previous
versions of TOPS-20 and enhancements through autopatch tape 18.
It includes the new software capabilities and components listed
in this document.

Word Countを実行します。

@SNOBOL WC.SNO
TOPS-20
version
7
includes
all
the
facilities
of
previous
versions
of
TOPS-20
and
enhancements
through
autopatch
tape
18
It
includes
the
new
software
capabilities
and
components
listed
in
this
document
4 lines, 30 words , 232 characters
EXIT
@

単語に分解して表示されました。

  • 4行
  • 30単語
  • 232文字

SNOBOL参考資料

ネットで検索すると SNOBOLに関する参考資料がヒットします。

SNOBOL4 PROGRAMMING LANGUAGEの本のPDFがアップされています。英語ですが、この本を読みこなせば SNOBOL通間違いなしです。

THE SNOBOL4 PROGRAMMING LANGUAGE

THE SNOBOL4 PROGRAM LANGUAGE

THE SNOBOL4 PROGRAM LANGUAGE

 

まとめ

41年ぶりにSNOBOL言語で簡単なプログラミングしました。強力なパターンマッチングにより少ないプログラムステップで目的が達成できます。
もう少し、複雑な処理をSNOBOL言語で書きたくなってきました。

TOPS-20に関するブログ

歴史的に貴重なDEC社 TOPS-20を使うためにKLH10エミュレーターをLinuxにインストールして、TOPS-20を実行することができました。

TOPS-20に関するブログを以下に示します。

DEC社 TOPS-20を使う方法 KLH10エミュレーター導入編

DEC社 TOPS-20を使う方法 KLH10エミュレーター実行編

DEC社 TOPS-20を使う方法 TOPS-20コマンド使用編

DEC社 TOPS-20を使う方法 エミュレーター簡単起動/停止編

DEC社 TOPS-20を使う方法 TELNETでログイン編

DEC社 TOPS-20を使う方法 タイムゾーンの設定編

DEC社 TOPS-20を使う方法 ディレクトリのツリーウォーク編

DEC社 TOPS-20を使う方法 UNIX Toolsとbash使用編

DEC社 TOPS-20を使う方法 ファイルタイプ編

DEC社 TOPS-20を使う方法 FORTHシステム使用編

DEC社 TOPS-20を使う方法 KermitTeraTerm でファイル転送