自然言語ライブラリの用法

注意

自然言語ライブラリは ASCII エンコーディング専用です。マルチバイト文字列 (UTF-8, Shift JIS, JIS, EUC-JP など) での記述はできません。これは Ring の文字列処理用の組み込み関数 (left, right, len, substr) の制約によるものです。原作者側では未だに文字列処理を軽視しているようでコトの重要性を認識していないようです。そういう方針だと思って諦めましょう。

注釈

For foreign Ring developers: if you need japanese text test data, use a 青空文庫. It's mainly of the public domain's japanese literature collections.

自然言語ライブラリで命令グループのある言語を手軽に定義するための用法です。

自然言語ライブラリの使用前に naturallib.ring ライブラリを読み込みます。

load "naturallib.ring"

ライブラリの読み込み後、このメソッドで自然言語を使えます。

  • SetLanguageName(cLanguageName)

  • setCommandsPath(cFolder)

  • SetPackageName(cPackageName)

  • UseCommand(cCommandName)

  • SetOperators(cOperators)

  • RunFile(cFileName)

  • RunString(cString)

自然言語ライブラリ - デモプログラム

例えば、テキストファイル program.txt に自然言語コードを記述します。

ファイル: program.txt

Welcome to the Ring programming language!
What you are reading now is not comments, I swear!

After many years of programming I decided to think different about
programming and solve the problems in a better way.

We are writing commands or code and the Ring language is reading
it to understand us! Sure, What you are seeing now is
just ***part of the code - Not the Complete Program***
You have to write little things before and after this
part to be able to run it!

It is the natural part of our code where we can write in English,
Arabic or any Natural Language Then we will tell the computer
through the Ring language what must happens! in a way that we can scale
for large frameworks and programs.

Just imagine what will happens to the world of programming once
we create many powerful frameworks using the Ring language that
uses this way (Natural Programming).

For example When we say Hello to the Machine, It can reply! and when we
say count from 1 to 5 it will understand us, Also if
we said count from 5 to 1 it will
understand us too! You can see the Output window!

This Goal is not new, but the Ring language comes
with an innovative solution to this problem.

実行結果:

Hello, Sir!


The Numbers!

1

2

3

4

5

I will count Again!

5

4

3

2

1

自然言語コードを実行するには start.ring が必要です。

start.ring には言語と命令を定義します。

ファイル: start.ring

load "stdlib.ring"
load "naturallib.ring"

New NaturalLanguage {
        SetLanguageName(:MyLanguage)
        SetCommandsPath(CurrentDir()+"/../command")
        SetPackageName("MyLanguage.Natural")
        UseCommand(:Hello)
        UseCommand(:Count)
        RunFile("program.txt")
}

これで MyLanguage 言語名は定義済みになり、言語命令用のフォルダが指定されます。

各命令は MyLanguage.Natural パッケージにあるクラスとして定義されています。

命令として Hello と Count を定義しています。

CurrentDir()+”/../command” フォルダで命令を定義するには以下のファイルが必要です。

ファイル: hello.ring

DefineNaturalCommand.SyntaxIsKeyword([
        :Package = "MyLanguage.Natural",
        :Keyword = :hello,
        :Function = func {
                See  "Hello, Sir!" + nl + nl
        }
])

ファイル: count.ring

DefineNaturalCommand.SyntaxIsKeywordNumberNumber([
        :Package = "MyLanguage.Natural",
        :Keyword = :count,
        :Function = func {
                if not isattribute(self,:count_times) {
                        AddAttribute(self,:count_times)
                        Count_Times = 0
                }
                if Expr(1) > Expr(2) {
                        nStep = -1
                else
                        nStep = 1
                }
                if Count_Times = 0 {
                        see nl+"The Numbers!" + nl
                        Count_Times++
                else
                        see nl + "I will count Again!" +nl
                }
                for x = Expr(1) to Expr(2) step nStep {
                        see nl+x+nl
                }
                CommandReturn(fabs(Expr(1)-Expr(2))+1)
        }
])

命令の定義

DefineNaturalCommand オブジェクトで新しい命令を定義します。

このオブジェクトでは、下記のメソッドが使えます。

  • SyntaxIsKeyword(aPara)

  • SyntaxIsKeywordNumber(aPara)

  • SyntaxIsKeywordNumberNumber(aPara)

  • SyntaxIsKeywordNumbers(aPara,nCount)

  • SyntaxIsKeywordString(aPara)

  • SyntaxIsKeywordStringString(aPara)

  • SyntaxIsKeywordStrings(aPara,nCount)

  • SyntaxIsKeywordExpression(aPara)

  • SyntaxIsKeywordExpressionExpression(aPara)

  • SyntaxIsKeywordExpressions(aPara,nCount)

  • SyntaxIsCommand(aPara)

  • SyntaxIsCommandNumber(aPara)

  • SyntaxIsCommandNumberNumber(aPara)

  • SyntaxIsCommandNumbers(aPara,nCount)

  • SyntaxIsCommandString(aPara)

  • SyntaxIsCommandStringString(aPara)

  • SyntaxIsCommandStrings(aPara,nCount)

  • SyntaxIsCommandExpression(aPara)

  • SyntaxIsCommandExpressionExpression(aPara)

  • SyntaxIsCommandExpressions(aPara,nCount)

ファイル: mylanguage.ring

load "stdlib.ring"
load "naturallib.ring"

MyLanguage = New NaturalLanguage {
        SetLanguageName(:MyLanguage)
        SetCommandsPath(CurrentDir()+"/../command")
        SetPackageName("MyLanguage.Natural")
        UseCommand(:Hello)
        UseCommand(:Count)
        UseCommand(:Print)
        UseCommand(:IWantWindow)
        UseCommand(:WindowTitleIs)
        UseCommand(:IWantButton)
}

用例①

この用例では、 Print 命令を定義します。

SyntaxIsKeywordExpression() メソッドを使用します。

メソッドにはリスト (ハッシュとして) を渡します。 実行するパッケージ名、キーワード、および関数を決定します。

この定義にある Expr(nExprNumber) 関数はユーザがキーワードの後に記述する式の値を取得します。

ファイル: print.ring

DefineNaturalCommand.SyntaxIsKeywordExpression([
        :Package = "MyLanguage.Natural",
        :Keyword = :print,
        :Function = func {
                See  Expr(1)
        }
])

用法:

load "mylanguage.ring"

MyLanguage.RunString('
        print "Hello, World!"
')

実行結果:

Hello, World!

用例②

ファイル: iwantwindow.ring

DefineNaturalCommand.SyntaxIsCommand([
        :Package = "MyLanguage.Natural",
        :Command = "i want window",
        :Function = func {
                See  "Command: I want window" + nl
        }
])

用法:

load "mylanguage.ring"

MyLanguage.RunString('
        i want window
')

実行結果:

Command: I want window

用例③

ファイル: windowtitleis.ring

DefineNaturalCommand.SyntaxIsCommandString([
        :Package = "MyLanguage.Natural",
        :Command = "window title is",
        :Function = func {
                See  "Command: Window title is " + Expr(1) + nl
        }
])

用法:

load "mylanguage.ring"

MyLanguage.RunString('
        I want window and the window title is "Hello World"
')

実行結果:

Command: I want window
Command: Window title is Hello World

自然言語ライブラリ - 演算子

この用例は演算子ではなく Count 命令を使用しています。

load "mylanguage.ring"

MyLanguage.RunString("
        Hello
        Count 1 5
        Count 5 1
")

詳述すると、

load "mylanguage.ring"

MyLanguage.RunString("
        Hello, Please   Count from 1 to 5 then count from 5 to 1
")

また、命令は “(” や ”)” などの演算子で囲むことができます。

load "mylanguage.ring"

MyLanguage {
        SetOperators("()")
        RunString("
                Here we will play and will try something
                that looks like Lisp Syntax
                (count  (count 1 5)  (count 20 15))
                Just for fun!
        ")
}

クラスによる命令の定義

実装について詳しく説明します。

自然言語ライブラリは新規命令の定義をするたびにクラスを定義します。

DefineNaturalCommand オブジェクト、またはこの用例のように、新しいクラスの定義により単純明快なインタフェースで命令を定義する選択肢があります。

DefineNaturalCommand (最も簡単な方法) は実行時にクラスを定義します。

ファイル: hello.ring

Package MyLanguage.Natural

class Hello

        func AddAttributes_Hello
                AddAttribute(self,:hello)

        func GetHello
                See  "Hello, Sir!" + nl + nl

ファイル: count.ring

Package MyLanguage.Natural

class Count

        func Getcount
                StartCommand()
                CommandData()[:name] = :Count
                CommandData()[:nExpr] = 0
                CommandData()[:aExpr] = []

        func BraceExprEval_Count nValue
                if isCommand() and CommandData()[:name] = :Count {
                        if isNumber(nValue) {
                                CommandData()[:nExpr]++
                                CommandData()[:aExpr] + nValue
                                if CommandData()[:nExpr] = 2 {
                                        Count_Execute()
                                }
                        }
                }

        func AddAttributes_Count
                AddAttribute(self,:count)

        func Count_Execute
                if not isattribute(self,:count_times) {
                        AddAttribute(self,:count_times)
                        Count_Times = 0
                }
                if Expr(1) > Expr(2) {
                        nStep = -1
                else
                        nStep = 1
                }
                if Count_Times = 0 {
                        see nl+"The Numbers!" + nl
                        Count_Times++
                else
                        see nl + "I will count Again!" +nl
                }
                for x = Expr(1) to Expr(2) step nStep {
                        see nl+x+nl
                }
                CommandReturn(fabs(Expr(1)-Expr(2))+1)