summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/AbuseFilter/includes/parser/AFPTreeNode.php
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/AbuseFilter/includes/parser/AFPTreeNode.php')
-rw-r--r--www/wiki/extensions/AbuseFilter/includes/parser/AFPTreeNode.php126
1 files changed, 126 insertions, 0 deletions
diff --git a/www/wiki/extensions/AbuseFilter/includes/parser/AFPTreeNode.php b/www/wiki/extensions/AbuseFilter/includes/parser/AFPTreeNode.php
new file mode 100644
index 00000000..e185616c
--- /dev/null
+++ b/www/wiki/extensions/AbuseFilter/includes/parser/AFPTreeNode.php
@@ -0,0 +1,126 @@
+<?php
+/**
+ * Represents a node of a parser tree.
+ */
+class AFPTreeNode {
+ // Each of the constants below represents a node corresponding to a level
+ // of the parser, from the top of the tree to the bottom.
+
+ // ENTRY is always one-element and thus does not have its own node.
+
+ // SEMICOLON is a many-children node, denoting that the nodes have to be
+ // evaluated in order and the last value has to be returned.
+ const SEMICOLON = 'SEMICOLON';
+
+ // ASSIGNMENT (formerly known as SET) is a node which is responsible for
+ // assigning values to variables. ASSIGNMENT is a (variable name [string],
+ // value [tree node]) tuple, INDEX_ASSIGNMENT (which is used to assign
+ // values at list offsets) is a (variable name [string], index [tree node],
+ // value [tree node]) tuple, and LIST_APPEND has the form of (variable name
+ // [string], value [tree node]).
+ const ASSIGNMENT = 'ASSIGNMENT';
+ const INDEX_ASSIGNMENT = 'INDEX_ASSIGNMENT';
+ const LIST_APPEND = 'LIST_APPEND';
+
+ // CONDITIONAL represents both a ternary operator and an if-then-else-end
+ // construct. The format is (condition, evaluated-if-true,
+ // evaluated-in-false), all tree nodes.
+ const CONDITIONAL = 'CONDITIONAL';
+
+ // LOGIC is a logic operator accepted by AFPData::boolOp. The format is
+ // (operation, left operand, right operand).
+ const LOGIC = 'LOGIC';
+
+ // COMPARE is a comparison operator accepted by AFPData::boolOp. The format is
+ // (operation, left operand, right operand).
+ const COMPARE = 'COMPARE';
+
+ // SUM_REL is either '+' or '-'. The format is (operation, left operand,
+ // right operand).
+ const SUM_REL = 'SUM_REL';
+
+ // MUL_REL is a multiplication-related operation accepted by AFPData::mulRel.
+ // The format is (operation, left operand, right operand).
+ const MUL_REL = 'MUL_REL';
+
+ // POW is an exponentiation operator. The format is (base, exponent).
+ const POW = 'POW';
+
+ // BOOL_INVERT is a boolean inversion operator. The format is (operand).
+ const BOOL_INVERT = 'BOOL_INVERT';
+
+ // KEYWORD_OPERATOR is one of the binary keyword operators supported by the
+ // filter language. The format is (keyword, left operand, right operand).
+ const KEYWORD_OPERATOR = 'KEYWORD_OPERATOR';
+
+ // UNARY is either unary minus or unary plus. The format is (operator,
+ // operand).
+ const UNARY = 'UNARY';
+
+ // LIST_INDEX is an operation of accessing a list by an offset. The format
+ // is (list, offset).
+ const LIST_INDEX = 'LIST_INDEX';
+
+ // Since parenthesis only manipulate precedence of the operators, they are
+ // not explicitly represented in the tree.
+
+ // FUNCTION_CALL is an invocation of built-in function. The format is a
+ // tuple where the first element is a function name, and all subsequent
+ // elements are the arguments.
+ const FUNCTION_CALL = 'FUNCTION_CALL';
+
+ // LIST_DEFINITION is a list literal. The $children field contains tree
+ // nodes for the values of each of the list element used.
+ const LIST_DEFINITION = 'LIST_DEFINITION';
+
+ // ATOM is a node representing a literal. The only element of $children is a
+ // token corresponding to the literal.
+ const ATOM = 'ATOM';
+
+ /** @var string Type of the node, one of the constants above */
+ public $type;
+ /**
+ * Parameters of the value. Typically it is an array of children nodes,
+ * which might be either strings (for parametrization of the node) or another
+ * node. In case of ATOM it's a parser token.
+ * @var AFPTreeNode[]|string[]|AFPToken
+ */
+ public $children;
+
+ // Position used for error reporting.
+ public $position;
+
+ public function __construct( $type, $children, $position ) {
+ $this->type = $type;
+ $this->children = $children;
+ $this->position = $position;
+ }
+
+ public function toDebugString() {
+ return implode( "\n", $this->toDebugStringInner() );
+ }
+
+ private function toDebugStringInner() {
+ if ( $this->type == self::ATOM ) {
+ return [ "ATOM({$this->children->type} {$this->children->value})" ];
+ }
+
+ $align = function ( $line ) {
+ return ' ' . $line;
+ };
+
+ $lines = [ "{$this->type}" ];
+ foreach ( $this->children as $subnode ) {
+ if ( $subnode instanceof AFPTreeNode ) {
+ $sublines = array_map( $align, $subnode->toDebugStringInner() );
+ } elseif ( is_string( $subnode ) ) {
+ $sublines = [ " {$subnode}" ];
+ } else {
+ throw new AFPException( "Each node parameter has to be either a node or a string" );
+ }
+
+ $lines = array_merge( $lines, $sublines );
+ }
+ return $lines;
+ }
+}