65.9K
CodeProject 正在变化。 阅读更多。
Home

Ring 编程语言中的自然语言编程

starIconstarIconstarIconstarIconstarIcon

5.00/5 (13投票s)

2016 年 10 月 13 日

CPOL

5分钟阅读

viewsIcon

27956

downloadIcon

178

基于面向对象编程的 Ring 编程语言中的自然语言定义

引言

2010年,我开发了一种名为Supernova的新编程语言。该语言使用一种看起来类似于自然语言语句的代码来创建简单的GUI应用程序。五年后,在Ring编程语言中,我们可以获得类似的结果,但现在我们能够在我们喜欢的或需要的任何领域中创建/使用类似于自然语言语句的代码。

Ring编程语言附带Supernova的精灵,但具有更强的通用性,并混合了其他语言的精灵。

该语言对自然语言编程和声明式编程提供了更好的支持。创新之处在于,在面向对象编程和函数式编程的基础上,通过新的实用技术来支持这些范例。Ring为程序员提供了构建类似于Supernova的自然语言或类似于REBOL和QML的声明式语言的工具,而无需了解任何关于(编译器和解析)的知识。您可以使用现成的语言构造来创建领域特定语言,而且速度非常快。

使用Ring编程语言,我们可以基于类和对象创建自然编程语言。

在Supernova语言中,我们可以输入(我想要一个窗口,窗口标题是hello world。)然后它将创建一个GUI窗口,窗口标题为“Hello, World!”。当我2010年创建Supernova语言时,我发现使用自然代码就像使用英语一样,不受限制,我们可以获得人类语言在编程中的强大功能,但要实现这一点,我们需要一种新语言,这种语言

  1. 通用目的
  2. 实践
  3. 可以非常快速地创建自然语言

因此,我们可以得到一个能够最大程度提高易用性和生产力的系统。

Supernova只是对这个想法的一次测试。以一种更近距离的视角来审视它的优缺点。在测试了新的想法后,您会得到一些实际的东西。所以,继Supernova语言之后,我们就有了Ring语言。

为什么要有定义自己语言的能力,而不是仅仅交出语法然后让你用你喜欢的任何代码来解析它?

这是创新——你无需了解解析即可创建自然语句。你只需使用类,这是一个明智的决定(之后我们可以混合使用类来支持更多基于上下文的语句——我们可以更改和翻译定义的语句,还有更多!)。此外,语句在Ring World中添加,你可以在其中使用任何Ring语句。

为什么选择自然语言编程?我们不是已经可以用命令式、面向对象和函数式语言做任何事情了吗?

当你设计一门新语言时,你可以从过去学习,但你必须着眼未来,活在当下。你对自然编程的了解可能基于这些范式在实际世界中力量的旧知识,我同意你,但我看到了另一种可以应用于实际工作的技术。你所忽视的自然语言是它们是上下文敏感的,这意味着我们可以以不同的方式使用它们,并思考如何表达我们的想法。

示例(1):我想要一个包含3个按钮的窗口。

一句话,我创建了4个对象(窗口和三个按钮),并将按钮添加到窗口中。自然编程的理念就是这样高效地完成许多事情。

示例(2):接收2个数字,然后打印它们的和。

背景

您可以查看这篇文章了解Supernova编程语言,以及这篇文章了解Ring编程语言。

还可以查看以下关于Ring编程语言的教程。

  1. 入门
  2. 控制结构
  3. 函数
  4. 列表

Ring语言中支持自然语言的特性

(1)紧凑的语法,语句没有明确的结尾(不需要;或ENTER)

示例

See "What is your name? " give cName see "Hello " + cName

或者用另一种风格

Put "What is your name? " Get cName Put "Hello " + cName

(2)使用花括号{ },我们可以直接像使用变量/函数一样访问对象并使用其属性/方法

示例

New point                       # create new object using the point class
{                               # access the new object attributes and methods
        x = 10                  # set the x attribute to 10
        y = 20                  # set the y attribute to 20
        z = 30                  # set the z attribute to 30
        print()                 # call the print method
}                               # end of object access

Class Point                     # define the Point class
        x y z                   # the class contains three attributes x, y & z
        func print              # define the print method
                see x + nl +    # print the x attribute
                    y + nl +    # print the y attribute
                    z + nl      # print the z attribute

(3)我们可以定义方法,以便在设置和获取对象属性时使用。

示例

o1 = new person

o1.name = "Mahmoud"  see o1.name + nl

o1 { name = "Ahmed"  see name }

Class Person

        name family = "Fayed"

        func setname value
                see "Message from SetName() Function!" + nl
                name = value + " " + family

        func getname
                see "Message from GetName() Function!" + nl
                return "Mr. " + name

输出

Message from SetName() Function!
Message from GetName() Function!
Mr. Mahmoud Fayed
Message from SetName() Function!
Message from GetName() Function!
Mr. Ahmed Fayed

使用代码

下一个例子展示了如何创建一个定义两个指令的类

  • 第一个指令是:我想要窗口
  • 第二个指令是:窗口标题 = <expr>

还可以忽略诸如“the”之类的关键字

	New App 
	{
		I want window 	
		The window title = "hello world"
	}

	Class App

		# Attributes for the instruction I want window
			i want window 
			nIwantwindow = 0
		# Attributes for the instruction Window title
		# Here we don't define the window attribute again
			title 
			nWindowTitle = 0
		# Keywords to ignore, just give them any value
			the=0	

		func geti
			if nIwantwindow = 0
				nIwantwindow++
			ok

		func getwant
			if nIwantwindow = 1
				nIwantwindow++
			ok

		func getwindow
			if nIwantwindow = 2
				nIwantwindow= 0
				see "Instruction : I want window" + nl
			ok
			if nWindowTitle = 0
				nWindowTitle++
			ok
	
		func settitle cValue
			if nWindowTitle = 1
				nWindowTitle=0
				see "Instruction : Window Title = " + cValue + nl
			ok

输出

Instruction : I want window
Instruction : Window Title = hello world

如果我们想用“and”连接两个指令怎么办?

我们遇到了一个问题,因为在Ring中“and”是一个关键字。

我们可以使用ChangeRingKeyword命令来改变它。

ChangeRingKeyword命令在编译器的扫描阶段执行(在解析之前)。

注意:请记住恢复该关键字。

语法

ChangeRingKeyword  <oldkeyword>  <newkeyword>

示例

ChangeRingKeyword       and  _and

New App
{
                I want window and the window title = "hello world"
}

Class App

                # Attributes for the instruction I want window
                                i want window
                                nIwantwindow = 0
                # Attributes for the instruction Window title
                # Here we don't define the window attribute again
                                title
                                nWindowTitle = 0
                # Keywords to ignore, just give them any value
                                the=0  and=0

ChangeRingKeyword       _and  and

                func geti
                        if nIwantwindow = 0
                                nIwantwindow++
                        ok

                func getwant
                        if nIwantwindow = 1
                                nIwantwindow++
                        ok

                func getwindow
                        if nIwantwindow = 2
                                nIwantwindow= 0
                                see "Instruction : I want window" + nl
                        ok
                        if nWindowTitle = 0
                                nWindowTitle++
                        ok

                func settitle cValue
                        if nWindowTitle = 1
                                nWindowTitle=0
                                see "Instruction : Window Title = " + cValue + nl
                        ok

                func getand
                        see "Using : and" + nl

输出

Instruction : I want window
Using : and
Instruction : Window Title = hello world

如果我们想为任何运算符(如“=”运算符)定义新的行为该怎么办?

我们可以使用ChangeRingOperator命令来进行这种更改,以隐藏运算符(更改其名称)。

然后,我们可以将该运算符用作标识符,并处理其行为。

语法

ChangeRingOperator  <oldoperator>  <newoperator>

现在,我们将“=”运算符更改为“is”。

示例

ChangeRingKeyword       and  _and
ChangeRingOperator      =    is

New App
{
                I want window and the window title is "hello world"
}

ChangeRingOperator      is    =

Class App

                # Attributes for the instruction I want window
                                i want window
                                nIwantwindow = 0
                # Attributes for the instruction Window title
                # Here we don't define the window attribute again
                                title
                                nWindowTitle = 0
                # Keywords to ignore, just give them any value
                                the=0  and=0

ChangeRingKeyword       _and  and

                func geti
                        if nIwantwindow = 0
                                nIwantwindow++
                        ok

                func getwant
                        if nIwantwindow = 1
                                nIwantwindow++
                        ok

                func getwindow
                        if nIwantwindow = 2
                                nIwantwindow= 0
                                see "Instruction : I want window" + nl
                        ok
                        if nWindowTitle = 0
                                nWindowTitle++
                        ok

                func settitle cValue
                        if nWindowTitle = 1
                                nWindowTitle=0
                                see "Instruction : Window Title = " + cValue + nl
                        ok

Eval() 函数

我们可以使用Eval()函数在运行时从string执行代码。

语法

Eval(cCode)

示例

Eval("nOutput = 5+2*5 " )
See "5+2*5 = " + nOutput + nl
Eval("for x = 1 to 10 see x + nl next")
Eval("func test see 'message from test!' ")
test()

输出

5+2*5 = 15
1
2
3
4
5
6
7
8
9
10
message from test!

Eval()与我们的自然代码一起使用

func Main

  cProgram = ' I want window and the window title is "hello world" '

  MyLanguage(cProgram)

Func MyLanguage cCode

  # We add to the code the instructions that change keywords and operators
  # Because Eval() uses a new Compiler Object (the original keywords and operatos).

  cCode = '
        ChangeRingKeyword  and  _and
        ChangeRingOperator  =    is
  ' + cCode

  New App
  {
          eval(cCode)
  }

  Class App

          # Attributes for the instruction I want window
                  i want window
                  nIwantwindow = 0
          # Attributes for the instruction Window title
          # Here we don't define the window attribute again
                  title
                  nWindowTitle = 0
          # Keywords to ignore, just give them any value
                  the=0

          ChangeRingKeyword  and  _and
                  and=0
          ChangeRingKeyword  _and  and

          func geti
                if nIwantwindow = 0
                  nIwantwindow++
                ok

          func getwant
                if nIwantwindow = 1
                  nIwantwindow++
                ok

          func getwindow
                if nIwantwindow = 2
                  nIwantwindow= 0
                  see "Instruction : I want window" + nl
                ok
                if nWindowTitle = 0
                  nWindowTitle++
                ok

          func settitle cValue
                if nWindowTitle = 1
                  nWindowTitle=0
                  see "Instruction : Window Title = " + cValue + nl
                ok

BraceStart() 和 BraceEnd()

我们可以在使用{ }之前/之后编写将要执行的代码

示例

o1 = new test {
        see "Hello" + nl
}

o1 {}

class test

        func bracestart
                see "start" + nl

        func braceend
                see "end" + nl

输出

start
Hello
end
start
end

使用 BraceExprEval()

下一个例子演示了如何使用“BraceExprEval”方法在自然代码中获取表达式。

示例

new natural {
        create 5
}

class natural
        create=0
        lkeyword = false
        func braceexpreval r
                if lkeyword lkeyword=false return ok
                see "expr eval" + nl
                see "type: " + type(r) see nl
                see "value : " see r see nl
        func getcreate
                lkeyword = true
                see "create" + nl

输出

create
expr eval
type: NUMBER
value : 5

真实的自然代码

下一个例子是一个更高级的例子。

# Natural Code
new program {
        Accept 2 numbers then print the sum
}

# Natural Code Implementation
class program
        # Keywords
                Accept=0 numbers=0 then=0 print=0 the=0 sum=0

        # Execution
        func braceexpreval x
                value = x
        func getnumbers
                for x=1 to value
                        see "Enter Number ("+x+") :" give nNumber
                        aNumbers + nNumber
                next
        func getsum
                nSUm = 0
                for x in aNumbers nSum+= x next
                see "The Sum : " + nSum
        private
                value=0 aNumbers=[]

输出

Enter Number (1) :3
Enter Number (2) :4
The Sum : 7

使用 BraceError()

接下来的例子演示了如何使用“BraceError”方法来处理使用花括号{}访问对象时出现的错误。

示例

func main
        o1 = new point {
                x=10 y=20 z=30
                TEST
                SEE test
        }

class point x y z
        func braceerror
                see "Handle Error!" + nl
                SEE "Message :" + cCatchError + nl
                if ( left(cCatchError,11) = "Error (R24)" ) and not isattribute(self,"test")
                        see "add attribute" + nl
                        addattribute(self,"test")
                        test = 10
                ok
                see "done" + nl
                return

输出

Handle Error!
Message :Error (R24) : Using uninitialized variable : test
add attribute
done
10

示例

new point {
        x=10 y=20 z=30
        test()
        see "mmm..." + NL
}

class point x y z
        func braceerror
                see "Handle Error!" + nl
                see "Message :" + cCatchError + nl
                see self
                see "Done" + NL

输出

Handle Error!
Message :Error (R3) : Calling Function without definition !: test
x: 10.000000
y: 20.000000
z: 30.000000
Done
mmm...

干净的自然代码

与键入字面量“literal”相反,我们可以直接接受单词。

示例

下一个例子接受hello world而不是“hello world

ChangeRingKeyword       and  _and
ChangeRingOperator      =    is

New App
{
        I want window and the window title is hello world
}

ChangeRingOperator      is    =

Class App

        # Attributes for the instruction I want window
                        i want window
                        nIwantwindow = 0
        # Attributes for the instruction Window title
        # Here we don't define the window attribute again
                        title
                        nWindowTitle = 0
        # Keywords to ignore, just give them any value
                        the=0  and=0
        # Data
                        literal = ""

ChangeRingKeyword       _and  and

        func geti
                if nIwantwindow = 0
                        nIwantwindow++
                ok

        func getwant
                if nIwantwindow = 1
                        nIwantwindow++
                ok

        func getwindow
                if nIwantwindow = 2
                        nIwantwindow= 0
                        see "Instruction : I want window" + nl
                ok
                if nWindowTitle = 0
                        nWindowTitle++
                ok

        func settitle cValue
                if nWindowTitle = 1
                        nWindowTitle=2
                ok

        func braceend
                if nWindowTitle = 2
                        see "Instruction : Window Title = " + literal + nl
                        nWindowTitle = 0
                ok

        func braceerror
                c= substr(cCatchError,":")
                while c > 0
                        c= substr(cCatchError,":")
                        cCatchError=substr(cCatchError,c+1)
                end
                literal += substr(cCatchError,1)

关注点

2010年,我花了9个月的时间开发了Supernova语言。现在使用Ring,我可以在几天内实现类似Supernova的语言。基于类定义自然语言而不是创建编译器,这一点意义重大。这提高了生产力并降低了问题的复杂性。您可以创建大型自然编程语言,并且仍然能够控制项目。考虑使用Ring来实现您的下一个自然编程语言!

历史

  • 2016年10月13日:初始版本

在自然编程语言方面已经做了很多工作。Ring编程语言是一种实用的编程语言,它试图将自然语言编程向前推进一步。Ring是一种新语言,于2016年1月25日发布。

© . All rights reserved.