def expression_parser(): """A function returning a (pyparsing) parser for parsing C expressions. Returns: a (pyparsing) parser for parsing C expressions. """ precedence = [] for operators, arity, associativity in _PRECEDENCE: if arity <= 2: operators = pyparsing.Or(map(pyparsing.Literal, operators)) else: operators = tuple(map(pyparsing.Literal, operators)) precedence.append(( operators, arity, associativity, _construct_operator(arity), )) expression = pyparsing.Forward() # pylint: disable=expression-not-assigned expression << pyparsing.infixNotation( baseExpr=_base_or_array_expression(expression), opList=precedence, lpar=pyparsing.NoMatch(), rpar=pyparsing.NoMatch(), ) expression.ignore(pyparsing.cppStyleComment) return expression
def _make_matcher_element(self): # Handle the case where use_current_match is True. if self.use_current_match is True: current_match = self.current_match if current_match is None: result = pyparsing.NoMatch() elif current_match == "": result = pyparsing.Empty() else: result = pyparsing.Literal(self.current_match) # Set the element's attributes and return it. return self._set_matcher_element_attributes(result) # Otherwise build a list of next possible literals. Make the required stack # of child-parent pairs. stack = [] p1, p2 = self, self.parent while p1 and p2: stack.append((p1, p2)) # Move both pivots further up the tree. p1 = p1.parent p2 = p2.parent # Build a list of next literals using the stack. next_literals, _ = _collect_next_literals(stack, 0, True, False) # De-duplicate the list. next_literals = set(next_literals) word = pyparsing.Regex(_word_regex_str, re.UNICODE) if next_literals: # Check if there is a next dictation literal. If there is, only match # one word for this expansion. if _word_regex_str in next_literals: result = word # Otherwise build an element to match one or more words stopping on # any of the next literals so that they aren't matched as dictation. else: next_literals = list(map(pyparsing.Literal, next_literals)) result = pyparsing.OneOrMore( word, stopOn=pyparsing.Or(next_literals)) else: # Handle the case of no literals ahead by allowing one or more Unicode # words without restrictions. result = pyparsing.OneOrMore(word) return self._set_matcher_element_attributes(result)
def __init__(self, base_freq=440.0, amplitude=.5, max_gain=10., min_gain=-200., new_scale='C/a', clef='violin'): # an important constant value for the conversion of musical halt tone steps to frequency values # is the twelfth root of 2 self.__root__ = 1.0594630943592952645618252949463 # (2 ** (1 / 12)) # *** parser definitions *** # helper no_whites = pp.NotAny(pp.White()) tok_end = (pp.StringEnd() | pp.LineEnd()).suppress() # numbers real = pp.Combine( pp.Word(pp.nums) + pp.Optional(pp.Char(',.') + pp.Word(pp.nums))).setParseAction( lambda t: float(t[0].replace(',', '.'))) integer = (pp.Optional(pp.Literal('-')) + pp.Word(pp.nums)).setParseAction( lambda t: int(t[0] + t[1]) if len(t) > 1 else int(t[0])) # signs must_sign = pp.Char('+-').setParseAction(lambda t: float(t[0] + '1')) may_sign = pp.Optional(pp.Char('+-')).setParseAction( lambda t: float(t[0] + '1' if len(t) > 0 else '1')) # note value cents cent = (must_sign + no_whites + real).setParseAction(lambda t: t[0] * t[1] / 100) # helpers for the note name parser note_name_offset = { 'C': -9, 'D': -7, 'E': -5, 'F': -4, 'G': -2, 'A': 0, 'B': 2, } note_name = pp.Char('CDEFGABcdefgab').setParseAction( lambda t: note_name_offset[t[0] if t[0] in 'CDEFGAB' else t[0].upper()]) flat_sharp = pp.Char('#b').setParseAction(lambda t: 1 if t[0] == '#' else -1) octave = pp.Char('0123456789').setParseAction(lambda t: (int(t[0]) - 4) * 12) full_note = (note_name + no_whites + pp.Optional(pp.FollowedBy(flat_sharp) + flat_sharp) + no_whites + pp.FollowedBy(octave) + octave).setParseAction(lambda t: sum(t)) self.note_name_parser = ( full_note + pp.Optional(pp.White()).suppress() + pp.Optional(cent) + tok_end ).setParseAction(lambda t: float(sum(t))).setResultsName('note_value') # frequency parsers hertz = real + pp.Literal('Hz').suppress() self.frequency_parser = (hertz + tok_end).setParseAction( lambda t: float(t[0])).setResultsName('frequency') self.base_freq_parser = ( full_note + pp.Literal('=').suppress() + hertz + tok_end ).setParseAction(lambda t: t[1] * (1.0594630943592952645618252949463** -t[0])).setResultsName('base_freq') # parses a string like "sc -7:b" into a musical half tone step (using the MusicConverter.set method) sign = (pp.Keyword('##') | pp.Keyword('bb') | pp.Keyword('#') | pp.Keyword('b') | pp.Keyword('n') | pp.Keyword('_')) self.score_parser = (integer + pp.Literal(':').suppress() + sign + tok_end).setResultsName('notation') # amplitude parser self.amp_parser = ( real + pp.Literal('%').suppress() + tok_end ).setParseAction(lambda t: float(t[0])).setResultsName('amplitude') self.gain_parser = ( may_sign + real + pp.Literal('dB').suppress() + tok_end ).setParseAction(lambda t: float(t[0] * t[1])).setResultsName('gain') # clef parser self.clef_parser = (pp.Keyword('violin') | pp.Keyword('alto') | pp.Keyword('bass')).setResultsName('clef') # key parser key_token = pp.NoMatch() for key in self.keys: key_token = key_token | pp.Keyword(key) self.key_parser = (key_token).setResultsName('key') # complete parser self.input_parser = self.note_name_parser | \ self.frequency_parser | \ self.base_freq_parser | \ self.amp_parser | \ self.gain_parser | \ self.clef_parser | \ self.key_parser | \ self.score_parser # *** initializations *** self.__note_value__ = 0. self.__base_freq__ = 440. self.base_freq = base_freq self.key = new_scale self.__names__ = 'C D EF G A B' self.clef = clef self.__clef__ = 'violin' self.max_gain = max_gain self.min_gain = min_gain self.amplitude = amplitude
class BaseQuery(metaclass=ABCMeta): """Query abstract class. All backends query classes must inherit, directly or indirectly, from this one. """ grammar = pyparsing.NoMatch() # This grammar will never match. """:py:class:`pyparsing.ParserElement`: derived classes must define their own pyparsing grammar and set this class attribute accordingly.""" def __init__(self, config): """Query constructor. Arguments: config (dict): a dictionary with the parsed configuration file. """ self.config = config self.logger = logging.getLogger('.'.join( (self.__module__, self.__class__.__name__))) self.logger.trace('Backend %s created with config: %s', type(self).__name__, config) def execute(self, query_string): """Build and execute the query, return the NodeSet of FQDN hostnames that matches. Arguments: query_string (str): the query string to be parsed and executed. Returns: ClusterShell.NodeSet.NodeSet: with the FQDNs of the matching hosts. """ self._build(query_string) return self._execute() @abstractmethod def _execute(self): """Execute the already parsed query and return the NodeSet of FQDN hostnames that matches. Returns: ClusterShell.NodeSet.NodeSet: with the FQDNs of the matching hosts. """ @abstractmethod def _parse_token(self, token): """Recursively interpret the tokens returned by the grammar parsing. Arguments: token (pyparsing.ParseResults): a single token returned by the grammar parsing. """ def _build(self, query_string): """Parse the query string according to the grammar and build the query for later execution. Arguments: query_string (str): the query string to be parsed. """ self.logger.trace('Parsing query: %s', query_string) parsed = self.grammar.parseString(query_string.strip(), parseAll=True) self.logger.trace('Parsed query: %s', parsed) for token in parsed: self._parse_token(token)
def _make_matcher_element(self): return pyparsing.NoMatch().setParseAction(self._parse_action)
#!/usr/bin/env python from __future__ import absolute_import from .annotator import Annotator, AnnoTier, AnnoSpan import re import pyparsing as pypar def word_token_regex(disallowed_delimiter): return pypar.Regex(r"[^\s\n" + re.escape(disallowed_delimiter) + r"]+") pypar.ParserElement.setDefaultWhitespaceChars(" \t") table_parser = pypar.NoMatch() table_cell_separators = ["|", "/", ","] for separator in table_cell_separators: value = pypar.Combine( word_token_regex(separator) * (0, 10), joinString=' ', adjacent=False) value.setParseAction(lambda start, tokens: (start, tokens[0])) empty = pypar.Empty() empty.setParseAction(lambda start, tokens: (start, tokens)) value = pypar.Group(value + empty) row = pypar.Group(pypar.Optional(separator).suppress() + (value + pypar.Literal(separator).suppress()) * (1, None) + pypar.Optional(value) + (pypar.StringEnd() | pypar.Literal("\n")).suppress() + pypar.Optional("\n").suppress()) table_parser ^= ( (pypar.LineStart() + pypar.Optional(pypar.White())).suppress() + row * (1, None)).setResultsName("delimiter:" + separator)
def __init__(self, extra_literals=[]): """ 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 ]* """ point = pp.Literal(".") e = pp.CaselessLiteral("E") fnumber = pp.Combine(pp.Word("+-" + pp.nums, pp.nums) + pp.Optional(point + pp.Optional(pp.Word(pp.nums))) + pp.Optional(e + pp.Word("+-" + pp.nums, pp.nums))) ident = pp.Word(pp.alphas, pp.alphas + pp.nums + "_$") plus = pp.Literal("+") minus = pp.Literal("-") mult = pp.Literal("*") div = pp.Literal("/") lpar = pp.Literal("(").suppress() rpar = pp.Literal(")").suppress() addop = plus | minus multop = mult | div expop = pp.Literal("^") pi = pp.CaselessLiteral("PI") self.extra_literals = extra_literals pp_extra_literals = functools.reduce(operator.or_, [pp.CaselessLiteral(e) for e in extra_literals], pp.NoMatch()) expr = pp.Forward() atom = ((pp.Optional(pp.oneOf("- +")) + (pi | e | pp_extra_literals | fnumber | ident + lpar + expr + rpar).setParseAction(self.pushFirst)) | pp.Optional(pp.oneOf("- +")) + pp.Group(lpar + expr + rpar) ).setParseAction(self.pushUMinus) # by defining exponentiation as "atom [ ^ factor ]..." instead of # "atom [ ^ atom ]...", we get right-to-left exponents, instead of left-to-right # that is, 2^3^2 = 2^(3^2), not (2^3)^2. factor = pp.Forward() factor << atom + pp.ZeroOrMore((expop + factor).setParseAction(self.pushFirst)) term = factor + pp.ZeroOrMore((multop + factor).setParseAction(self.pushFirst)) expr << term + pp.ZeroOrMore((addop + term).setParseAction(self.pushFirst)) # addop_term = ( addop + term ).setParseAction( self.pushFirst ) # general_term = term + ZeroOrMore( addop_term ) | OneOrMore( addop_term) # expr << general_term self.bnf = expr # map operator symbols to corresponding arithmetic operations epsilon = 1e-12 self.opn = {"+": operator.add, "-": operator.sub, "*": operator.mul, "/": operator.truediv, "^": operator.pow} self.fn = {"sin": math.sin, "cos": math.cos, "tan": math.tan, "abs": abs, "trunc": lambda a: int(a), "round": round, "sgn": lambda a: abs(a) > epsilon and pp.cmp(a, 0) or 0}
class DockerfileCommand(object): parser = p.NoMatch() @classmethod def parse(cls, value): return cls.parser.parseString(value, parseAll=True)
def _compile_impossible(self, element, src_state, dst_state, grammar, kaldi_rule, fst): # FIXME: not impossible enough (lower probability?) fst.add_arc(src_state, dst_state, self.impossible_word.lower()) return pp.NoMatch()