Let us walk on the 3-isogeny graph
Loading...
Searching...
No Matches
pip._vendor.pyparsing.helpers Namespace Reference

Data Structures

class  OpAssoc
 

Functions

ParserElement counted_array (ParserElement expr, typing.Optional[ParserElement] int_expr=None, *typing.Optional[ParserElement] intExpr=None)
 
ParserElement match_previous_literal (ParserElement expr)
 
ParserElement match_previous_expr (ParserElement expr)
 
ParserElement one_of (Union[typing.Iterable[str], str] strs, bool caseless=False, bool use_regex=True, bool as_keyword=False, *bool useRegex=True, bool asKeyword=False)
 
ParserElement dict_of (ParserElement key, ParserElement value)
 
ParserElement original_text_for (ParserElement expr, bool as_string=True, *bool asString=True)
 
ParserElement ungroup (ParserElement expr)
 
ParserElement locatedExpr (ParserElement expr)
 
ParserElement nested_expr (Union[str, ParserElement] opener="(", Union[str, ParserElement] closer=")", typing.Optional[ParserElement] content=None, ParserElement ignore_expr=quoted_string(), *ParserElement ignoreExpr=quoted_string())
 
 _makeTags (tagStr, xml, suppress_LT=Suppress("<"), suppress_GT=Suppress(">"))
 
Tuple[ParserElement, ParserElementmake_html_tags (Union[str, ParserElement] tag_str)
 
Tuple[ParserElement, ParserElementmake_xml_tags (Union[str, ParserElement] tag_str)
 
 replace_html_entity (s, l, t)
 
ParserElement infix_notation (ParserElement base_expr, List[InfixNotationOperatorSpec] op_list, Union[str, ParserElement] lpar=Suppress("("), Union[str, ParserElement] rpar=Suppress(")"))
 
 indentedBlock (blockStatementExpr, indentStack, indent=True, backup_stacks=[])
 
ParserElement delimited_list (Union[str, ParserElement] expr, Union[str, ParserElement] delim=",", bool combine=False, typing.Optional[int] min=None, typing.Optional[int] max=None, *bool allow_trailing_delim=False)
 
 delimitedList ()
 
 delimited_list ()
 
 countedArray ()
 
 matchPreviousLiteral ()
 
 matchPreviousExpr ()
 
 oneOf ()
 
 dictOf ()
 
 originalTextFor ()
 
 nestedExpr ()
 
 makeHTMLTags ()
 
 makeXMLTags ()
 
 replaceHTMLEntity ()
 
 infixNotation ()
 

Variables

ParserElement any_open_tag
 
ParserElement any_close_tag
 
dict _htmlEntityMap = {k.rstrip(";"): v for k, v in html.entities.html5.items()}
 
 common_html_entity
 
 InfixNotationOperatorArgType
 
 InfixNotationOperatorSpec
 
 c_style_comment
 
 html_comment = Regex(r"<!--[\s\S]*?-->").set_name("HTML comment")
 
 rest_of_line = Regex(r".*").leave_whitespace().set_name("rest of line")
 
 dbl_slash_comment = Regex(r"//(?:\\\n|[^\n])*").set_name("// comment")
 
 cpp_style_comment
 
 java_style_comment = cpp_style_comment
 
 python_style_comment = Regex(r"#.*").set_name("Python style comment")
 
list _builtin_exprs
 
 opAssoc = OpAssoc
 
ParserElement anyOpenTag = any_open_tag
 
ParserElement anyCloseTag = any_close_tag
 
 commonHTMLEntity = common_html_entity
 
 cStyleComment = c_style_comment
 
 htmlComment = html_comment
 
 restOfLine = rest_of_line
 
 dblSlashComment = dbl_slash_comment
 
 cppStyleComment = cpp_style_comment
 
 javaStyleComment = java_style_comment
 
 pythonStyleComment = python_style_comment
 

Function Documentation

◆ _makeTags()

_makeTags (   tagStr,
  xml,
  suppress_LT = Suppress("<"),
  suppress_GT = Suppress(">") 
)
protected
Internal helper to construct opening and closing tag expressions, given a tag name

Definition at line 541 of file helpers.py.

541def _makeTags(tagStr, xml, suppress_LT=Suppress("<"), suppress_GT=Suppress(">")):
542 """Internal helper to construct opening and closing tag expressions, given a tag name"""
543 if isinstance(tagStr, str_type):
544 resname = tagStr
545 tagStr = Keyword(tagStr, caseless=not xml)
546 else:
547 resname = tagStr.name
548
549 tagAttrName = Word(alphas, alphanums + "_-:")
550 if xml:
551 tagAttrValue = dbl_quoted_string.copy().set_parse_action(remove_quotes)
552 openTag = (
553 suppress_LT
554 + tagStr("tag")
555 + Dict(ZeroOrMore(Group(tagAttrName + Suppress("=") + tagAttrValue)))
556 + Opt("/", default=[False])("empty").set_parse_action(
557 lambda s, l, t: t[0] == "/"
558 )
559 + suppress_GT
560 )
561 else:
562 tagAttrValue = quoted_string.copy().set_parse_action(remove_quotes) | Word(
563 printables, exclude_chars=">"
564 )
565 openTag = (
566 suppress_LT
567 + tagStr("tag")
568 + Dict(
569 ZeroOrMore(
570 Group(
571 tagAttrName.set_parse_action(lambda t: t[0].lower())
572 + Opt(Suppress("=") + tagAttrValue)
573 )
574 )
575 )
576 + Opt("/", default=[False])("empty").set_parse_action(
577 lambda s, l, t: t[0] == "/"
578 )
579 + suppress_GT
580 )
581 closeTag = Combine(Literal("</") + tagStr + ">", adjacent=False)
582
583 openTag.set_name("<%s>" % resname)
584 # add start<tagname> results name in parse action now that ungrouped names are not reported at two levels
586 lambda t: t.__setitem__(
587 "start" + "".join(resname.replace(":", " ").title().split()), t.copy()
588 )
589 )
590 closeTag = closeTag(
591 "end" + "".join(resname.replace(":", " ").title().split())
592 ).set_name("</%s>" % resname)
593 openTag.tag = resname
594 closeTag.tag = resname
595 openTag.tag_body = SkipTo(closeTag())
596 return openTag, closeTag
597
598
for i

References i.

Referenced by pip._vendor.pyparsing.helpers.make_html_tags(), and pip._vendor.pyparsing.helpers.make_xml_tags().

Here is the caller graph for this function:

◆ counted_array()

ParserElement counted_array ( ParserElement  expr,
typing.Optional[ParserElement]   int_expr = None,
*typing.Optional[ParserElement]   intExpr = None 
)
Helper to define a counted list of expressions.

This helper defines a pattern of the form::

    integer expr expr expr...

where the leading integer tells how many expr expressions follow.
The matched tokens returns the array of expr tokens as a list - the
leading count token is suppressed.

If ``int_expr`` is specified, it should be a pyparsing expression
that produces an integer value.

Example::

    counted_array(Word(alphas)).parse_string('2 ab cd ef')  # -> ['ab', 'cd']

    # in this parser, the leading integer value is given in binary,
    # '10' indicating that 2 values are in the array
    binary_constant = Word('01').set_parse_action(lambda t: int(t[0], 2))
    counted_array(Word(alphas), int_expr=binary_constant).parse_string('10 ab cd ef')  # -> ['ab', 'cd']

    # if other fields must be parsed after the count but before the
    # list items, give the fields results names and they will
    # be preserved in the returned ParseResults:
    count_with_metadata = integer + Word(alphas)("type")
    typed_array = counted_array(Word(alphanums), int_expr=count_with_metadata)("items")
    result = typed_array.parse_string("3 bool True True False")
    print(result.dump())

    # prints
    # ['True', 'True', 'False']
    # - items: ['True', 'True', 'False']
    # - type: 'bool'

Definition at line 20 of file helpers.py.

25) -> ParserElement:
26 """Helper to define a counted list of expressions.
27
28 This helper defines a pattern of the form::
29
30 integer expr expr expr...
31
32 where the leading integer tells how many expr expressions follow.
33 The matched tokens returns the array of expr tokens as a list - the
34 leading count token is suppressed.
35
36 If ``int_expr`` is specified, it should be a pyparsing expression
37 that produces an integer value.
38
39 Example::
40
41 counted_array(Word(alphas)).parse_string('2 ab cd ef') # -> ['ab', 'cd']
42
43 # in this parser, the leading integer value is given in binary,
44 # '10' indicating that 2 values are in the array
45 binary_constant = Word('01').set_parse_action(lambda t: int(t[0], 2))
46 counted_array(Word(alphas), int_expr=binary_constant).parse_string('10 ab cd ef') # -> ['ab', 'cd']
47
48 # if other fields must be parsed after the count but before the
49 # list items, give the fields results names and they will
50 # be preserved in the returned ParseResults:
51 count_with_metadata = integer + Word(alphas)("type")
52 typed_array = counted_array(Word(alphanums), int_expr=count_with_metadata)("items")
53 result = typed_array.parse_string("3 bool True True False")
54 print(result.dump())
55
56 # prints
57 # ['True', 'True', 'False']
58 # - items: ['True', 'True', 'False']
59 # - type: 'bool'
60 """
61 intExpr = intExpr or int_expr
62 array_expr = Forward()
63
64 def count_field_parse_action(s, l, t):
65 nonlocal array_expr
66 n = t[0]
67 array_expr <<= (expr * n) if n else Empty()
68 # clear list contents, but keep any named results
69 del t[:]
70
71 if intExpr is None:
72 intExpr = Word(nums).set_parse_action(lambda t: int(t[0]))
73 else:
74 intExpr = intExpr.copy()
75 intExpr.set_name("arrayLen")
76 intExpr.add_parse_action(count_field_parse_action, call_during_try=True)
77 return (intExpr + array_expr).set_name("(len) " + str(expr) + "...")
78
79

References i.

◆ countedArray()

countedArray ( )

Definition at line 1069 of file helpers.py.

1069def countedArray(): ...
1070
1071@replaced_by_pep8(match_previous_literal)

◆ delimited_list() [1/2]

delimited_list ( )

Definition at line 1066 of file helpers.py.

1066def delimited_list(): ...
1067
1068@replaced_by_pep8(counted_array)

◆ delimited_list() [2/2]

ParserElement delimited_list ( Union[str, ParserElement expr,
Union[str, ParserElement]   delim = ",",
bool   combine = False,
typing.Optional[int]   min = None,
typing.Optional[int]   max = None,
*bool   allow_trailing_delim = False 
)
(DEPRECATED - use :class:`DelimitedList` class)

Definition at line 1033 of file helpers.py.

1041) -> ParserElement:
1042 """(DEPRECATED - use :class:`DelimitedList` class)"""
1043 return DelimitedList(
1044 expr, delim, combine, min, max, allow_trailing_delim=allow_trailing_delim
1045 )
1046
1047
1048# pre-PEP8 compatible names
1049# fmt: off

References i.

◆ delimitedList()

delimitedList ( )

Definition at line 1063 of file helpers.py.

1063def delimitedList(): ...
1064
1065@replaced_by_pep8(DelimitedList)

◆ dict_of()

ParserElement dict_of ( ParserElement  key,
ParserElement  value 
)
Helper to easily and clearly define a dictionary by specifying
the respective patterns for the key and value.  Takes care of
defining the :class:`Dict`, :class:`ZeroOrMore`, and
:class:`Group` tokens in the proper order.  The key pattern
can include delimiting markers or punctuation, as long as they are
suppressed, thereby leaving the significant key text.  The value
pattern can include named results, so that the :class:`Dict` results
can include named token fields.

Example::

    text = "shape: SQUARE posn: upper left color: light blue texture: burlap"
    attr_expr = (label + Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join))
    print(attr_expr[1, ...].parse_string(text).dump())

    attr_label = label
    attr_value = Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join)

    # similar to Dict, but simpler call format
    result = dict_of(attr_label, attr_value).parse_string(text)
    print(result.dump())
    print(result['shape'])
    print(result.shape)  # object attribute access works too
    print(result.as_dict())

prints::

    [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']]
    - color: 'light blue'
    - posn: 'upper left'
    - shape: 'SQUARE'
    - texture: 'burlap'
    SQUARE
    SQUARE
    {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'}

Definition at line 275 of file helpers.py.

275def dict_of(key: ParserElement, value: ParserElement) -> ParserElement:
276 """Helper to easily and clearly define a dictionary by specifying
277 the respective patterns for the key and value. Takes care of
278 defining the :class:`Dict`, :class:`ZeroOrMore`, and
279 :class:`Group` tokens in the proper order. The key pattern
280 can include delimiting markers or punctuation, as long as they are
281 suppressed, thereby leaving the significant key text. The value
282 pattern can include named results, so that the :class:`Dict` results
283 can include named token fields.
284
285 Example::
286
287 text = "shape: SQUARE posn: upper left color: light blue texture: burlap"
288 attr_expr = (label + Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join))
289 print(attr_expr[1, ...].parse_string(text).dump())
290
291 attr_label = label
292 attr_value = Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join)
293
294 # similar to Dict, but simpler call format
295 result = dict_of(attr_label, attr_value).parse_string(text)
296 print(result.dump())
297 print(result['shape'])
298 print(result.shape) # object attribute access works too
299 print(result.as_dict())
300
301 prints::
302
303 [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']]
304 - color: 'light blue'
305 - posn: 'upper left'
306 - shape: 'SQUARE'
307 - texture: 'burlap'
308 SQUARE
309 SQUARE
310 {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'}
311 """
312 return Dict(OneOrMore(Group(key + value)))
313
314

◆ dictOf()

dictOf ( )

Definition at line 1081 of file helpers.py.

1081def dictOf(): ...
1082
1083@replaced_by_pep8(original_text_for)

◆ indentedBlock()

indentedBlock (   blockStatementExpr,
  indentStack,
  indent = True,
  backup_stacks = [] 
)
(DEPRECATED - use :class:`IndentedBlock` class instead)
Helper method for defining space-delimited indentation blocks,
such as those used to define block statements in Python source code.

Parameters:

- ``blockStatementExpr`` - expression defining syntax of statement that
  is repeated within the indented block
- ``indentStack`` - list created by caller to manage indentation stack
  (multiple ``statementWithIndentedBlock`` expressions within a single
  grammar should share a common ``indentStack``)
- ``indent`` - boolean indicating whether block must be indented beyond
  the current level; set to ``False`` for block of left-most statements
  (default= ``True``)

A valid block must contain at least one ``blockStatement``.

(Note that indentedBlock uses internal parse actions which make it
incompatible with packrat parsing.)

Example::

    data = '''
    def A(z):
      A1
      B = 100
      G = A2
      A2
      A3
    B
    def BB(a,b,c):
      BB1
      def BBA():
        bba1
        bba2
        bba3
    C
    D
    def spam(x,y):
         def eggs(z):
             pass
    '''


    indentStack = [1]
    stmt = Forward()

    identifier = Word(alphas, alphanums)
    funcDecl = ("def" + identifier + Group("(" + Opt(delimitedList(identifier)) + ")") + ":")
    func_body = indentedBlock(stmt, indentStack)
    funcDef = Group(funcDecl + func_body)

    rvalue = Forward()
    funcCall = Group(identifier + "(" + Opt(delimitedList(rvalue)) + ")")
    rvalue << (funcCall | identifier | Word(nums))
    assignment = Group(identifier + "=" + rvalue)
    stmt << (funcDef | assignment | identifier)

    module_body = stmt[1, ...]

    parseTree = module_body.parseString(data)
    parseTree.pprint()

prints::

    [['def',
      'A',
      ['(', 'z', ')'],
      ':',
      [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]],
     'B',
     ['def',
      'BB',
      ['(', 'a', 'b', 'c', ')'],
      ':',
      [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]],
     'C',
     'D',
     ['def',
      'spam',
      ['(', 'x', 'y', ')'],
      ':',
      [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]]

Definition at line 857 of file helpers.py.

857def indentedBlock(blockStatementExpr, indentStack, indent=True, backup_stacks=[]):
858 """
859 (DEPRECATED - use :class:`IndentedBlock` class instead)
860 Helper method for defining space-delimited indentation blocks,
861 such as those used to define block statements in Python source code.
862
863 Parameters:
864
865 - ``blockStatementExpr`` - expression defining syntax of statement that
866 is repeated within the indented block
867 - ``indentStack`` - list created by caller to manage indentation stack
868 (multiple ``statementWithIndentedBlock`` expressions within a single
869 grammar should share a common ``indentStack``)
870 - ``indent`` - boolean indicating whether block must be indented beyond
871 the current level; set to ``False`` for block of left-most statements
872 (default= ``True``)
873
874 A valid block must contain at least one ``blockStatement``.
875
876 (Note that indentedBlock uses internal parse actions which make it
877 incompatible with packrat parsing.)
878
879 Example::
880
881 data = '''
882 def A(z):
883 A1
884 B = 100
885 G = A2
886 A2
887 A3
888 B
889 def BB(a,b,c):
890 BB1
891 def BBA():
892 bba1
893 bba2
894 bba3
895 C
896 D
897 def spam(x,y):
898 def eggs(z):
899 pass
900 '''
901
902
903 indentStack = [1]
904 stmt = Forward()
905
906 identifier = Word(alphas, alphanums)
907 funcDecl = ("def" + identifier + Group("(" + Opt(delimitedList(identifier)) + ")") + ":")
908 func_body = indentedBlock(stmt, indentStack)
909 funcDef = Group(funcDecl + func_body)
910
911 rvalue = Forward()
912 funcCall = Group(identifier + "(" + Opt(delimitedList(rvalue)) + ")")
913 rvalue << (funcCall | identifier | Word(nums))
914 assignment = Group(identifier + "=" + rvalue)
915 stmt << (funcDef | assignment | identifier)
916
917 module_body = stmt[1, ...]
918
919 parseTree = module_body.parseString(data)
920 parseTree.pprint()
921
922 prints::
923
924 [['def',
925 'A',
926 ['(', 'z', ')'],
927 ':',
928 [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]],
929 'B',
930 ['def',
931 'BB',
932 ['(', 'a', 'b', 'c', ')'],
933 ':',
934 [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]],
935 'C',
936 'D',
937 ['def',
938 'spam',
939 ['(', 'x', 'y', ')'],
940 ':',
941 [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]]
942 """
943 backup_stacks.append(indentStack[:])
944
945 def reset_stack():
946 indentStack[:] = backup_stacks[-1]
947
948 def checkPeerIndent(s, l, t):
949 if l >= len(s):
950 return
951 curCol = col(l, s)
952 if curCol != indentStack[-1]:
953 if curCol > indentStack[-1]:
954 raise ParseException(s, l, "illegal nesting")
955 raise ParseException(s, l, "not a peer entry")
956
957 def checkSubIndent(s, l, t):
958 curCol = col(l, s)
959 if curCol > indentStack[-1]:
960 indentStack.append(curCol)
961 else:
962 raise ParseException(s, l, "not a subentry")
963
964 def checkUnindent(s, l, t):
965 if l >= len(s):
966 return
967 curCol = col(l, s)
968 if not (indentStack and curCol in indentStack):
969 raise ParseException(s, l, "not an unindent")
970 if curCol < indentStack[-1]:
972
973 NL = OneOrMore(LineEnd().set_whitespace_chars("\t ").suppress())
974 INDENT = (Empty() + Empty().set_parse_action(checkSubIndent)).set_name("INDENT")
975 PEER = Empty().set_parse_action(checkPeerIndent).set_name("")
976 UNDENT = Empty().set_parse_action(checkUnindent).set_name("UNINDENT")
977 if indent:
978 smExpr = Group(
979 Opt(NL)
980 + INDENT
981 + OneOrMore(PEER + Group(blockStatementExpr) + Opt(NL))
982 + UNDENT
983 )
984 else:
985 smExpr = Group(
986 Opt(NL)
987 + OneOrMore(PEER + Group(blockStatementExpr) + Opt(NL))
988 + Opt(UNDENT)
989 )
990
991 # add a parse action to remove backup_stack from list of backups
993 lambda: backup_stacks.pop(-1) and None if backup_stacks else None
994 )
995 smExpr.set_fail_action(lambda a, b, c, d: reset_stack())
996 blockStatementExpr.ignore(_bslash + LineEnd())
997 return smExpr.set_name("indented block")
998
999
1000# it's easy to get these comment structures wrong - they're very common, so may as well make them available

References i.

◆ infix_notation()

ParserElement infix_notation ( ParserElement  base_expr,
List[InfixNotationOperatorSpec op_list,
Union[str, ParserElement]   lpar = Suppress("("),
Union[str, ParserElement]   rpar = Suppress(")") 
)
Helper method for constructing grammars of expressions made up of
operators working in a precedence hierarchy.  Operators may be unary
or binary, left- or right-associative.  Parse actions can also be
attached to operator expressions. The generated parser will also
recognize the use of parentheses to override operator precedences
(see example below).

Note: if you define a deep operator list, you may see performance
issues when using infix_notation. See
:class:`ParserElement.enable_packrat` for a mechanism to potentially
improve your parser performance.

Parameters:

- ``base_expr`` - expression representing the most basic operand to
  be used in the expression
- ``op_list`` - list of tuples, one for each operator precedence level
  in the expression grammar; each tuple is of the form ``(op_expr,
  num_operands, right_left_assoc, (optional)parse_action)``, where:

  - ``op_expr`` is the pyparsing expression for the operator; may also
    be a string, which will be converted to a Literal; if ``num_operands``
    is 3, ``op_expr`` is a tuple of two expressions, for the two
    operators separating the 3 terms
  - ``num_operands`` is the number of terms for this operator (must be 1,
    2, or 3)
  - ``right_left_assoc`` is the indicator whether the operator is right
    or left associative, using the pyparsing-defined constants
    ``OpAssoc.RIGHT`` and ``OpAssoc.LEFT``.
  - ``parse_action`` is the parse action to be associated with
    expressions matching this operator expression (the parse action
    tuple member may be omitted); if the parse action is passed
    a tuple or list of functions, this is equivalent to calling
    ``set_parse_action(*fn)``
    (:class:`ParserElement.set_parse_action`)
- ``lpar`` - expression for matching left-parentheses; if passed as a
  str, then will be parsed as ``Suppress(lpar)``. If lpar is passed as
  an expression (such as ``Literal('(')``), then it will be kept in
  the parsed results, and grouped with them. (default= ``Suppress('(')``)
- ``rpar`` - expression for matching right-parentheses; if passed as a
  str, then will be parsed as ``Suppress(rpar)``. If rpar is passed as
  an expression (such as ``Literal(')')``), then it will be kept in
  the parsed results, and grouped with them. (default= ``Suppress(')')``)

Example::

    # simple example of four-function arithmetic with ints and
    # variable names
    integer = pyparsing_common.signed_integer
    varname = pyparsing_common.identifier

    arith_expr = infix_notation(integer | varname,
        [
        ('-', 1, OpAssoc.RIGHT),
        (one_of('* /'), 2, OpAssoc.LEFT),
        (one_of('+ -'), 2, OpAssoc.LEFT),
        ])

    arith_expr.run_tests('''
        5+3*6
        (5+3)*6
        -2--11
        ''', full_dump=False)

prints::

    5+3*6
    [[5, '+', [3, '*', 6]]]

    (5+3)*6
    [[[5, '+', 3], '*', 6]]

    (5+x)*y
    [[[5, '+', 'x'], '*', 'y']]

    -2--11
    [[['-', 2], '-', ['-', 11]]]

Definition at line 680 of file helpers.py.

685) -> ParserElement:
686 """Helper method for constructing grammars of expressions made up of
687 operators working in a precedence hierarchy. Operators may be unary
688 or binary, left- or right-associative. Parse actions can also be
689 attached to operator expressions. The generated parser will also
690 recognize the use of parentheses to override operator precedences
691 (see example below).
692
693 Note: if you define a deep operator list, you may see performance
694 issues when using infix_notation. See
695 :class:`ParserElement.enable_packrat` for a mechanism to potentially
696 improve your parser performance.
697
698 Parameters:
699
700 - ``base_expr`` - expression representing the most basic operand to
701 be used in the expression
702 - ``op_list`` - list of tuples, one for each operator precedence level
703 in the expression grammar; each tuple is of the form ``(op_expr,
704 num_operands, right_left_assoc, (optional)parse_action)``, where:
705
706 - ``op_expr`` is the pyparsing expression for the operator; may also
707 be a string, which will be converted to a Literal; if ``num_operands``
708 is 3, ``op_expr`` is a tuple of two expressions, for the two
709 operators separating the 3 terms
710 - ``num_operands`` is the number of terms for this operator (must be 1,
711 2, or 3)
712 - ``right_left_assoc`` is the indicator whether the operator is right
713 or left associative, using the pyparsing-defined constants
714 ``OpAssoc.RIGHT`` and ``OpAssoc.LEFT``.
715 - ``parse_action`` is the parse action to be associated with
716 expressions matching this operator expression (the parse action
717 tuple member may be omitted); if the parse action is passed
718 a tuple or list of functions, this is equivalent to calling
719 ``set_parse_action(*fn)``
720 (:class:`ParserElement.set_parse_action`)
721 - ``lpar`` - expression for matching left-parentheses; if passed as a
722 str, then will be parsed as ``Suppress(lpar)``. If lpar is passed as
723 an expression (such as ``Literal('(')``), then it will be kept in
724 the parsed results, and grouped with them. (default= ``Suppress('(')``)
725 - ``rpar`` - expression for matching right-parentheses; if passed as a
726 str, then will be parsed as ``Suppress(rpar)``. If rpar is passed as
727 an expression (such as ``Literal(')')``), then it will be kept in
728 the parsed results, and grouped with them. (default= ``Suppress(')')``)
729
730 Example::
731
732 # simple example of four-function arithmetic with ints and
733 # variable names
734 integer = pyparsing_common.signed_integer
735 varname = pyparsing_common.identifier
736
737 arith_expr = infix_notation(integer | varname,
738 [
739 ('-', 1, OpAssoc.RIGHT),
740 (one_of('* /'), 2, OpAssoc.LEFT),
741 (one_of('+ -'), 2, OpAssoc.LEFT),
742 ])
743
744 arith_expr.run_tests('''
745 5+3*6
746 (5+3)*6
747 -2--11
748 ''', full_dump=False)
749
750 prints::
751
752 5+3*6
753 [[5, '+', [3, '*', 6]]]
754
755 (5+3)*6
756 [[[5, '+', 3], '*', 6]]
757
758 (5+x)*y
759 [[[5, '+', 'x'], '*', 'y']]
760
761 -2--11
762 [[['-', 2], '-', ['-', 11]]]
763 """
764
765 # captive version of FollowedBy that does not do parse actions or capture results names
766 class _FB(FollowedBy):
767 def parseImpl(self, instring, loc, doActions=True):
768 self.expr.try_parse(instring, loc)
769 return loc, []
770
771 _FB.__name__ = "FollowedBy>"
772
773 ret = Forward()
774 if isinstance(lpar, str):
775 lpar = Suppress(lpar)
776 if isinstance(rpar, str):
777 rpar = Suppress(rpar)
778
779 # if lpar and rpar are not suppressed, wrap in group
780 if not (isinstance(rpar, Suppress) and isinstance(rpar, Suppress)):
781 lastExpr = base_expr | Group(lpar + ret + rpar)
782 else:
783 lastExpr = base_expr | (lpar + ret + rpar)
784
785 arity: int
786 rightLeftAssoc: opAssoc
787 pa: typing.Optional[ParseAction]
788 opExpr1: ParserElement
789 opExpr2: ParserElement
790 for i, operDef in enumerate(op_list):
791 opExpr, arity, rightLeftAssoc, pa = (operDef + (None,))[:4] # type: ignore[assignment]
792 if isinstance(opExpr, str_type):
793 opExpr = ParserElement._literalStringClass(opExpr)
794 opExpr = typing.cast(ParserElement, opExpr)
795 if arity == 3:
796 if not isinstance(opExpr, (tuple, list)) or len(opExpr) != 2:
797 raise ValueError(
798 "if numterms=3, opExpr must be a tuple or list of two expressions"
799 )
800 opExpr1, opExpr2 = opExpr
801 term_name = f"{opExpr1}{opExpr2} term"
802 else:
803 term_name = f"{opExpr} term"
804
805 if not 1 <= arity <= 3:
806 raise ValueError("operator must be unary (1), binary (2), or ternary (3)")
807
808 if rightLeftAssoc not in (OpAssoc.LEFT, OpAssoc.RIGHT):
809 raise ValueError("operator must indicate right or left associativity")
810
811 thisExpr: ParserElement = Forward().set_name(term_name)
812 thisExpr = typing.cast(Forward, thisExpr)
813 if rightLeftAssoc is OpAssoc.LEFT:
814 if arity == 1:
815 matchExpr = _FB(lastExpr + opExpr) + Group(lastExpr + opExpr[1, ...])
816 elif arity == 2:
817 if opExpr is not None:
818 matchExpr = _FB(lastExpr + opExpr + lastExpr) + Group(
819 lastExpr + (opExpr + lastExpr)[1, ...]
820 )
821 else:
822 matchExpr = _FB(lastExpr + lastExpr) + Group(lastExpr[2, ...])
823 elif arity == 3:
824 matchExpr = _FB(
825 lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr
826 ) + Group(lastExpr + OneOrMore(opExpr1 + lastExpr + opExpr2 + lastExpr))
827 elif rightLeftAssoc is OpAssoc.RIGHT:
828 if arity == 1:
829 # try to avoid LR with this extra test
830 if not isinstance(opExpr, Opt):
831 opExpr = Opt(opExpr)
832 matchExpr = _FB(opExpr.expr + thisExpr) + Group(opExpr + thisExpr)
833 elif arity == 2:
834 if opExpr is not None:
835 matchExpr = _FB(lastExpr + opExpr + thisExpr) + Group(
836 lastExpr + (opExpr + thisExpr)[1, ...]
837 )
838 else:
839 matchExpr = _FB(lastExpr + thisExpr) + Group(
840 lastExpr + thisExpr[1, ...]
841 )
842 elif arity == 3:
843 matchExpr = _FB(
844 lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr
845 ) + Group(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr)
846 if pa:
847 if isinstance(pa, (tuple, list)):
849 else:
851 thisExpr <<= (matchExpr | lastExpr).setName(term_name)
852 lastExpr = thisExpr
853 ret <<= lastExpr
854 return ret
855
856

References i.

◆ infixNotation()

infixNotation ( )

Definition at line 1099 of file helpers.py.

1099def infixNotation(): ...
1100# fmt: on

◆ locatedExpr()

ParserElement locatedExpr ( ParserElement  expr)
(DEPRECATED - future code should use the :class:`Located` class)
Helper to decorate a returned token with its starting and ending
locations in the input string.

This helper adds the following results names:

- ``locn_start`` - location where matched expression begins
- ``locn_end`` - location where matched expression ends
- ``value`` - the actual parsed results

Be careful if the input text contains ``<TAB>`` characters, you
may want to call :class:`ParserElement.parse_with_tabs`

Example::

    wd = Word(alphas)
    for match in locatedExpr(wd).search_string("ljsdf123lksdjjf123lkkjj1222"):
        print(match)

prints::

    [[0, 'ljsdf', 5]]
    [[8, 'lksdjjf', 15]]
    [[18, 'lkkjj', 23]]

Definition at line 375 of file helpers.py.

375def locatedExpr(expr: ParserElement) -> ParserElement:
376 """
377 (DEPRECATED - future code should use the :class:`Located` class)
378 Helper to decorate a returned token with its starting and ending
379 locations in the input string.
380
381 This helper adds the following results names:
382
383 - ``locn_start`` - location where matched expression begins
384 - ``locn_end`` - location where matched expression ends
385 - ``value`` - the actual parsed results
386
387 Be careful if the input text contains ``<TAB>`` characters, you
388 may want to call :class:`ParserElement.parse_with_tabs`
389
390 Example::
391
392 wd = Word(alphas)
393 for match in locatedExpr(wd).search_string("ljsdf123lksdjjf123lkkjj1222"):
394 print(match)
395
396 prints::
397
398 [[0, 'ljsdf', 5]]
399 [[8, 'lksdjjf', 15]]
400 [[18, 'lkkjj', 23]]
401 """
402 locator = Empty().set_parse_action(lambda ss, ll, tt: ll)
403 return Group(
404 locator("locn_start")
405 + expr("value")
406 + locator.copy().leaveWhitespace()("locn_end")
407 )
408
409

References i.

◆ make_html_tags()

Tuple[ParserElement, ParserElement] make_html_tags ( Union[str, ParserElement]   tag_str)
Helper to construct opening and closing tag expressions for HTML,
given a tag name. Matches tags in either upper or lower case,
attributes with namespaces and with quoted or unquoted values.

Example::

    text = '<td>More info at the <a href="https://github.com/pyparsing/pyparsing/wiki">pyparsing</a> wiki page</td>'
    # make_html_tags returns pyparsing expressions for the opening and
    # closing tags as a 2-tuple
    a, a_end = make_html_tags("A")
    link_expr = a + SkipTo(a_end)("link_text") + a_end

    for link in link_expr.search_string(text):
        # attributes in the <A> tag (like "href" shown here) are
        # also accessible as named results
        print(link.link_text, '->', link.href)

prints::

    pyparsing -> https://github.com/pyparsing/pyparsing/wiki

Definition at line 599 of file helpers.py.

601) -> Tuple[ParserElement, ParserElement]:
602 """Helper to construct opening and closing tag expressions for HTML,
603 given a tag name. Matches tags in either upper or lower case,
604 attributes with namespaces and with quoted or unquoted values.
605
606 Example::
607
608 text = '<td>More info at the <a href="https://github.com/pyparsing/pyparsing/wiki">pyparsing</a> wiki page</td>'
609 # make_html_tags returns pyparsing expressions for the opening and
610 # closing tags as a 2-tuple
611 a, a_end = make_html_tags("A")
612 link_expr = a + SkipTo(a_end)("link_text") + a_end
613
614 for link in link_expr.search_string(text):
615 # attributes in the <A> tag (like "href" shown here) are
616 # also accessible as named results
617 print(link.link_text, '->', link.href)
618
619 prints::
620
621 pyparsing -> https://github.com/pyparsing/pyparsing/wiki
622 """
623 return _makeTags(tag_str, False)
624
625

References pip._vendor.pyparsing.helpers._makeTags().

Here is the call graph for this function:

◆ make_xml_tags()

Tuple[ParserElement, ParserElement] make_xml_tags ( Union[str, ParserElement]   tag_str)
Helper to construct opening and closing tag expressions for XML,
given a tag name. Matches tags only in the given upper/lower case.

Example: similar to :class:`make_html_tags`

Definition at line 626 of file helpers.py.

628) -> Tuple[ParserElement, ParserElement]:
629 """Helper to construct opening and closing tag expressions for XML,
630 given a tag name. Matches tags only in the given upper/lower case.
631
632 Example: similar to :class:`make_html_tags`
633 """
634 return _makeTags(tag_str, True)
635
636

References pip._vendor.pyparsing.helpers._makeTags().

Here is the call graph for this function:

◆ makeHTMLTags()

makeHTMLTags ( )

Definition at line 1090 of file helpers.py.

1090def makeHTMLTags(): ...
1091
1092@replaced_by_pep8(make_xml_tags)

◆ makeXMLTags()

makeXMLTags ( )

Definition at line 1093 of file helpers.py.

1093def makeXMLTags(): ...
1094
1095@replaced_by_pep8(replace_html_entity)

◆ match_previous_expr()

ParserElement match_previous_expr ( ParserElement  expr)
Helper to define an expression that is indirectly defined from
the tokens matched in a previous expression, that is, it looks for
a 'repeat' of a previous expression.  For example::

    first = Word(nums)
    second = match_previous_expr(first)
    match_expr = first + ":" + second

will match ``"1:1"``, but not ``"1:2"``.  Because this
matches by expressions, will *not* match the leading ``"1:1"``
in ``"1:10"``; the expressions are evaluated first, and then
compared, so ``"1"`` is compared with ``"10"``. Do *not* use
with packrat parsing enabled.

Definition at line 113 of file helpers.py.

113def match_previous_expr(expr: ParserElement) -> ParserElement:
114 """Helper to define an expression that is indirectly defined from
115 the tokens matched in a previous expression, that is, it looks for
116 a 'repeat' of a previous expression. For example::
117
118 first = Word(nums)
119 second = match_previous_expr(first)
120 match_expr = first + ":" + second
121
122 will match ``"1:1"``, but not ``"1:2"``. Because this
123 matches by expressions, will *not* match the leading ``"1:1"``
124 in ``"1:10"``; the expressions are evaluated first, and then
125 compared, so ``"1"`` is compared with ``"10"``. Do *not* use
126 with packrat parsing enabled.
127 """
128 rep = Forward()
129 e2 = expr.copy()
130 rep <<= e2
131
132 def copy_token_to_repeater(s, l, t):
133 matchTokens = _flatten(t.as_list())
134
135 def must_match_these_tokens(s, l, t):
136 theseTokens = _flatten(t.as_list())
137 if theseTokens != matchTokens:
138 raise ParseException(
139 s, l, f"Expected {matchTokens}, found{theseTokens}"
140 )
141
142 rep.set_parse_action(must_match_these_tokens, callDuringTry=True)
143
144 expr.add_parse_action(copy_token_to_repeater, callDuringTry=True)
145 rep.set_name("(prev) " + str(expr))
146 return rep
147
148

References i.

◆ match_previous_literal()

ParserElement match_previous_literal ( ParserElement  expr)
Helper to define an expression that is indirectly defined from
the tokens matched in a previous expression, that is, it looks for
a 'repeat' of a previous expression.  For example::

    first = Word(nums)
    second = match_previous_literal(first)
    match_expr = first + ":" + second

will match ``"1:1"``, but not ``"1:2"``.  Because this
matches a previous literal, will also match the leading
``"1:1"`` in ``"1:10"``. If this is not desired, use
:class:`match_previous_expr`. Do *not* use with packrat parsing
enabled.

Definition at line 80 of file helpers.py.

80def match_previous_literal(expr: ParserElement) -> ParserElement:
81 """Helper to define an expression that is indirectly defined from
82 the tokens matched in a previous expression, that is, it looks for
83 a 'repeat' of a previous expression. For example::
84
85 first = Word(nums)
86 second = match_previous_literal(first)
87 match_expr = first + ":" + second
88
89 will match ``"1:1"``, but not ``"1:2"``. Because this
90 matches a previous literal, will also match the leading
91 ``"1:1"`` in ``"1:10"``. If this is not desired, use
92 :class:`match_previous_expr`. Do *not* use with packrat parsing
93 enabled.
94 """
95 rep = Forward()
96
97 def copy_token_to_repeater(s, l, t):
98 if t:
99 if len(t) == 1:
100 rep << t[0]
101 else:
102 # flatten t tokens
103 tflat = _flatten(t.as_list())
104 rep << And(Literal(tt) for tt in tflat)
105 else:
106 rep << Empty()
107
108 expr.add_parse_action(copy_token_to_repeater, callDuringTry=True)
109 rep.set_name("(prev) " + str(expr))
110 return rep
111
112

References i.

◆ matchPreviousExpr()

matchPreviousExpr ( )

Definition at line 1075 of file helpers.py.

1075def matchPreviousExpr(): ...
1076
1077@replaced_by_pep8(one_of)

◆ matchPreviousLiteral()

matchPreviousLiteral ( )

Definition at line 1072 of file helpers.py.

1072def matchPreviousLiteral(): ...
1073
1074@replaced_by_pep8(match_previous_expr)

◆ nested_expr()

ParserElement nested_expr ( Union[str, ParserElement]   opener = "(",
Union[str, ParserElement]   closer = ")",
typing.Optional[ParserElement]   content = None,
ParserElement   ignore_expr = quoted_string(),
*ParserElement   ignoreExpr = quoted_string() 
)
Helper method for defining nested lists enclosed in opening and
closing delimiters (``"("`` and ``")"`` are the default).

Parameters:

- ``opener`` - opening character for a nested list
  (default= ``"("``); can also be a pyparsing expression
- ``closer`` - closing character for a nested list
  (default= ``")"``); can also be a pyparsing expression
- ``content`` - expression for items within the nested lists
  (default= ``None``)
- ``ignore_expr`` - expression for ignoring opening and closing delimiters
  (default= :class:`quoted_string`)
- ``ignoreExpr`` - this pre-PEP8 argument is retained for compatibility
  but will be removed in a future release

If an expression is not provided for the content argument, the
nested expression will capture all whitespace-delimited content
between delimiters as a list of separate values.

Use the ``ignore_expr`` argument to define expressions that may
contain opening or closing characters that should not be treated as
opening or closing characters for nesting, such as quoted_string or
a comment expression.  Specify multiple expressions using an
:class:`Or` or :class:`MatchFirst`. The default is
:class:`quoted_string`, but if no expressions are to be ignored, then
pass ``None`` for this argument.

Example::

    data_type = one_of("void int short long char float double")
    decl_data_type = Combine(data_type + Opt(Word('*')))
    ident = Word(alphas+'_', alphanums+'_')
    number = pyparsing_common.number
    arg = Group(decl_data_type + ident)
    LPAR, RPAR = map(Suppress, "()")

    code_body = nested_expr('{', '}', ignore_expr=(quoted_string | c_style_comment))

    c_function = (decl_data_type("type")
                  + ident("name")
                  + LPAR + Opt(DelimitedList(arg), [])("args") + RPAR
                  + code_body("body"))
    c_function.ignore(c_style_comment)

    source_code = '''
        int is_odd(int x) {
            return (x%2);
        }

        int dec_to_hex(char hchar) {
            if (hchar >= '0' && hchar <= '9') {
                return (ord(hchar)-ord('0'));
            } else {
                return (10+ord(hchar)-ord('A'));
            }
        }
    '''
    for func in c_function.search_string(source_code):
        print("%(name)s (%(type)s) args: %(args)s" % func)


prints::

    is_odd (int) args: [['int', 'x']]
    dec_to_hex (int) args: [['char', 'hchar']]

Definition at line 410 of file helpers.py.

417) -> ParserElement:
418 """Helper method for defining nested lists enclosed in opening and
419 closing delimiters (``"("`` and ``")"`` are the default).
420
421 Parameters:
422
423 - ``opener`` - opening character for a nested list
424 (default= ``"("``); can also be a pyparsing expression
425 - ``closer`` - closing character for a nested list
426 (default= ``")"``); can also be a pyparsing expression
427 - ``content`` - expression for items within the nested lists
428 (default= ``None``)
429 - ``ignore_expr`` - expression for ignoring opening and closing delimiters
430 (default= :class:`quoted_string`)
431 - ``ignoreExpr`` - this pre-PEP8 argument is retained for compatibility
432 but will be removed in a future release
433
434 If an expression is not provided for the content argument, the
435 nested expression will capture all whitespace-delimited content
436 between delimiters as a list of separate values.
437
438 Use the ``ignore_expr`` argument to define expressions that may
439 contain opening or closing characters that should not be treated as
440 opening or closing characters for nesting, such as quoted_string or
441 a comment expression. Specify multiple expressions using an
442 :class:`Or` or :class:`MatchFirst`. The default is
443 :class:`quoted_string`, but if no expressions are to be ignored, then
444 pass ``None`` for this argument.
445
446 Example::
447
448 data_type = one_of("void int short long char float double")
449 decl_data_type = Combine(data_type + Opt(Word('*')))
450 ident = Word(alphas+'_', alphanums+'_')
451 number = pyparsing_common.number
452 arg = Group(decl_data_type + ident)
453 LPAR, RPAR = map(Suppress, "()")
454
455 code_body = nested_expr('{', '}', ignore_expr=(quoted_string | c_style_comment))
456
457 c_function = (decl_data_type("type")
458 + ident("name")
459 + LPAR + Opt(DelimitedList(arg), [])("args") + RPAR
460 + code_body("body"))
461 c_function.ignore(c_style_comment)
462
463 source_code = '''
464 int is_odd(int x) {
465 return (x%2);
466 }
467
468 int dec_to_hex(char hchar) {
469 if (hchar >= '0' && hchar <= '9') {
470 return (ord(hchar)-ord('0'));
471 } else {
472 return (10+ord(hchar)-ord('A'));
473 }
474 }
475 '''
476 for func in c_function.search_string(source_code):
477 print("%(name)s (%(type)s) args: %(args)s" % func)
478
479
480 prints::
481
482 is_odd (int) args: [['int', 'x']]
483 dec_to_hex (int) args: [['char', 'hchar']]
484 """
485 if ignoreExpr != ignore_expr:
486 ignoreExpr = ignore_expr if ignoreExpr == quoted_string() else ignoreExpr
487 if opener == closer:
488 raise ValueError("opening and closing strings cannot be the same")
489 if content is None:
490 if isinstance(opener, str_type) and isinstance(closer, str_type):
491 opener = typing.cast(str, opener)
492 closer = typing.cast(str, closer)
493 if len(opener) == 1 and len(closer) == 1:
494 if ignoreExpr is not None:
495 content = Combine(
496 OneOrMore(
497 ~ignoreExpr
498 + CharsNotIn(
499 opener + closer + ParserElement.DEFAULT_WHITE_CHARS,
500 exact=1,
501 )
502 )
503 ).set_parse_action(lambda t: t[0].strip())
504 else:
505 content = empty.copy() + CharsNotIn(
506 opener + closer + ParserElement.DEFAULT_WHITE_CHARS
507 ).set_parse_action(lambda t: t[0].strip())
508 else:
509 if ignoreExpr is not None:
510 content = Combine(
511 OneOrMore(
512 ~ignoreExpr
513 + ~Literal(opener)
514 + ~Literal(closer)
515 + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS, exact=1)
516 )
517 ).set_parse_action(lambda t: t[0].strip())
518 else:
519 content = Combine(
520 OneOrMore(
521 ~Literal(opener)
522 + ~Literal(closer)
523 + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS, exact=1)
524 )
525 ).set_parse_action(lambda t: t[0].strip())
526 else:
527 raise ValueError(
528 "opening and closing arguments must be strings if no content expression is given"
529 )
530 ret = Forward()
531 if ignoreExpr is not None:
532 ret <<= Group(
533 Suppress(opener) + ZeroOrMore(ignoreExpr | ret | content) + Suppress(closer)
534 )
535 else:
536 ret <<= Group(Suppress(opener) + ZeroOrMore(ret | content) + Suppress(closer))
537 ret.set_name("nested %s%s expression" % (opener, closer))
538 return ret
539
540

References i, and pip._vendor.pyparsing.core.quoted_string.

◆ nestedExpr()

nestedExpr ( )

Definition at line 1087 of file helpers.py.

1087def nestedExpr(): ...
1088
1089@replaced_by_pep8(make_html_tags)

◆ one_of()

ParserElement one_of ( Union[typing.Iterable[str], str]  strs,
bool   caseless = False,
bool   use_regex = True,
bool   as_keyword = False,
*bool   useRegex = True,
bool   asKeyword = False 
)
Helper to quickly define a set of alternative :class:`Literal` s,
and makes sure to do longest-first testing when there is a conflict,
regardless of the input order, but returns
a :class:`MatchFirst` for best performance.

Parameters:

- ``strs`` - a string of space-delimited literals, or a collection of
  string literals
- ``caseless`` - treat all literals as caseless - (default= ``False``)
- ``use_regex`` - as an optimization, will
  generate a :class:`Regex` object; otherwise, will generate
  a :class:`MatchFirst` object (if ``caseless=True`` or ``as_keyword=True``, or if
  creating a :class:`Regex` raises an exception) - (default= ``True``)
- ``as_keyword`` - enforce :class:`Keyword`-style matching on the
  generated expressions - (default= ``False``)
- ``asKeyword`` and ``useRegex`` are retained for pre-PEP8 compatibility,
  but will be removed in a future release

Example::

    comp_oper = one_of("< = > <= >= !=")
    var = Word(alphas)
    number = Word(nums)
    term = var | number
    comparison_expr = term + comp_oper + term
    print(comparison_expr.search_string("B = 12  AA=23 B<=AA AA>12"))

prints::

    [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']]

Definition at line 149 of file helpers.py.

157) -> ParserElement:
158 """Helper to quickly define a set of alternative :class:`Literal` s,
159 and makes sure to do longest-first testing when there is a conflict,
160 regardless of the input order, but returns
161 a :class:`MatchFirst` for best performance.
162
163 Parameters:
164
165 - ``strs`` - a string of space-delimited literals, or a collection of
166 string literals
167 - ``caseless`` - treat all literals as caseless - (default= ``False``)
168 - ``use_regex`` - as an optimization, will
169 generate a :class:`Regex` object; otherwise, will generate
170 a :class:`MatchFirst` object (if ``caseless=True`` or ``as_keyword=True``, or if
171 creating a :class:`Regex` raises an exception) - (default= ``True``)
172 - ``as_keyword`` - enforce :class:`Keyword`-style matching on the
173 generated expressions - (default= ``False``)
174 - ``asKeyword`` and ``useRegex`` are retained for pre-PEP8 compatibility,
175 but will be removed in a future release
176
177 Example::
178
179 comp_oper = one_of("< = > <= >= !=")
180 var = Word(alphas)
181 number = Word(nums)
182 term = var | number
183 comparison_expr = term + comp_oper + term
184 print(comparison_expr.search_string("B = 12 AA=23 B<=AA AA>12"))
185
186 prints::
187
188 [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']]
189 """
190 asKeyword = asKeyword or as_keyword
191 useRegex = useRegex and use_regex
192
193 if (
194 isinstance(caseless, str_type)
196 ):
198 "More than one string argument passed to one_of, pass"
199 " choices as a list or space-delimited string",
200 stacklevel=2,
201 )
202
203 if caseless:
204 isequal = lambda a, b: a.upper() == b.upper()
205 masks = lambda a, b: b.upper().startswith(a.upper())
206 parseElementClass = CaselessKeyword if asKeyword else CaselessLiteral
207 else:
208 isequal = lambda a, b: a == b
209 masks = lambda a, b: b.startswith(a)
210 parseElementClass = Keyword if asKeyword else Literal
211
212 symbols: List[str] = []
213 if isinstance(strs, str_type):
214 strs = typing.cast(str, strs)
215 symbols = strs.split()
216 elif isinstance(strs, Iterable):
217 symbols = list(strs)
218 else:
219 raise TypeError("Invalid argument to one_of, expected string or iterable")
220 if not symbols:
221 return NoMatch()
222
223 # reorder given symbols to take care to avoid masking longer choices with shorter ones
224 # (but only if the given symbols are not just single characters)
225 if any(len(sym) > 1 for sym in symbols):
226 i = 0
227 while i < len(symbols) - 1:
228 cur = symbols[i]
229 for j, other in enumerate(symbols[i + 1 :]):
230 if isequal(other, cur):
231 del symbols[i + j + 1]
232 break
233 elif masks(cur, other):
234 del symbols[i + j + 1]
235 symbols.insert(i, other)
236 break
237 else:
238 i += 1
239
240 if useRegex:
241 re_flags: int = re.IGNORECASE if caseless else 0
242
243 try:
244 if all(len(sym) == 1 for sym in symbols):
245 # symbols are just single characters, create range regex pattern
246 patt = f"[{''.join(_escape_regex_range_chars(sym) for sym in symbols)}]"
247 else:
248 patt = "|".join(re.escape(sym) for sym in symbols)
249
250 # wrap with \b word break markers if defining as keywords
251 if asKeyword:
252 patt = rf"\b(?:{patt})\b"
253
254 ret = Regex(patt, flags=re_flags).set_name(" | ".join(symbols))
255
256 if caseless:
257 # add parse action to return symbols as specified, not in random
258 # casing as found in input string
259 symbol_map = {sym.lower(): sym for sym in symbols}
260 ret.add_parse_action(lambda s, l, t: symbol_map[t[0].lower()])
261
262 return ret
263
264 except re.error:
266 "Exception creating Regex for one_of, building MatchFirst", stacklevel=2
267 )
268
269 # last resort, just use MatchFirst
270 return MatchFirst(parseElementClass(sym) for sym in symbols).set_name(
271 " | ".join(symbols)
272 )
273
274

References i.

◆ oneOf()

oneOf ( )

Definition at line 1078 of file helpers.py.

1078def oneOf(): ...
1079
1080@replaced_by_pep8(dict_of)

◆ original_text_for()

ParserElement original_text_for ( ParserElement  expr,
bool   as_string = True,
*bool   asString = True 
)
Helper to return the original, untokenized text for a given
expression.  Useful to restore the parsed fields of an HTML start
tag into the raw tag text itself, or to revert separate tokens with
intervening whitespace back to the original matching input text. By
default, returns a string containing the original parsed text.

If the optional ``as_string`` argument is passed as
``False``, then the return value is
a :class:`ParseResults` containing any results names that
were originally matched, and a single token containing the original
matched text from the input string.  So if the expression passed to
:class:`original_text_for` contains expressions with defined
results names, you must set ``as_string`` to ``False`` if you
want to preserve those results name values.

The ``asString`` pre-PEP8 argument is retained for compatibility,
but will be removed in a future release.

Example::

    src = "this is test <b> bold <i>text</i> </b> normal text "
    for tag in ("b", "i"):
        opener, closer = make_html_tags(tag)
        patt = original_text_for(opener + ... + closer)
        print(patt.search_string(src)[0])

prints::

    ['<b> bold <i>text</i> </b>']
    ['<i>text</i>']

Definition at line 315 of file helpers.py.

317) -> ParserElement:
318 """Helper to return the original, untokenized text for a given
319 expression. Useful to restore the parsed fields of an HTML start
320 tag into the raw tag text itself, or to revert separate tokens with
321 intervening whitespace back to the original matching input text. By
322 default, returns a string containing the original parsed text.
323
324 If the optional ``as_string`` argument is passed as
325 ``False``, then the return value is
326 a :class:`ParseResults` containing any results names that
327 were originally matched, and a single token containing the original
328 matched text from the input string. So if the expression passed to
329 :class:`original_text_for` contains expressions with defined
330 results names, you must set ``as_string`` to ``False`` if you
331 want to preserve those results name values.
332
333 The ``asString`` pre-PEP8 argument is retained for compatibility,
334 but will be removed in a future release.
335
336 Example::
337
338 src = "this is test <b> bold <i>text</i> </b> normal text "
339 for tag in ("b", "i"):
340 opener, closer = make_html_tags(tag)
341 patt = original_text_for(opener + ... + closer)
342 print(patt.search_string(src)[0])
343
344 prints::
345
346 ['<b> bold <i>text</i> </b>']
347 ['<i>text</i>']
348 """
349 asString = asString and as_string
350
351 locMarker = Empty().set_parse_action(lambda s, loc, t: loc)
352 endlocMarker = locMarker.copy()
354 matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end")
355 if asString:
356 extractText = lambda s, l, t: s[t._original_start : t._original_end]
357 else:
358
359 def extractText(s, l, t):
360 t[:] = [s[t.pop("_original_start") : t.pop("_original_end")]]
361
362 matchExpr.set_parse_action(extractText)
365 return matchExpr
366
367

References i.

◆ originalTextFor()

originalTextFor ( )

Definition at line 1084 of file helpers.py.

1084def originalTextFor(): ...
1085
1086@replaced_by_pep8(nested_expr)

◆ replace_html_entity()

replace_html_entity (   s,
  l,
  t 
)
Helper parser action to replace common HTML entities with their special characters

Definition at line 649 of file helpers.py.

649def replace_html_entity(s, l, t):
650 """Helper parser action to replace common HTML entities with their special characters"""
652
653

References i.

◆ replaceHTMLEntity()

replaceHTMLEntity ( )

Definition at line 1096 of file helpers.py.

1096def replaceHTMLEntity(): ...
1097
1098@replaced_by_pep8(infix_notation)

◆ ungroup()

ParserElement ungroup ( ParserElement  expr)
Helper to undo pyparsing's default grouping of And expressions,
even if all but one are non-empty.

Definition at line 368 of file helpers.py.

368def ungroup(expr: ParserElement) -> ParserElement:
369 """Helper to undo pyparsing's default grouping of And expressions,
370 even if all but one are non-empty.
371 """
372 return TokenConverter(expr).add_parse_action(lambda t: t[0])
373
374

Variable Documentation

◆ _builtin_exprs

list _builtin_exprs
protected
Initial value:
1= [
2 v for v in vars().values() if isinstance(v, ParserElement)
3]

Definition at line 1027 of file helpers.py.

◆ _htmlEntityMap

dict _htmlEntityMap = {k.rstrip(";"): v for k, v in html.entities.html5.items()}
protected

Definition at line 643 of file helpers.py.

◆ any_close_tag

any_close_tag

Definition at line 638 of file helpers.py.

◆ any_open_tag

any_open_tag

Definition at line 637 of file helpers.py.

◆ anyCloseTag

Definition at line 1052 of file helpers.py.

◆ anyOpenTag

Definition at line 1051 of file helpers.py.

◆ c_style_comment

c_style_comment
Initial value:
1= Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + "*/").set_name(
2 "C style comment"
3)

Definition at line 1001 of file helpers.py.

◆ common_html_entity

common_html_entity
Initial value:
1= Regex("&(?P<entity>" + "|".join(_htmlEntityMap) + ");").set_name(
2 "common HTML entity"
3)

Definition at line 644 of file helpers.py.

◆ commonHTMLEntity

commonHTMLEntity = common_html_entity

Definition at line 1053 of file helpers.py.

◆ cpp_style_comment

cpp_style_comment
Initial value:
1= Combine(
2 Regex(r"/\*(?:[^*]|\*(?!/))*") + "*/" | dbl_slash_comment
3).set_name("C++ style comment")

Definition at line 1013 of file helpers.py.

◆ cppStyleComment

cppStyleComment = cpp_style_comment

Definition at line 1058 of file helpers.py.

◆ cStyleComment

cStyleComment = c_style_comment

Definition at line 1054 of file helpers.py.

◆ dbl_slash_comment

dbl_slash_comment = Regex(r"//(?:\\\n|[^\n])*").set_name("// comment")

Definition at line 1010 of file helpers.py.

◆ dblSlashComment

dblSlashComment = dbl_slash_comment

Definition at line 1057 of file helpers.py.

◆ html_comment

html_comment = Regex(r"<!--[\s\S]*?-->").set_name("HTML comment")

Definition at line 1006 of file helpers.py.

◆ htmlComment

htmlComment = html_comment

Definition at line 1055 of file helpers.py.

◆ InfixNotationOperatorArgType

InfixNotationOperatorArgType
Initial value:
1= Union[
2 ParserElement, str, Tuple[Union[ParserElement, str], Union[ParserElement, str]]
3]

Definition at line 662 of file helpers.py.

◆ InfixNotationOperatorSpec

InfixNotationOperatorSpec
Initial value:
1= Union[
2 Tuple[
3 InfixNotationOperatorArgType,
4 int,
5 OpAssoc,
6 typing.Optional[ParseAction],
7 ],
8 Tuple[
9 InfixNotationOperatorArgType,
10 int,
11 OpAssoc,
12 ],
13]

Definition at line 665 of file helpers.py.

◆ java_style_comment

java_style_comment = cpp_style_comment

Definition at line 1018 of file helpers.py.

◆ javaStyleComment

javaStyleComment = java_style_comment

Definition at line 1059 of file helpers.py.

◆ opAssoc

opAssoc = OpAssoc

Definition at line 1050 of file helpers.py.

◆ python_style_comment

python_style_comment = Regex(r"#.*").set_name("Python style comment")

Definition at line 1021 of file helpers.py.

◆ pythonStyleComment

pythonStyleComment = python_style_comment

Definition at line 1060 of file helpers.py.

◆ rest_of_line

rest_of_line = Regex(r".*").leave_whitespace().set_name("rest of line")

Definition at line 1009 of file helpers.py.

◆ restOfLine

restOfLine = rest_of_line

Definition at line 1056 of file helpers.py.