Project import generated by Copybara.

GitOrigin-RevId: d9e9e3fb4e31372ec1fb43b178994ca78fa8fe70
diff --git a/proto/ast_pb2.py b/proto/ast_pb2.py
new file mode 100644
index 0000000..2b77ca9
--- /dev/null
+++ b/proto/ast_pb2.py
@@ -0,0 +1,111 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file or at
+# https://developers.google.com/open-source/licenses/bsd
+
+"""Protocol buffers for user queries parsed into abstract syntax trees.
+
+A user issue query can look like [Type=Defect owner:jrobbins "memory leak"].
+In that simple form, all the individual search conditions are simply ANDed
+together.  In the code, a list of conditions to be ANDed is called a
+conjunction.
+
+Monorail also supports a quick-or feature: [Type=Defect,Enhancement].  That
+will match any issue that has labels Type-Defect or Type-Enhancement, or both.
+
+Monorail supports a top-level "OR" keyword that can
+be used to logically OR a series of conjunctions.  For example:
+[Type=Defect stars>10 OR Type=Enhancement stars>50].
+
+Parentheses groups and "OR" statements are preprocessed before the final
+QueryAST is constructed.
+
+So, QueryAST is always exactly two levels:  the overall tree
+consists of a list of conjunctions, and each conjunction consists of a list
+of conditions.
+
+A condition can look like [stars>10] or [summary:memory] or
+[Type=Defect,Enhancement].  Each condition has a single comparison operator.
+Most conditions refer to a single field definition, but in the case of
+cross-project search a single condition can have a list of field definitions
+from the different projects being searched.  Each condition can have a list
+of constant values to compare against.  The values may be all strings or all
+integers.
+
+Some conditions are procesed by the SQL database and others by the GAE
+search API.  All conditions are passed to each module and it is up to
+the module to decide which conditions to handle and which to ignore.
+"""
+
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+
+from protorpc import messages
+
+from proto import tracker_pb2
+
+
+# This is a special field_name for a FieldDef that means to do a fulltext
+# search for words that occur in any part of the issue.
+ANY_FIELD = 'any_field'
+
+
+class QueryOp(messages.Enum):
+  """Enumeration of possible query condition operators."""
+  EQ = 1
+  NE = 2
+  LT = 3
+  GT = 4
+  LE = 5
+  GE = 6
+  TEXT_HAS = 7
+  NOT_TEXT_HAS = 8
+  IS_DEFINED = 11
+  IS_NOT_DEFINED = 12
+  KEY_HAS = 13
+
+
+class TokenType(messages.Enum):
+  """Enumeration of query tokens used for parentheses parsing."""
+  SUBQUERY = 1
+  LEFT_PAREN = 2
+  RIGHT_PAREN = 3
+  OR = 4
+
+
+class QueryToken(messages.Message):
+  """Data structure to represent a single token for parentheses parsing."""
+  token_type = messages.EnumField(TokenType, 1, required=True)
+  value = messages.StringField(2)
+
+
+class Condition(messages.Message):
+  """Representation of one query condition.  E.g., [Type=Defect,Task]."""
+  op = messages.EnumField(QueryOp, 1, required=True)
+  field_defs = messages.MessageField(tracker_pb2.FieldDef, 2, repeated=True)
+  str_values = messages.StringField(3, repeated=True)
+  int_values = messages.IntegerField(4, repeated=True)
+  # The suffix of a search field
+  # eg. the 'approver' in 'UXReview-approver:user@mail.com'
+  key_suffix = messages.StringField(5)
+  # The name of the phase this field value should belong to.
+  phase_name = messages.StringField(6)
+
+
+class Conjunction(messages.Message):
+  """A list of conditions that are implicitly ANDed together."""
+  conds = messages.MessageField(Condition, 1, repeated=True)
+
+
+class QueryAST(messages.Message):
+  """Abstract syntax tree for the user's query."""
+  conjunctions = messages.MessageField(Conjunction, 1, repeated=True)
+
+
+def MakeCond(op, field_defs, str_values, int_values,
+             key_suffix=None, phase_name=None):
+  """Shorthand function to construct a Condition PB."""
+  return Condition(
+      op=op, field_defs=field_defs, str_values=str_values,
+      int_values=int_values, key_suffix=key_suffix, phase_name=phase_name)