private function _search_reviewer($qword, $keyword, &$qt) { global $Conf; if (preg_match('/\\A(.*)(pri|sec|ext)\\z/', $keyword, $m)) { $qword = $m[2] . ":" . $qword; $keyword = $m[1]; } if (str_starts_with($keyword, "c")) { $qword = "complete:" . $qword; } else { if (str_starts_with($keyword, "i")) { $qword = "incomplete:" . $qword; } else { if (str_starts_with($keyword, "p")) { $qword = "inprogress:" . $qword; } } } $rt = 0; $completeness = 0; $quoted = false; $contacts = null; $rounds = null; $count = ">0"; $wordcount = null; $tailre = '(?:\\z|:|(?=[=!<>]=?|≠|≤|≥))(.*)\\z/'; while ($qword !== "") { if (preg_match('/\\A((?:[=!<>]=?|≠|≤|≥|)\\d+|any|none|yes|no)' . $tailre, $qword, $m)) { $count = self::_matchCompar($m[1], false); $count = $count[1]; $qword = $m[2]; } else { if (preg_match('/\\A(pri|primary|sec|secondary|ext|external)' . $tailre, $qword, $m)) { $rt = ReviewSearchMatcher::parse_review_type($m[1]); $qword = $m[2]; } else { if (preg_match('/\\A(complete|done|incomplete|in-?progress)' . $tailre, $qword, $m)) { if ($m[1] === "complete" || $m[1] === "done") { $completeness |= ReviewSearchMatcher::COMPLETE; } else { if ($m[1] === "incomplete") { $completeness |= ReviewSearchMatcher::INCOMPLETE; } else { $completeness |= ReviewSearchMatcher::INPROGRESS; } } $qword = $m[2]; } else { if (preg_match('/\\A(?:au)?words((?:[=!<>]=?|≠|≤|≥)\\d+)(?:\\z|:)(.*)\\z/', $qword, $m)) { $wordcount = new CountMatcher($m[1]); $qword = $m[2]; } else { if (preg_match('/\\A([A-Za-z0-9]+)' . $tailre, $qword, $m) && (($round = $Conf->round_number($m[1], false)) || $m[1] === "unnamed")) { if ($rounds === null) { $rounds = array(); } $rounds[] = $round; $qword = $m[2]; } else { if (preg_match('/\\A(..*?|"[^"]+(?:"|\\z))' . $tailre, $qword, $m)) { if ($quoted = $m[1][0] === "\"") { $m[1] = str_replace(array('"', '*'), array('', '\\*'), $m[1]); } $contacts = $m[1]; $qword = $m[2]; } else { $count = "<0"; break; } } } } } } } if ($qr = self::_tautology($count)) { $qr->set_float("used_revadj", true); $qt[] = $qr; return; } if ($completeness == 0 && $wordcount) { $completeness = ReviewSearchMatcher::COMPLETE; } if ($contacts) { $contacts = $this->_reviewerMatcher($contacts, $quoted, $rt >= REVIEW_PC); } $value = new ReviewSearchMatcher($count, $contacts); $value->review_type = $rt; $value->completeness = $completeness; $value->round = $rounds; $value->wordcountexpr = $wordcount; $qt[] = new SearchTerm("re", self::F_XVIEW, $value); }
private function _parse_expr(&$t, $level, $in_qc) { global $Conf; if (($t = ltrim($t)) === "") { return null; } $lpos = -strlen($t); $e = null; if ($t[0] === "(") { $t = substr($t, 1); $e = $this->_parse_ternary($t, false); $t = ltrim($t); if (!$e || $t === "" || $t[0] !== ")") { return null; } $t = substr($t, 1); } else { if ($t[0] === "-" || $t[0] === "+" || $t[0] === "!") { $op = $t[0]; $t = substr($t, 1); if (!($e = $this->_parse_expr($t, self::$opprec["u{$op}"], $in_qc))) { return null; } $e = $op == "!" ? new NegateFexpr($e) : new Fexpr($op, $e); } else { if (preg_match('/\\Aopt(?:ion)?:\\s*(.*)\\z/s', $t, $m)) { $rest = self::_pop_argument($m[1]); $os = PaperSearch::analyze_option_search($rest[1]); foreach ($os->warn as $w) { $this->_error_html[] = $w; } if (!count($os->os) && !count($os->warn)) { $this->_error_html[] = "“" . htmlspecialchars($rest[1]) . "” doesn’t match a submission option."; } if (!count($os->os)) { return null; } foreach ($os->os as $o) { $ex = new OptionFexpr($o->option); if ($o->kind) { $this->_error_html[] = "“" . htmlspecialchars($rest[1]) . "” can’t be used in formulas."; } else { if ($o->value_word === "") { /* stick with raw option fexpr */ } else { if (is_array($o->value) && $o->compar === "!=") { $ex = new NegateFexpr(new InFexpr($ex, $o->value)); } else { if (is_array($o->value)) { $ex = new InFexpr($ex, $o->value); } else { $ex = new Fexpr(get(self::$_oprewrite, $o->compar, $o->compar), $ex, new ConstantFexpr($o->value, $o->option)); } } } } $e = $e ? new Fexpr("||", $e, $ex) : $ex; } if ($os->negate) { $e = new NegateFexpr($e); } $t = $rest[2]; } else { if (preg_match('/\\Anot([\\s(].*|)\\z/i', $t, $m)) { $t = $m[1]; if (!($e = $this->_parse_expr($t, self::$opprec["u!"], $in_qc))) { return null; } $e = new NegateFexpr($e); } else { if (preg_match('/\\A(\\d+\\.?\\d*|\\.\\d+)(.*)\\z/s', $t, $m)) { $e = new ConstantFexpr($m[1] + 0.0); $t = $m[2]; } else { if (preg_match('/\\A(false|true)\\b(.*)\\z/si', $t, $m)) { $e = new ConstantFexpr($m[1], Fexpr::FBOOL); $t = $m[2]; } else { if (preg_match('/\\A(?:pid|paperid)\\b(.*)\\z/si', $t, $m)) { $e = new PidFexpr(); $t = $m[1]; } else { if (preg_match('/\\A(?:dec|decision):\\s*' . self::ARGUMENT_REGEX . '(.*)\\z/si', $t, $m)) { $e = $this->field_search_fexpr(["outcome", PaperSearch::matching_decisions($m[1])]); $t = $m[2]; } else { if (preg_match('/\\A(?:dec|decision)\\b(.*)\\z/si', $t, $m)) { $e = new DecisionFexpr(); $t = $m[1]; } else { if (preg_match('/\\A(?:is|status):\\s*' . self::ARGUMENT_REGEX . '(.*)\\z/si', $t, $m)) { $e = $this->field_search_fexpr(PaperSearch::status_field_matcher($m[1])); $t = $m[2]; } else { if (preg_match('/\\A(?:tag(?:\\s*:\\s*|\\s+)|#)(' . TAG_REGEX . ')(.*)\\z/is', $t, $m) || preg_match('/\\Atag\\s*\\(\\s*(' . TAG_REGEX . ')\\s*\\)(.*)\\z/is', $t, $m)) { $e = new TagFexpr($m[1], false); $t = $m[2]; } else { if (preg_match('/\\Atag(?:v|-?val|-?value)(?:\\s*:\\s*|\\s+)(' . TAG_REGEX . ')(.*)\\z/is', $t, $m) || preg_match('/\\Atag(?:v|-?val|-?value)\\s*\\(\\s*(' . TAG_REGEX . ')\\s*\\)(.*)\\z/is', $t, $m)) { $e = new TagFexpr($m[1], true); $t = $m[2]; } else { if (preg_match('/\\A(r|re|rev|review|r(?:|e|ev|eview)type|(?:|r|re|rev|review)round|reviewer|r(?:|e|ev|eview)(?:|au)words)(?::|(?=#))\\s*' . self::ARGUMENT_REGEX . '(.*)\\z/is', $t, $m)) { $e = $this->_reviewer_decoration($this->_reviewer_base($m[1]), $m[2]); $t = $m[3]; } else { if (preg_match('/\\A((?:r|re|rev|review)(?:type|round|(?:|au)words)|(?:round|reviewer))\\b(.*)\\z/is', $t, $m)) { $e = $this->_reviewer_base($m[1]); $t = $m[2]; } else { if (preg_match('/\\A(my|all|any|avg|average|mean|median|quantile|count|min|max|atminof|atmaxof|argmin|argmax|std(?:d?ev(?:_pop|_samp|[_.][ps])?)?|sum|var(?:iance)?(?:_pop|_samp|[_.][ps])?|wavg)\\b(.*)\\z/is', $t, $m)) { $t = $m[2]; if (!($e = $this->_parse_function($m[1], $t, true))) { return null; } } else { if (preg_match('/\\A(greatest|least|round|floor|trunc|ceil|log|sqrt|pow|exp)\\b(.*)\\z/is', $t, $m)) { $t = $m[2]; if (!($e = $this->_parse_function($m[1], $t, false))) { return null; } } else { if (preg_match('/\\Anull\\b(.*)\\z/s', $t, $m)) { $e = ConstantFexpr::cnull(); $t = $m[1]; } else { if (preg_match('/\\A(?:is:?)?(rev?|pc(?:rev?)?|pri(?:mary)?|sec(?:ondary)?|ext(?:ernal)?)\\b(.*)\\z/is', $t, $m)) { $rt = ReviewSearchMatcher::parse_review_type($m[1]); $op = $rt == 0 || $rt == REVIEW_PC ? ">=" : "=="; $e = new Fexpr($op, new RevtypeFexpr(), new ConstantFexpr($rt, Fexpr::FREVTYPE)); $t = $m[2]; } else { if (preg_match('/\\Atopicscore\\b(.*)\\z/is', $t, $m)) { $e = new TopicScoreFexpr(); $t = $m[1]; } else { if (preg_match('/\\Aconf(?:lict)?\\b(.*)\\z/is', $t, $m)) { $e = new ConflictFexpr(false); $t = $m[1]; } else { if (preg_match('/\\Apcconf(?:lict)?\\b(.*)\\z/is', $t, $m)) { $e = new ConflictFexpr(true); $t = $m[1]; } else { if (preg_match('/\\A(?:rev)?pref\\b(.*)\\z/is', $t, $m)) { $e = new PrefFexpr(false); $t = $m[1]; } else { if (preg_match('/\\A(?:rev)?prefexp(?:ertise)?\\b(.*)\\z/is', $t, $m)) { $e = new PrefFexpr(true); $t = $m[1]; } else { if (preg_match('/\\A([A-Za-z0-9_]+|\\".*?\\")(.*)\\z/s', $t, $m) && $m[1] !== "\"\"" && !preg_match('/\\A\\s*\\(/', $m[2])) { $field = $m[1]; $t = $m[2]; if ($quoted = $field[0] === "\"") { $field = substr($field, 1, strlen($field) - 2); } if (($f = ReviewForm::field_search($field)) && $f->has_options) { $e = new ScoreFexpr($f); } else { if (!$quoted) { $e = new ConstantFexpr($field, false); } else { return null; } } } } } } } } } } } } } } } } } } } } } } } } } } if (!$e) { return null; } $e->set_landmark($lpos, -strlen($t)); while (1) { if (($t = ltrim($t)) === "") { return $e; } else { if (preg_match(self::BINARY_OPERATOR_REGEX, $t, $m)) { $op = $m[0]; $tn = substr($t, strlen($m[0])); } else { if (preg_match('/\\A(and|or)([\\s(].*|)\\z/i', $t, $m)) { $op = strlen($m[1]) == 3 ? "&&" : "||"; $tn = $m[2]; } else { if (!$in_qc && substr($t, 0, 1) === ":") { $op = ":"; $tn = substr($t, 1); } else { return $e; } } } } $opprec = self::$opprec[$op]; if ($opprec < $level) { return $e; } $t = $tn; $op = get(self::$_oprewrite, $op) ?: $op; if (!($e2 = $this->_parse_expr($t, get(self::$_oprassoc, $op) ? $opprec : $opprec + 1, $in_qc))) { return null; } $e = new Fexpr($op, $e, $e2); $e->set_landmark($lpos, -strlen($t)); } }