.. index:: single: Using the Natural Library; Introduction ========================= Using the Natural Library ========================= In this chapter we will learn how to use the Natural Library to quickly define a language that contains a group of commands. To start using the library, We need to call naturallib.ring .. code-block:: ring load "naturallib.ring" After loading the library, We can use the NaturalLanguage class that contains the next methods :- * SetLanguageName(cLanguageName) * setCommandsPath(cFolder) * SetPackageName(cPackageName) * UseCommand(cCommandName) * SetOperators(cOperators) * RunFile(cFileName) * RunString(cString) .. index:: pair: Using the Natural Library; Natural Library - Demo Program Natural Library - Demo Program ============================== We will write the natural code in a Text file, for example program.txt File: program.txt .. code-block:: none 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. Output: .. code-block:: none Hello, Sir! The Numbers! 1 2 3 4 5 I will count Again! 5 4 3 2 1 To execute the natural code, We have start.ring In start.ring we define the language and the commands. File: start.ring .. code-block:: ring load "stdlib.ring" load "naturallib.ring" New NaturalLanguage { SetLanguageName(:MyLanguage) SetCommandsPath(CurrentDir()+"/../command") SetPackageName("MyLanguage.Natural") UseCommand(:Hello) UseCommand(:Count) RunFile("program.txt") } We defined a language called MyLanguage, We have folder for the language commands. Each command will define a class that belong to the MyLanguage.Natural package. We will define two commands, Hello and Count. So we must have two files for defining the commands in the CurrentDir()+"/../command" folder File: hello.ring .. code-block:: ring DefineNaturalCommand.SyntaxIsKeyword([ :Package = "MyLanguage.Natural", :Keyword = :hello, :Function = func { See "Hello, Sir!" + nl + nl } ]) File: count.ring .. code-block:: 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) } ]) .. index:: pair: Using the Natural Library; Defining Commands Defining Commands ================= To define new command we can use the DefineNaturalCommand object This object provides the next methods :- * 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) File: mylanguage.ring .. code-block:: 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) } Example (1) In the next example we will define the Print command. We will use the SyntaxIsKeywordExpression() Method. We pass list (as Hash) to the method. We determine the package name, the keyword and the function that will be executed. Inside this function we uses the Expr(nExprNumber) function to get the expression value that the user will write after the keyword. File: print.ring .. code-block:: ring DefineNaturalCommand.SyntaxIsKeywordExpression([ :Package = "MyLanguage.Natural", :Keyword = :print, :Function = func { See Expr(1) } ]) Usage: .. code-block:: ring load "mylanguage.ring" MyLanguage.RunString(' print "Hello, World!" ') Output: .. code-block:: none Hello, World! Example (2) File: iwantwindow.ring .. code-block:: ring DefineNaturalCommand.SyntaxIsCommand([ :Package = "MyLanguage.Natural", :Command = "i want window", :Function = func { See "Command: I want window" + nl } ]) Usage: .. code-block:: ring load "mylanguage.ring" MyLanguage.RunString(' i want window ') Output: .. code-block:: none Command: I want window Example (3) File: windowtitleis.ring .. code-block:: ring DefineNaturalCommand.SyntaxIsCommandString([ :Package = "MyLanguage.Natural", :Command = "window title is", :Function = func { See "Command: Window title is " + Expr(1) + nl } ]) Usage: .. code-block:: ring load "mylanguage.ring" MyLanguage.RunString(' I want window and the window title is "Hello World" ') Output: .. code-block:: none Command: I want window Command: Window title is Hello World .. index:: pair: Using the Natural Library; Operators Natural Library - Operators =========================== In the next example we uses the Count command without using operators .. code-block:: ring load "mylanguage.ring" MyLanguage.RunString(" Hello Count 1 5 Count 5 1 ") We can add more description .. code-block:: ring load "mylanguage.ring" MyLanguage.RunString(" Hello, Please Count from 1 to 5 then count from 5 to 1 ") Also we can use operators like "(" and ")" around the instruction .. code-block:: ring 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! ") } .. index:: pair: Using the Natural Library; Defining commands using classes Defining commands using classes =============================== This section is related to the implementation details. When we define new command, Each command is defined by the Natural Library as a class. We have the choice to define commands using the simple interface provided by the DefineNaturalCommand object or by defining new class as in the next examples. If we used DefineNaturalCommand (More Simple), The class will be defined during the runtime. File: hello.ring .. code-block:: ring Package MyLanguage.Natural class Hello func AddAttributes_Hello AddAttribute(self,:hello) func GetHello See "Hello, Sir!" + nl + nl File: count.ring .. code-block:: 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)