Example #1
0
    def parseImpl(self, string, loc, doActions=True):
        maxExcLoc = -1
        maxException = None
        matches = []
        for e in self.exprs:
            try:
                loc2 = e.tryParse(string, loc)
            except ParseException as err:
                err.__traceback__ = None
                if err.loc > maxExcLoc:
                    maxException = err
                    maxExcLoc = err.loc
            except IndexError:
                if len(string) > maxExcLoc:
                    maxException = ParseException(string, len(string), self)
                    maxExcLoc = len(string)
            else:
                # save match among all matches, to retry longest to shortest
                matches.append((loc2, e))

        if matches:
            # re-evaluate all matches in descending order of length of match, in case attached actions
            # might change whether or how much they match of the input.
            matches.sort(key=itemgetter(0), reverse=True)

            if not doActions:
                # no further conditions or parse actions to change the selection of
                # alternative, so the first match will be the best match
                _, best_expr = matches[0]
                loc, best_results = best_expr._parse(string, loc, doActions)
                return loc, ParseResults(self, [best_results])

            longest = -1, None
            for loc1, expr1 in matches:
                if loc1 <= longest[0]:
                    # already have a longer match than this one will deliver, we are done
                    return longest

                try:
                    loc2, toks = expr1._parse(string, loc, doActions)
                except ParseException as err:
                    err.__traceback__ = None
                    if err.loc > maxExcLoc:
                        maxException = err
                        maxExcLoc = err.loc
                else:
                    if loc2 >= loc1:
                        return loc2, ParseResults(self, [toks])
                    # didn't match as much as before
                    elif loc2 > longest[0]:
                        longest = loc2, ParseResults(self, [toks])

            if longest != (-1, None):
                return longest

        if maxException is not None:
            maxException.msg = "Expecting " + text(self)
            raise maxException
        else:
            raise ParseException(string, loc, "no defined alternatives to match", self)
Example #2
0
 def parseImpl(self, string, start, doActions=True):
     try:
         results = self.expr._parse(string, start, doActions)
         return ParseResults(self, results.start, results.end, [results])
     except ParseException:
         return ParseResults(self, start, start,
                             self.parser_config.defaultValue)
Example #3
0
 def parseImpl(self, string, loc, doActions=True):
     if self.re.match(string, loc):
         end = loc + len(self.match)
         try:
             if string[end] not in self.identChars:
                 return end, ParseResults(self, [self.match])
         except IndexError:
             return end, ParseResults(self, [self.match])
     raise ParseException(self, loc, string)
Example #4
0
    def parseImpl(self, string, loc, doActions=True):
        try:
            loc, tokens = self.expr._parse(string, loc, doActions)
        except (ParseException, IndexError):
            if self.defaultValue is None:
                return loc, ParseResults(self, [])
            else:
                tokens = self.defaultValue

        return loc, ParseResults(self, [tokens])
Example #5
0
 def parseImpl(self, string, loc, doActions=True):
     if loc < len(string):
         if string[loc] == "\n":
             return loc + 1, ParseResults(self, ["\n"])
         else:
             raise ParseException(self, loc, string)
     elif loc == len(string):
         return loc + 1, ParseResults(self, [])
     else:
         raise ParseException(self, loc, string)
Example #6
0
 def parseImpl(self, string, start, doActions=True):
     acc = []
     end = start
     max = self.parser_config.max_match
     stopper = self.parser_config.end
     count = 0
     try:
         while end < len(string) and count < max:
             if stopper:
                 end = self.engine.skip(string, end)
                 if stopper.match(string, end):
                     if self.parser_config.min_match <= count:
                         break
                     else:
                         raise ParseException(self,
                                              end,
                                              string,
                                              msg="found stopper too soon")
             result = self.expr._parse(string, end, doActions)
             end = result.end
             if result:
                 acc.append(result)
                 count += 1
     except ParseException:
         if self.parser_config.min_match <= count <= max:
             pass
         else:
             ParseException(self,
                            start,
                            string,
                            msg="Not correct amount of matches")
     if count:
         if (count < self.parser_config.min_match
                 or self.parser_config.max_match < count):
             raise ParseException(
                 self,
                 acc[0].start,
                 string,
                 msg=(
                     f"Expecting between {self.parser_config.min_match} and"
                     f" {self.parser_config.max_match} of {self.expr}"),
             )
         else:
             return ParseResults(self, acc[0].start, acc[-1].end, acc)
     else:
         if not self.parser_config.min_match:
             return ParseResults(self, start, start, [])
         else:
             raise ParseException(
                 self,
                 start,
                 string,
                 msg=
                 f"Expecting at least {self.parser_config.min_match} of {self}",
             )
Example #7
0
 def parseImpl(self, string, start, doActions=True):
     if self.regex:
         found = self.regex.match(string, start)
         if found:
             return ParseResults(self, start, start, [])
         raise ParseException(self, start, string)
     else:
         try:
             self.expr.parse(string, start, doActions=True)
             raise ParseException(self, start, string)
         except:
             return ParseResults(self, start, start, [])
Example #8
0
    def parseImpl(self, string, start, doActions=True):
        causes = []
        matches = []
        for e in self.exprs:
            try:
                end = e.tryParse(string, start)
                matches.append((end, e))
            except ParseException as err:
                causes.append(err)

        if matches:
            # re-evaluate all matches in descending order of length of match, in case attached actions
            # might change whether or how much they match of the input.
            matches.sort(key=itemgetter(0), reverse=True)

            if not doActions:
                # no further conditions or parse actions to change the selection of
                # alternative, so the first match will be the best match
                _, best_expr = matches[0]
                best_results = best_expr._parse(string, start, doActions)
                return ParseResults(self, best_results.start, best_results.end,
                                    [best_results])

            longest = -1, None
            for loc, expr1 in matches:
                if loc <= longest[0]:
                    # already have a longer match than this one will deliver, we are done
                    return longest

                try:
                    toks = expr1._parse(string, start, doActions)
                except ParseException as err:
                    causes.append(err)
                else:
                    if toks.end >= loc:
                        return ParseResults(self, toks.start, toks.end, [toks])
                    # didn't match as much as before
                    elif toks.end > longest[0]:
                        longest = (
                            toks.end,
                            ParseResults(self, toks.start, toks.end, [toks]),
                        )

            if longest != (-1, None):
                return longest

        raise ParseException(self,
                             start,
                             string,
                             msg="no defined alternatives to match",
                             cause=causes)
Example #9
0
    def parseImpl(self, string, end, doActions=True):
        start = end
        instrlen = len(string)
        end_parse = self.expr._parse
        self_failOn_canParseNext = (self.failOn.canParseNext
                                    if self.failOn is not None else None)
        self_ignoreExpr_tryParse = (self.ignoreExpr.tryParse
                                    if self.ignoreExpr is not None else None)

        tmploc = end
        while tmploc <= instrlen:
            if self_failOn_canParseNext is not None:
                # break if failOn expression matches
                if self_failOn_canParseNext(string, tmploc):
                    before_end = tmploc
                    break

            if self_ignoreExpr_tryParse is not None:
                # advance past ignore expressions
                while 1:
                    try:
                        tmploc = self_ignoreExpr_tryParse(string, tmploc)
                    except ParseBaseException:
                        break
            try:
                before_end = tmploc
                tmploc, _ = end_parse(string, tmploc, doActions=False)
            except (ParseException, IndexError):
                # no match, advance loc in string
                tmploc += 1
            else:
                # matched skipto expr, done
                break

        else:
            # ran off the end of the input string without matching skipto expr, fail
            raise ParseException(self, end, string)

        # build up return values
        end = tmploc
        skiptext = string[start:before_end]
        skip_result = []
        if skiptext:
            skip_result.append(skiptext)

        if self.includeMatch:
            _, end_result = end_parse(string, before_end, doActions)
            skip_result.append(end_result)
            return end, ParseResults(self, skip_result)
        else:
            return before_end, ParseResults(self, skip_result)
Example #10
0
    def parseImpl(self, string, start, doActions=True):
        instrlen = len(string)
        fail = self.parser_config.fail
        ignore = self.parser_config.ignore

        loc = start
        while loc <= instrlen:
            if fail:
                # break if failOn expression matches
                if fail.canParseNext(string, loc):
                    before_end = loc
                    break

            if ignore:
                # advance past ignore expressions
                while 1:
                    try:
                        loc = ignore.tryParse(string, loc)
                        if loc == None:
                            Log.error("")
                    except ParseException:
                        break
            try:
                before_end = loc
                loc = self.expr._parse(string, loc, doActions=False).end
                if loc == None:
                    Log.error("")
            except ParseException:
                # no match, advance loc in string
                loc += 1
            else:
                # matched skipto expr, done
                break

        else:
            # ran off the end of the input string without matching skipto expr, fail
            raise ParseException(self, start, string)

        # build up return values
        end = loc
        skiptext = string[start:before_end]
        skip_result = []
        if skiptext:
            skip_result.append(skiptext)

        if self.parser_config.include:
            end_result = self.expr._parse(string, before_end, doActions)
            skip_result.append(end_result)
            return ParseResults(self, start, end, skip_result)
        else:
            return ParseResults(self, start, before_end, skip_result)
Example #11
0
    def parseImpl(self, string, loc, doActions=True):
        start = loc
        instrlen = len(string)
        maxloc = start + len(self.match_string)

        if maxloc <= instrlen:
            match_string = self.match_string
            match_stringloc = 0
            mismatches = []
            maxMismatches = self.maxMismatches

            for match_stringloc, (src, mat) in enumerate(
                    zip(string[loc:maxloc], match_string)):
                if src != mat:
                    mismatches.append(match_stringloc)
                    if len(mismatches) > maxMismatches:
                        break
            else:
                loc = match_stringloc + 1
                results = ParseResults(self, [string[start:loc]])
                results["original"] = match_string
                results["mismatches"] = mismatches
                return loc, results

        raise ParseException(self, loc, string)
Example #12
0
    def parseImpl(self, string, loc, doActions=True):
        # pass False as last arg to _parse for first element, since we already
        # pre-parsed the string as part of our And pre-parsing
        encountered_error_stop = False
        acc = []
        for expr in self.exprs:
            if isinstance(expr, And._ErrorStop):
                encountered_error_stop = True
                continue
            try:
                loc, exprtokens = expr._parse(string, loc, doActions)
                acc.append(exprtokens)
            except ParseSyntaxException as cause:
                raise cause
            except ParseBaseException as pe:
                if encountered_error_stop:
                    raise ParseSyntaxException(pe.parserElement, pe.loc, pe.pstr)
                else:
                    raise pe
            except IndexError as ie:
                if encountered_error_stop:
                    raise ParseSyntaxException(string, len(string), self)
                else:
                    raise ie

        return loc, ParseResults(self, acc)
Example #13
0
    def parseImpl(self, string, loc, doActions=True):
        result = (string[loc] == self.firstQuoteChar
                  and self.re_match(string, loc) or None)
        if not result:
            raise ParseException(self, loc, string)

        loc = result.end()
        ret = result.group()

        if self.unquoteResults:

            # strip off quotes
            ret = ret[self.quoteCharLen:-self.endQuoteCharLen]

            if isinstance(ret, text):
                # replace escaped whitespace
                if "\\" in ret and self.convertWhitespaceEscapes:
                    ws_map = {
                        r"\t": "\t",
                        r"\n": "\n",
                        r"\f": "\f",
                        r"\r": "\r",
                    }
                    for wslit, wschar in ws_map.items():
                        ret = ret.replace(wslit, wschar)

                # replace escaped characters
                if self.escChar:
                    ret = re.sub(self.escCharReplacePattern, r"\g<1>", ret)

                # replace escaped quotes
                if self.escQuote:
                    ret = ret.replace(self.escQuote, self.endQuoteChar)

        return loc, ParseResults(self, [ret])
Example #14
0
 def parseImpl(self, string, loc, doActions=True):
     if loc != 0:
         if string[
                 loc -
                 1] in self.wordChars or string[loc] not in self.wordChars:
             raise ParseException(self, loc, string)
     return loc, ParseResults(self, [])
Example #15
0
    def _searchString(self, string, maxMatches=MAX_INT):
        if isinstance(self, Group):
            g = self
            scanned = [t for t, s, e in self._scanString(string, maxMatches)]
        else:
            g = Group(self)
            scanned = [
                ParseResults(g, s, e, [t])
                for t, s, e in self._scanString(string, maxMatches)
            ]

        if not scanned:
            return ParseResults(ZeroOrMore(g), -1, 0, [])
        else:
            return ParseResults(ZeroOrMore(g), scanned[0].start,
                                scanned[-1].end, scanned)
Example #16
0
    def parseImpl(self, string, start=0, doActions=True):
        if self.parser_config.exact:
            loc = start - self.parser_config.retreat
            if loc < 0:
                raise ParseException(self, start, string)
            ret = self.expr._parse(string, loc)
        else:
            # retreat specified a maximum lookbehind window, iterate
            test_expr = self.expr + StringEnd()
            instring_slice = string[:start]
            last_cause = ParseException(self, start, string)

            with self.engine.backup():
                for offset in range(self.parser_config.retreat, start + 1):
                    try:
                        ret = test_expr._parse(instring_slice, start - offset)
                        break
                    except ParseException as cause:
                        last_cause = cause
                else:
                    raise last_cause
        # return empty list of tokens, but preserve any defined results names

        ret.__class__ = Annotation
        return ParseResults(self, start, start, [ret])
Example #17
0
    def parseImpl(self, string, loc, doActions=True):
        if string[loc] not in self.initChars:
            raise ParseException(self, loc, string)

        start = loc
        loc += 1
        instrlen = len(string)
        bodychars = self.bodyChars
        maxloc = start + self.maxLen
        maxloc = min(maxloc, instrlen)
        while loc < maxloc and string[loc] in bodychars:
            loc += 1

        throwException = False
        if loc - start < self.minLen:
            throwException = True
        elif self.maxSpecified and loc < instrlen and string[loc] in bodychars:
            throwException = True
        elif self.asKeyword:
            if (start > 0 and string[start - 1] in bodychars
                    or loc < instrlen and string[loc] in bodychars):
                throwException = True

        if throwException:
            raise ParseException(self, loc, string)

        return loc, ParseResults(self, [string[start:loc]])
Example #18
0
    def parseImpl(self, string, start, doActions=True):
        end = start
        instrlen = len(string)
        maxloc = start + len(self.parser_config.match)

        if maxloc <= instrlen:
            match = self.parser_config.match
            match_stringloc = 0
            mismatches = []
            maxMismatches = self.parser_config.maxMismatches

            for match_stringloc, (src, mat) in enumerate(
                    zip(string[end:maxloc], match)):
                if src != mat:
                    mismatches.append(match_stringloc)
                    if len(mismatches) > maxMismatches:
                        break
            else:
                end = match_stringloc + 1
                results = ParseResults(self, start, end, [string[start:end]])
                results["original"] = match
                results["mismatches"] = mismatches
                return results

        raise ParseException(self, start, string)
Example #19
0
 def parseImpl(self, string, loc, doActions=True):
     instrlen = len(string)
     if instrlen > 0 and loc < instrlen:
         if string[loc] in self.wordChars or string[
                 loc - 1] not in self.wordChars:
             raise ParseException(self, loc, string)
     return loc, ParseResults(self, [])
Example #20
0
    def parseImpl(self, string, start, doActions=True):
        # by using self._expr.parse and deleting the contents of the returned ParseResults list
        # we keep any named results that were defined in the FollowedBy expression
        result = self.expr._parse(string, start, doActions=doActions)
        result.__class__ = Annotation

        return ParseResults(self, start, start, [result])
Example #21
0
    def post_parse(tokens):
        ret = tokens[0]
        if unquote_results:
            # strip off quotes
            ret = ret[len(quote_char) : -len(end_quote_char)]

            if isinstance(ret, text):
                # replace escaped whitespace
                if "\\" in ret and convert_whitespace_escape:
                    ws_map = {
                        r"\t": "\t",
                        r"\n": "\n",
                        r"\f": "\f",
                        r"\r": "\r",
                    }
                    for wslit, wschar in ws_map.items():
                        ret = ret.replace(wslit, wschar)

                # replace escaped characters
                if esc_char:
                    ret = re.sub(esc_char_replace_pattern, r"\g<1>", ret)

                # replace escaped quotes
                if esc_quote:
                    ret = ret.replace(esc_quote, end_quote_char)

        return ParseResults(tokens.type, tokens.start, tokens.end, [ret])
Example #22
0
def extractText(tokens, loc, string):
    start, d, end = tokens
    content = string[start:end]
    annotations = [
        Annotation(k, v[0].start, v[-1].end, v) for k, v in d.items()
    ]
    return ParseResults(d.type, start, end, [content] + annotations)
Example #23
0
 def parseImpl(self, string, start, doActions=True):
     word_chars = self.parser_config.word_chars
     instrlen = len(string)
     if instrlen > 0 and start < instrlen:
         if string[start] in word_chars or string[start - 1] not in word_chars:
             raise ParseException(self, start, string)
     return ParseResults(self, start, start, [])
Example #24
0
    def parseImpl(self, string, loc, doActions=True):
        result = self.re.match(string, loc)
        if not result:
            raise ParseException(self, loc, string)

        loc = result.end()
        return loc, ParseResults(self, [result.group()])
Example #25
0
    def parseImpl(self, string, loc, doActions=True):
        end_loc = loc
        matchOrder = []
        todo = list(zip(
            self.exprs, self.parser_config.min_match, self.parser_config.max_match
        ))
        count = [0] * len(self.exprs)

        while todo:
            for i, (c, (e, mi, ma)) in enumerate(zip(count, todo)):
                try:
                    temp_loc = e.tryParse(string, end_loc)
                    if temp_loc == end_loc:
                        continue
                    end_loc = temp_loc
                    c2 = count[i] = c + 1
                    if c2 >= ma:
                        del todo[i]
                        del count[i]
                    matchOrder.append(e)
                    break
                except ParseException as pe:
                    continue
            else:
                break

        for c, (e, mi, ma) in zip(count, todo):
            if c < mi:
                raise ParseException(
                    string,
                    loc,
                    "Missing minimum (%i) more required elements (%s)" % (mi, e),
                )

        found = set(id(m) for m in matchOrder)
        missing = [
            e
            for e, mi in zip(self.exprs, self.parser_config.min_matches)
            if id(e) not in found and not e.parser_config.mayReturnEmpty and mi > 0
        ]
        if missing:
            missing = ", ".join(text(e) for e in missing)
            raise ParseException(
                string, loc, "Missing one or more required elements (%s)" % missing
            )

        # add any unmatched Optionals, in case they have default values defined
        matchOrder += [
            e
            for e in self.exprs
            if id(e) not in found and e.parser_config.mayReturnEmpty
        ]

        results = []
        for e in matchOrder:
            loc, result = e._parse(string, loc, doActions)
            results.append(result)

        return loc, ParseResults(self, results)
Example #26
0
    def parseImpl(self, string, start, doActions=True):
        try:
            if string[start] == self.parser_config.match:
                return ParseResults(self, start, start + 1, [self.parser_config.match])
        except IndexError:
            pass

        raise ParseException(self, start, string)
Example #27
0
def _combine(tokens, start, string):
    output = ParseResults(
        tokens.type,
        tokens.start,
        tokens.end,
        [tokens.asString(sep=tokens.type.parser_config.separator)],
    )
    return output
Example #28
0
 def parseImpl(self, string, start, doActions=True):
     result = self.expr.parseImpl(string, start, doActions=doActions)
     output = ParseResults(
         self,
         start,
         result.end,
         [result.asString(sep=self.parser_config.separator)],
     )
     return output
Example #29
0
 def parseImpl(self, string, start, doActions=True):
     found = self.parser_config.regex.match(string, start)
     if found:
         return ParseResults(
             self,
             start,
             found.end(),
             [self.parser_config.match],
         )
     raise ParseException(self, start, string)
Example #30
0
 def parseImpl(self, string, loc, doActions=True):
     try:
         result = self.expr._parse(string, loc, doActions)
         return ParseResults(self, result.start, result.end, [result])
     except Exception as cause:
         if is_null(self.expr):
             Log.warning(
                 "Ensure you have assigned a ParserElement (<<) to this Forward",
                 cause=cause,
             )
         raise cause