Python pyparsing 模块,Combine() 实例源码
我们从Python开源项目中,提取了以下15个代码示例,用于说明如何使用pyparsing.Combine()。
def anything_beetween(opener_and_closer):
"""Builds a (pyparsing) parser for the content inside delimiters.
Args:
opener_and_closer: a string containing two elements: opener and closer
Returns:
A (pyparsing) parser for the content inside delimiters.
"""
opener = pyparsing.Literal(opener_and_closer[0])
closer = pyparsing.Literal(opener_and_closer[1])
char_removal_mapping = dict.fromkeys(map(ord, opener_and_closer))
other_chars = unicode(string.printable).translate(char_removal_mapping)
word_without_delimiters = pyparsing.Word(other_chars).setName(
"other_chars")
anything = pyparsing.Forward()
delimited_block = opener + anything + closer
# pylint: disable=expression-not-assigned
anything << pyparsing.ZeroOrMore(
word_without_delimiters.setName("word_without_delimiters")
| delimited_block.setName("delimited_block")
)
# Combine all the parts into a single string.
return pyparsing.Combine(anything)
def anything_beetween(opener_and_closer):
"""Builds a (pyparsing) parser for the content inside delimiters.
Args:
opener_and_closer: a string containing two elements: opener and closer
Returns:
A (pyparsing) parser for the content inside delimiters.
"""
opener = pyparsing.Literal(opener_and_closer[0])
closer = pyparsing.Literal(opener_and_closer[1])
char_removal_mapping = dict.fromkeys(map(ord, opener_and_closer))
other_chars = unicode(string.printable).translate(char_removal_mapping)
word_without_delimiters = pyparsing.Word(other_chars).setName(
"other_chars")
anything = pyparsing.Forward()
delimited_block = opener + anything + closer
# pylint: disable=expression-not-assigned
anything << pyparsing.ZeroOrMore(
word_without_delimiters.setName("word_without_delimiters")
| delimited_block.setName("delimited_block")
)
# Combine all the parts into a single string.
return pyparsing.Combine(anything)
def expression(self):
expression = pyparsing.Forward()
# (1 + (2 + 3))
nested_expression = pyparsing.nestedExpr(
"(", ")", expression).setParseAction(self._combine_lists)
# FOO(2,3)
function_call = (
_TOKEN().setResultsName("function")
+ _OPEN_PARENTHESIS()
+ pyparsing.delimitedList(
pyparsing.Combine(expression, adjacent=False, joinString=" "),
delim=",").setResultsName("func_args")
+ _CLOSE_PARENTHESIS()
)
expression << pyparsing.OneOrMore(
function_call.setParseAction(self._is_kNown_function)
| pyparsing.Group(nested_expression)
| _TOKEN()
| _NOT_TOKEN()
)
return pyparsing.Combine(expression, joinString=" ")
def parser(self):
# Define punctuation as suppressed literals.
lparen, rparen, lbrack, rbrack, lbrace, rbrace, colon = \
map(pp.Suppress, "()[]{}:")
integer = pp.Combine(pp.Optional(pp.oneOf("+ -")) + pp.Word(pp.nums)) \
.setName("integer") \
.setParseAction(lambda toks: int(toks[0]))
real = pp.Combine(pp.Optional(pp.oneOf("+ -")) + pp.Word(pp.nums) + "." +
pp.Optional(pp.Word(pp.nums)) +
pp.Optional(pp.oneOf("e E") + pp.Optional(pp.oneOf("+ -")) + pp.Word(pp.nums))) \
.setName("real") \
.setParseAction(lambda toks: float(toks[0]))
_datetime_arg = (integer | real)
datetime_args = pp.Group(pp.delimitedList(_datetime_arg))
_datetime = pp.Suppress(pp.Literal('datetime') + pp.Literal("(")) + datetime_args + pp.Suppress(")")
_datetime.setParseAction(lambda x: self._make_datetime(x[0]))
tuple_str = pp.Forward()
list_str = pp.Forward()
dict_str = pp.Forward()
list_item = real | integer | _datetime | pp.quotedString.setParseAction(pp.removeQuotes) | \
pp.Group(list_str) | tuple_str | dict_str
tuple_str << (pp.Suppress("(") + pp.Optional(pp.delimitedList(list_item)) +
pp.Optional(pp.Suppress(",")) + pp.Suppress(")"))
tuple_str.setParseAction(lambda toks : tuple(toks.asList()))
list_str << (lbrack + pp.Optional(pp.delimitedList(list_item) +
pp.Optional(pp.Suppress(","))) + rbrack)
dict_entry = pp.Group(list_item + colon + list_item)
dict_str << (lbrace + pp.Optional(pp.delimitedList(dict_entry) +
pp.Optional(pp.Suppress(","))) + rbrace)
dict_str.setParseAction(lambda toks: dict(toks.asList()))
return list_item
def number_parser():
point = pp.Literal(".")
e = pp.CaselessLiteral("e")
plusorminus = pp.Literal("+") ^ pp.Literal("-")
num = pp.Word(pp.nums)
dec = pp.Combine(num + pp.Optional(point + pp.Optional(num)) + pp.Optional(e + pp.Optional(plusorminus) + num)) ^\
pp.Combine(point + pp.Optional(num) + pp.Optional(e + pp.Optional(plusorminus) + num))
bin = pp.Combine(pp.Literal("0") + pp.CaselessLiteral("b") + pp.Word("01"))
hex = pp.Combine(pp.Literal("0") + pp.CaselessLiteral("x") + pp.Word(pp.hexnums))
oct = pp.Combine(pp.Literal("0") + pp.Optional(pp.CaselessLiteral("o")) + pp.Word("01234567"))
return dec ^ bin ^ hex ^ oct
def statement():
return pyparsing.Group(
_IDENTIFIER.setResultsName("lhs") + _EQUALS +
pyparsing.Combine(
(anything_in_curly() |
pyparsing.QuotedString("'", escChar="\\", unquoteResults=False) |
pyparsing.QuotedString("\"", unquoteResults=False) |
_REGEX) +
pyparsing.ZeroOrMore(_KEYWORD),
adjacent=False,
joinString=" ",
).setResultsName("rhs")
)
def _hexadecimal_as_string(self):
return pyparsing.Combine('0x' + pyparsing.Word(pyparsing.hexnums))
def parseTerms():
"""
expop :: '^'
multop :: '*' | '/'
addop :: '+' | '-'
integer :: ['+' | '-'] '0'..'9'+
atom :: PI | E | real | fn '(' expr ')' | '(' expr ')'
factor :: atom [ expop factor ]*
term :: factor [ multop factor ]*
expr :: term [ addop term ]*
"""
global terms
if not terms:
point = Literal( "." )
e = CaselessLiteral( "E" )
fnumber = Combine( Word( "+-"+nums, nums ) +
Optional( point + Optional( Word( nums ) ) ) +
Optional( e + Word( "+-"+nums, nums ) ) )
ident = Word(alphas, alphas+nums+"_$")
plus = Literal( "+" )
minus = Literal( "-" )
mult = Literal( "*" )
div = Literal( "/" )
lpar = Literal( "(" ).suppress()
rpar = Literal( ")" ).suppress()
addop = plus | minus
multop = mult | div
expop = Literal( "^" )
pi = CaselessLiteral( "PI" )
expr = Forward()
atom = (Optional("-") + ( pi | e | fnumber | ident + lpar + expr + rpar ).setParseAction( pushFirst ) | ( lpar + expr.suppress() + rpar )).setParseAction(pushUMinus)
# by defining exponentiation as "atom [ ^ factor ]..." instead of "atom [ ^ atom ]...",we get right-to-left exponents,instead of left-to-righ
# that is,2^3^2 = 2^(3^2),not (2^3)^2.
factor = Forward()
factor << atom + ZeroOrMore( ( expop + factor ).setParseAction( pushFirst ) )
term = factor + ZeroOrMore( ( multop + factor ).setParseAction( pushFirst ) )
expr << term + ZeroOrMore( ( addop + term ).setParseAction( pushFirst ) )
terms = expr
return terms
def grammar():
"""Define the query grammar.
Backus-Naur form (BNF) of the grammar::
<grammar> ::= <item> | <item> <and_or> <grammar>
<item> ::= [<neg>] <query-token> | [<neg>] "(" <grammar> ")"
<query-token> ::= <token> | <hosts>
<token> ::= <category>:<key> [<operator> <value>]
Given that the pyparsing library defines the grammar in a BNF-like style,for the details of the tokens not
specified above check directly the source code.
Returns:
pyparsing.ParserElement: the grammar parser.
"""
# Boolean operators
and_or = (pp.CaselessKeyword('and') | pp.CaselessKeyword('or'))('bool')
# 'neg' is used as label to allow the use of dot notation,'not' is a reserved word in Python
neg = pp.CaselessKeyword('not')('neg')
operator = pp.oneOf(OPERATORS, caseless=True)('operator') # Comparison operators
quoted_string = pp.quotedString.copy().addParseAction(pp.removeQuotes) # Both single and double quotes are allowed
# Parentheses
lpar = pp.Literal('(')('open_subgroup')
rpar = pp.Literal(')')('close_subgroup')
# Hosts selection: glob (*) and clustershell (,!&^[]) Syntaxes are allowed:
# i.e. host10[10-42].*.domain
hosts = quoted_string | (~(and_or | neg) + pp.Word(pp.alphanums + '-_.*,!&^[]'))
# Key-value token for allowed categories using the available comparison operators
# i.e. F:key = value
category = pp.oneOf(CATEGORIES, caseless=True)('category')
key = pp.Word(pp.alphanums + '-_.%@:')('key')
selector = pp.Combine(category + ':' + key) # i.e. F:key
# All printables characters except the parentheses that are part of this or the global grammar
all_but_par = ''.join([c for c in pp.printables if c not in ('(', ')', '{', '}')])
value = (quoted_string | pp.Word(all_but_par))('value')
token = selector + pp.Optional(operator + value)
# Final grammar,see the docstring for its BNF based on the tokens defined above
# Groups are used to split the parsed results for an easy access
full_grammar = pp.Forward()
item = pp.Group(pp.Optional(neg) + (token | hosts('hosts'))) | pp.Group(
pp.Optional(neg) + lpar + full_grammar + rpar)
full_grammar << item + pp.ZeroOrMore(pp.Group(and_or) + full_grammar) # pylint: disable=expression-not-assigned
return full_grammar
def grammar():
"""Define the query grammar.
Backus-Naur form (BNF) of the grammar::
<grammar> ::= "*" | <items>
<items> ::= <item> | <item> <whitespace> <items>
<item> ::= <key>:<value>
Given that the pyparsing library defines the grammar in a BNF-like style,for the details of the tokens not
specified above check directly the source code.
Returns:
pyparsing.ParserElement: the grammar parser.
"""
quoted_string = pp.quotedString.copy().addParseAction(pp.removeQuotes) # Both single and double quotes are allowed
# Key-value tokens: key:value
# Lowercase key,all printable characters except the parentheses that are part of the global grammar for the value
key = pp.Word(pp.srange('[a-z0-9-_.]"'), min=2)('key')
all_but_par = ''.join([c for c in pp.printables if c not in ('(', '}')])
value = (quoted_string | pp.Word(all_but_par))('value')
item = pp.Combine(key + ':' + value)
# Final grammar,see the docstring for its BNF based on the tokens defined above
# Groups are used to split the parsed results for an easy access
return pp.Group(pp.Literal('*')('all')) | pp.OneOrMore(pp.Group(item))
def grammar(backend_keys):
"""Define the main multi-query grammar.
Cumin provides a user-friendly generic query language that allows to combine the results of subqueries for multiple
backends:
* Each query part can be composed with the others using boolean operators ``and``,``or``,``and not``,``xor``.
* Multiple query parts can be grouped together with parentheses ``(``,``)``.
* Specific backend query ``I{backend-specific query Syntax}``,where ``I`` is an identifier for the specific
backend.
* Alias replacement,according to aliases defined in the configuration file ``A:group1``.
* The identifier ``A`` is reserved for the aliases replacement and cannot be used to identify a backend.
* A complex query example: ``(D{host1 or host2} and (P{R:Class = Role::MyClass} and not A:group1)) or D{host3}``
Backus-Naur form (BNF) of the grammar::
<grammar> ::= <item> | <item> <boolean> <grammar>
<item> ::= <backend_query> | <alias> | "(" <grammar> ")"
<backend_query> ::= <backend> "{" <query> "}"
<alias> ::= A:<alias_name>
<boolean> ::= "and not" | "and" | "xor" | "or"
Given that the pyparsing library defines the grammar in a BNF-like style,for the details of the tokens not
specified above check directly the source code.
Arguments:
backend_keys (list): list of the GRAMMAR_PREFIX for each registered backend.
Returns:
pyparsing.ParserElement: the grammar parser.
"""
# Boolean operators
boolean = (pp.CaselessKeyword('and not').leaveWhitespace() | pp.CaselessKeyword('and') |
pp.CaselessKeyword('xor') | pp.CaselessKeyword('or'))('bool')
# Parentheses
lpar = pp.Literal('(')('open_subgroup')
rpar = pp.Literal(')')('close_subgroup')
# Backend query: P{PuppetDB specific query}
query_start = pp.Combine(pp.oneOf(backend_keys, caseless=True)('backend') + pp.Literal('{'))
query_end = pp.Literal('}')
# Allow the backend specific query to use the end_query token as well,as long as it's in a quoted string
# and fail if there is a query_start token before the first query_end is reached
query = pp.SkipTo(query_end, ignore=pp.quotedString, failOn=query_start)('query')
backend_query = pp.Combine(query_start + query + query_end)
# Alias
alias = pp.Combine(pp.CaselessKeyword('A') + ':' + pp.Word(pp.alphanums + '-_.+')('alias'))
# Final grammar,see the docstring for its BNF based on the tokens defined above
# Group are used to have an easy dictionary access to the parsed results
full_grammar = pp.Forward()
item = backend_query | alias | lpar + full_grammar + rpar
full_grammar << pp.Group(item) + pp.ZeroOrMore(pp.Group(boolean + item)) # pylint: disable=expression-not-assigned
return full_grammar
def parseSelector(selectorstring):
# *select = @attr1 | /tf1/@attr | @attr1//objtype
"""
def enumtype(*args,**kwargs): #s,l,t,selectortype=None):
print(args)
selectortype = kwargs['selectortype']
if selectortype is None or not isinstance(selectortype,str):
raise ValueError('enumtype requires a selectortype string but got a',type(selectortype))
return selectortype
"""
def attrtype():
return AttrSelector() # 'ATTRTYPE'
def fullpathtype():
return FullPathSelector() #'FULLPATH'
def attrbyobjtype():
return AttrByObjectSelector() #'ATTRBYOBJECT'
def attrexpr(selectorstring=None):
attrmatch = p.Combine(p.Literal('@').suppress() + p.Word(p.alphanums))
return attrmatch.searchString(selectorstring)[0][0]
def expr(selectorstring=None, returntype=False):
attrmatch = p.Combine(p.Literal('@').suppress() + p.Word(p.alphanums))
fullpathmatch = p.Combine(p.OneOrMore(p.Literal('/') + p.Word(p.alphanums))) + p.Literal(
'/').suppress() + p.Combine(p.Literal('@').suppress() + p.Word(p.alphanums))
attrbyobjmatch = p.Combine(p.Literal('@').suppress() + p.Word(p.alphanums)) + p.Literal('//').suppress() + p.Word(p.alphanums)
matchgroup = (fullpathmatch | attrbyobjmatch | attrmatch)
if returntype:
attrmatch.setParseAction(attrtype)
fullpathmatch.setParseAction(fullpathtype)
attrbyobjmatch.setParseAction(attrbyobjtype)
return matchgroup.parseString(selectorstring)
_selectorconfig = expr(selectorstring=selectorstring)
_selectortype = expr(selectorstring=selectorstring, returntype=True)
_selectorattr = attrexpr(selectorstring=selectorstring)
return {
'type': _selectortype[0],
'config': _selectorconfig[:2], #Todo unclear why [0] returns only a subset of the matches
'attribute': _selectorattr
}
def __init__(self, obj, config=str()):
def process(config):
pathexpr = p.Literal("'").suppress() + \
p.Optional(
p.Combine(
p.OneOrMore(p.Literal("/") + p.Word(p.alphanums)) + p.Literal("/").suppress()
)
).setResultsName('path') + \
p.Combine(
(p.Literal('@').suppress() | p.Literal('!').suppress()) +
p.Word(p.alphanums) +
p.Literal("'").suppress()
).setResultsName('attrib')
expr = p.Group(pathexpr).setResultsName('search')
match = expr.parseString(config)
_ret = []
if 'search' in match:
if 'path' in match['search']:
_ret.append(match['search']['path'])
if 'attrib' in match['search']:
_ret.append(match['search']['attrib'])
return _ret
super(Xattrib, self).__init__(obj, config=config, defer=True)
if self.config is None or len(self.config) < 1 or not isinstance(self.config, str):
raise ValueError('Xattrib plugin function requires a config string')
try:
_result = process("'%s'" % self.config)
if len(_result) == 2:
self.targetobject, self.targetattribute = _result
elif len(_result) == 1:
_config = getattr(obj, _result[0], None)
if _config is None:
raise ValueError('Xattrib plugin received an attribute name that does not exist')
# Todo len check only required for attributes,but not method plugins
if len(_config) > 1:
raise ValueError('Xattrib plugin received a attribute name that contains multiple values')
self.targetobject, self.targetattribute = process("'%s'" % _config[0])
else:
raise Exception()
except:
raise ValueError('An error occured when processing the search string for the Xattrib plugin function')
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。