class SimpleValue(LeafRule): """Represents terminals as plaintext. E.g. title top cross section, or title Si-28(p(pol.), n(pol.)). """ class Whitespace(LeafRule): grammar = attr('value', whitespace) grammar = contiguous( SimpleValueUnit, maybe_some((optional(Whitespace), some(SimpleValueUnit)))) def __init__(self, values): super(SimpleValue, self).__init__() self.value = unicode.strip(''.join([v.value for v in values])) @classmethod def parse(cls, parser, text, pos): def unconsume_and_reconstruct_input(): """Reconstruct input in case of consuming a keyword query with ComplexValue as SimpleValue. Un-consuming 3 elements and specifically a Keyword, Whitespace and ComplexValue and then reconstructing parser's input text. Example: Given this query "author foo t 'bar'", r would be: r = [SimpleValueUnit("foo"), Whitespace(" "), SimpleValueUnit("t"), Whitespace(" "), SimpleValueUnit("'bar'")] thus after this method, r would be [SimpleValueUnit("foo"), Whitespace(" ")], while initial text will have been reconstructed as "t 'bar' rest_of_the_text". """ reconstructed_terminals = r[:idx - 2] remaining_text = ''.join([v.value for v in r[idx - 2:]]) + " " + t return remaining_text, reconstructed_terminals try: t, r = parser.parse(text, cls.grammar) # Covering a case of implicit-and when one of the SimpleValue tokens is a ComplexValue. # E.g. with the query "author foo t 'bar'", since 'bar' is a ComplexValue, then the previous token is a # keyword. This means we have consumed a KeywordQuery (due to 'and' missing). found_complex_value = False for idx, v in enumerate(r): if ComplexValue.regex.match(v.value): remaining_text, reconstructed_terminals = unconsume_and_reconstruct_input( r) found_complex_value = True break if found_complex_value: result = remaining_text, SimpleValue(reconstructed_terminals) else: result = t, SimpleValue(r) except SyntaxError as e: return text, e return result
class SimpleValue(LeafRule): """Represents terminals as plaintext. E.g. title top cross section, or title Si-28(p(pol.), n(pol.)). """ class Whitespace(LeafRule): grammar = attr('value', whitespace) grammar = contiguous([SimpleValueUnit, SimpleValueWithColonUnit], maybe_some( (optional(Whitespace), some(SimpleValueUnit)))) def __init__(self, values): super(SimpleValue, self).__init__() if isinstance(values, six.string_types): self.value = values else: self.value = six.text_type.strip(''.join([v.value for v in values])) @staticmethod def unconsume_and_reconstruct_input(remaining_text, recognized_tokens, complex_value_idx): """Reconstruct input in case of consuming a keyword query or a value query with ComplexValue as value. Un-consuming at most 3 elements and specifically (Keyword,) Whitespace and ComplexValue, while also reconstructing parser's input text. Example: Given this query "author foo t 'bar'", r would be: r = [SimpleValueUnit("foo"), Whitespace(" "), SimpleValueUnit("t"), Whitespace(" "), SimpleValueUnit("'bar'")] thus after this method, r would be [SimpleValueUnit("foo"), Whitespace(" ")], while initial text will have been reconstructed as "t 'bar' rest_of_the_text". """ # Default slicing index: i.e. at most 3 elements will be unconsumed, Keyword, Whitespace and ComplexValue. slicing_start_idx = 2 # Check whether the 3rd element from the end is an InspireKeyword. If not, a Value query with ComplexValue # was consumed. if not INSPIRE_PARSER_KEYWORDS.get( recognized_tokens[complex_value_idx - slicing_start_idx].value, None): slicing_start_idx = 1 reconstructed_terminals = recognized_tokens[:complex_value_idx - slicing_start_idx] reconstructed_text = '{} {}'.format( ''.join([ token.value for token in recognized_tokens[complex_value_idx - slicing_start_idx:] ]), remaining_text) return reconstructed_text, reconstructed_terminals @classmethod def parse(cls, parser, text, pos): try: remaining_text, recognized_tokens = parser.parse(text, cls.grammar) # Covering a case of implicit-and when one of the SimpleValue tokens is a ComplexValue. # This means we either have a KeywordQuery or a ValueQuery with a ComplexValue. # E.g. "author foo t 'bar'", since 'bar' is a ComplexValue, then the previous token is a keyword. # This means we have consumed a KeywordQuery (due to 'and' missing). # Same goes for "author foo 'bar'", but in this case we have a ValueQuery with a ComplexValue. found_complex_value = False for idx, token in enumerate(recognized_tokens): if ComplexValue.regex.match(token.value): reconstructed_text, reconstructed_terminals = cls.unconsume_and_reconstruct_input( remaining_text, recognized_tokens, idx) found_complex_value = True break if found_complex_value: result = reconstructed_text, SimpleValue( reconstructed_terminals) else: result = remaining_text, SimpleValue(recognized_tokens) except SyntaxError as e: return text, e return result
class ExtValue(peg.List): """An ext-value of an attribute (RFC 5987, Section 3.2).""" grammar = peg.contiguous(Charset, "'", peg.optional(Language), "'", ValueChars)
class ExcludedField(List): grammar = contiguous('-', name())
class ExcludedField(List): # Chỉ trừ đi field đc chọn grammar = contiguous('-', name())
class ConstHexInteger(_SingleValue): grammar = pypeg2.contiguous(['0x', '0X'], re.compile(r'[0-9a-fA-F]+')) def __init__(self, hex_str): super().__init__(int(hex_str, 16))
left = "({0})".format( parser.compose(self.left, grammar=grammar, attr_of=attr_of) ) else: left = parser.compose(self.left, grammar=grammar, attr_of=attr_of) if getattr(self, "op", None): if type(self.right) is Condition: right = "({0})".format( parser.compose(self.right, grammar=grammar, attr_of=attr_of) ) else: right = parser.compose(self.right, grammar=grammar, attr_of=attr_of) op = parser.compose(self.op, grammar=grammar, attr_of=attr_of) result = "{0} {1} {2}".format(left, op, right) else: result = left return result Condition.grammar = contiguous( attr("left", [SIG, XHX, CSV, CLTV, ("(", Condition, ")")]), maybe_some( whitespace, attr("op", Operator), whitespace, attr("right", [SIG, XHX, CSV, CLTV, ("(", Condition, ")")]), ), )
def compose(self, parser: Any, grammar: Any = None, attr_of: str = None) -> str: """ Return the Condition as string format :param parser: Parser instance :param grammar: Grammar :param attr_of: Attribute of... """ if type(self.left) is Condition: left = "({0})".format(parser.compose(self.left, grammar=grammar, attr_of=attr_of)) else: left = parser.compose(self.left, grammar=grammar, attr_of=attr_of) if getattr(self, 'op', None): if type(self.right) is Condition: right = "({0})".format(parser.compose(self.right, grammar=grammar, attr_of=attr_of)) else: right = parser.compose(self.right, grammar=grammar, attr_of=attr_of) op = parser.compose(self.op, grammar=grammar, attr_of=attr_of) result = "{0} {1} {2}".format(left, op, right) else: result = left return result Condition.grammar = contiguous(attr('left', [SIG, XHX, CSV, CLTV, ('(', Condition, ')')]), maybe_some(whitespace, attr('op', Operator), whitespace, attr('right', [SIG, XHX, CSV, CLTV, ('(', Condition, ')')])))
:param attr_of: Attribute of... """ if type(self.left) is Condition: left = "({0})".format( parser.compose(self.left, grammar=grammar, attr_of=attr_of)) else: left = parser.compose(self.left, grammar=grammar, attr_of=attr_of) if getattr(self, 'op', None): if type(self.right) is Condition: right = "({0})".format( parser.compose(self.right, grammar=grammar, attr_of=attr_of)) else: right = parser.compose(self.right, grammar=grammar, attr_of=attr_of) op = parser.compose(self.op, grammar=grammar, attr_of=attr_of) result = "{0} {1} {2}".format(left, op, right) else: result = left return result Condition.grammar = contiguous( attr('left', [SIG, XHX, CSV, CLTV, ('(', Condition, ')')]), maybe_some(whitespace, attr('op', Operator), whitespace, attr('right', [SIG, XHX, CSV, CLTV, ('(', Condition, ')')])))