一元运算符(+ - ~ )
(unary operator(+ - ~))
(一)一元运算符
一元运算符是只有一个操作数的运算符,在Redy中有:'+' , '-' , '~' 这么三种,它们的运算优先级相等,结合方向为自右到左。当这三个运算符的操作数为整数,长整数时,它们代表着正号,负数,取反。例如:
代码1.1
- a=1
- -a /*结果为-1*/
- +a /*结果为1*/
- ----a /*四个负号,结果为1*/
- ++++a /*不管多少个正号,结果还是1*/
- +-+-+-a /*正号对我没影响,可是负号有3个,结果为-1*/
- ~a /*1取反,结果为-2*/
- ~~a /*两次取反,还原了,结果为1*/
析解器解析代码1.1并为之构造语法树,需要分别用结点来表示这三个一元运算符。在Redy源码中,符号'+' 用结点AstNodePositive表示,符号'-'用结点AstNodeNegative表示,符号'~'用结点AstNodeNegated 表示,这三个结点都继承同一个结点AstNodeUExpr。用uml来表示它们之间的关系为:
图1
图1的内容为:
AstNodeNegative,AstNodePositive,AstNodeNegated继承AstNodeUExpr。
AstNodeUExpr继承AstObject
AstNodeUExpr由一个子结点s_value组成
(二)语法树实例1
下面来看一元运算符的实例。
代码1.2:
- -+-1
在代码1.2中有3个一运算符和一个整数型的文字常量,要为之构造语法树,则需4个结点,三个一元运算符结点,一个文字常量结点(文字常量结点在前面文章中讲到)。具体的语法构如下:
图2
要图2的语法树跑起来,需要从结点root来始执行,然后递归调用。AstNodeLiteral的执行方式前面已经讲到过,但还有两个节点AstNodePositive,AstNodeNegative的执行方式还没有实现。下面来看:
AstNodePositive的执行方式
代码1.3
- AstNodePositive.execute()
- AstNodePositive.s_value.execute() /*执行子节点*/
- value=reg0 /*子结点的执行后的结果,在寄存器reg0中*/
- ret=value.positive() /*调用positive()方法*/
- reg0=ret /*把结果保存存reg0中,供父结点使用*/
- end
其中需要说明的是;
(1)在前面一章中,介绍了一个简单的虚拟机,该虚拟机有一个寄存器reg0。每个节点执行过后,都必须把结果放在寄存器reg0中。
(2)在Redy中每一个对象,如果要支持某种运算符,那就必须实现该运算相对应的方法,例如要支持一元运算符'+',就必须实现positive方法;要支持一元运算符'-',就必须实现negative方法;要支持一元运算符'~',就必须实现negated方法。
AstNodeNegative的执行方式:
代码1.4
- AstNodeNegative.execute()
- AstNodeNegative.s_value.execute() /*执行子节点*/
- value=reg0 /*子结点的执行后的结果,在寄存器reg0中*/
- ret=value.negative() /*调用negative()方法*/
- reg0=ret /*把结果保存存reg0中,供父结点使用*/
- end
现在来运行图1中的语法树,一点问题都没有了。
(三)语法树实例2
代码1.5
- ~+-4
为代码1.5构造语法树为:
图3
在实例1中,已经实现了AstNodeNegative,和AstNodePositive的执行方法,要让图3个语法树跑要来,还需要实现AstNodeNegated的执行方法,具体如下:
代码1.6
- AstNodeNegated.execute()
- AstNodeNegated.s_value.execute() /*执行子节点*/
- value=reg0 /*子结点的执行后的结果,在寄存器reg0中*/
- ret=value.Negated() /*调用Negated()方法*/
- reg0=ret /*把结果保存存reg0中,供父结点使用*/
- end
Ok,现在就可以执行图3的语法树。
附: 代码下载: git clone git://git.code.sf.net/p/redy/code redy-code
AstNodePositive ,AstNodeNegative, AstNodeNegated 位于src/syntax/ 文件ast_node_unary_expr中