aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--doc/sciteco.7.template62
-rw-r--r--src/expressions.cpp3
-rw-r--r--src/expressions.h34
3 files changed, 60 insertions, 39 deletions
diff --git a/doc/sciteco.7.template b/doc/sciteco.7.template
index 9c6180c..30d6c76 100644
--- a/doc/sciteco.7.template
+++ b/doc/sciteco.7.template
@@ -726,40 +726,55 @@ command.
.SS Operators
.
The following binary operators are supported with descending
+precedence, whereas borders separate operators of the \fIsame\fP
precedence:
-.TP 2
-.IB base " ^* " power
+.TS
+expand,box,tab(;);
+L LX.
+\fIbase\fB ^* \fIpower\fR;T{
Raise \fIbase\fP to \fIpower\fP.
-.TP
-.IB a " ^/ " b
+T}
+=
+\fIa\fB ^/ \fIb\fR;T{
Remainder of \fIa\fP divided by \fIb\fP.
It is actually a modulo operation conforming to the
host C compiler's modulo semantics.
-.TP
-.IB a " / " b
+T}
+\fIa\fB / \fIb\fR;T{
Divide \fIa\fP by \fIb\fP.
Naturally it is a division without remainder.
-.TP
-.IB a " * " b
+T}
+\fIa\fB * \fIb\fP;T{
Multiply \fIa\fP by \fIb\fP.
-.TP
-.IB a " - " b
+T}
+=
+\fIa\fB - \fIb\fP;T{
Subtract \fIb\fP from \fIa\fP.
-.TP
-.IB a " + " b
+T}
+\fIa\fB + \fIb\fP;T{
Add \fIb\fP to \fIa\fP.
-.TP
-.IB a " & " b
+T}
+=
+\fIa\fB & \fIb\fP;T{
Binary AND.
-.TP
-.IB a " ^# " b
+T}
+=
+\fIa\fB ^# \fIb\fP;T{
Binary exclusive OR (XOR).
-.TP
-.IB a " # " b
+T}
+=
+\fIa\fB # \fIb\fP;T{
Binary OR.
+T}
+.TE
.LP
+All binary operators are \fIleft-associative\fP, ie. associate
+from left to right, in \*(ST.
Round brackets may be used for grouping expressions to override
-operator precedence.
+operator precedence and associativity.
+For instance, since \(lq\fB^/\fP\(rq, \(lq\fB/\fP\(rq and \(lq\fB*\fP\(rq
+all have the same precedence, the expression \(lq1 ^/ 2 / 3 * 4\(rq is
+equivalent to \(lq(((1 ^/ 2) / 3) * 4)\(rq.
The opening bracket also represents an argument barrier, ie. the first
command after the opening bracket does not see and cannot pop any
arguments from the stack.
@@ -774,15 +789,6 @@ mandatory in classic TECO, like in \(lq.ZD\(rq.
I recommend to use it as much as possible in code where clarity
matters.
.LP
-Note that \*(ST assigns an unique precedence to each operator
-instead of having several operators (like addition and subtraction)
-share the same precedence and evaluate them according to their
-associativity.
-Still the precedence rules should ensure that expressions are
-evaluated similarily to other programming languages.
-When the same operator is used repeatedly, expressions are always
-evaluated with left-to-right associativity.
-For instance, \(lq2^*3^*4\(rq is evaluated like \(lq(2^*3)^*4\(rq.
The arithmetic evaluation order established by the operator precedence
or braces must not be confused with the execution order of \*(ST commands
which is always strictly from left to right (unless flow control
diff --git a/src/expressions.cpp b/src/expressions.cpp
index 8d21388..6b1e8fe 100644
--- a/src/expressions.cpp
+++ b/src/expressions.cpp
@@ -93,7 +93,8 @@ Expressions::push_calc(Expressions::Operator op)
gint first = first_op();
/* calculate if op has lower precedence than op on stack */
- if (first >= 0 && operators.peek(first) <= op)
+ if (first >= 0 &&
+ precedence(operators.peek(first)) <= precedence(op))
calc();
return push(op);
diff --git a/src/expressions.h b/src/expressions.h
index f97ec1c..e49880c 100644
--- a/src/expressions.h
+++ b/src/expressions.h
@@ -150,31 +150,45 @@ public:
}
};
-/*
+/**
* Arithmetic expression stacks
*/
extern class Expressions {
public:
- /* reflects also operator precedence */
+ /**
+ * Operator type.
+ * The enumeration value divided by 16 represents
+ * its precedence (the lower, the higher).
+ * In other words, the value's lower nibble is
+ * reserved for enumerating operators of the
+ * same precedence.
+ */
enum Operator {
- OP_NIL = 0,
- OP_POW, // ^*
- OP_MOD, // ^/
+ OP_NIL = 0,
+ OP_POW = 0x10, // ^*
+ OP_MOD = 0x20, // ^/
OP_DIV, // /
OP_MUL, // *
- OP_SUB, // -
+ OP_SUB = 0x30, // -
OP_ADD, // +
- OP_AND, // &
- OP_XOR, // ^#
- OP_OR, // #
+ OP_AND = 0x40, // &
+ OP_XOR = 0x50, // ^#
+ OP_OR = 0x60, // #
// pseudo operators:
- OP_NEW,
+ OP_NEW = 0xF0,
OP_BRACE,
OP_LOOP,
OP_NUMBER
};
private:
+ /** Get operator precedence */
+ inline gint
+ precedence(Operator op)
+ {
+ return op >> 4;
+ }
+
ValueStack<tecoInt> numbers;
ValueStack<Operator> operators;