How to use the bashlex.ast.nodevisitor function in bashlex

To help you get started, we’ve selected a few bashlex examples, based on popular ways it is used in public projects.

Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.

github idank / explainshell / tests / test-matcher.py View on Github external
def test_expansion_limit(self):
        cmd = 'a $(b $(c))'
        m = matcher.matcher(cmd, s)
        m.match()

        class depthchecker(bashlex.ast.nodevisitor):
            def __init__(self):
                self.depth = 0
                self.maxdepth = 0
            def visitnode(self, node):
                if 'substitution' in node.kind:
                    self.depth += 1
                    self.maxdepth = max(self.maxdepth, self.depth)
            def visitendnode(self, node):
                if 'substitution' in node.kind:
                    self.depth -= 1

        v = depthchecker()
        v.visit(m.ast)
        self.assertEquals(v.maxdepth, 1)
github idank / bashlex / tests / test-parser.py View on Github external
def assertASTEquals(self, s, expected, **parserargs):
        results = parse(s, **parserargs)
        self.assertTrue(len(results) == 1, 'expected one ast from parse(), '
                        'got %d' % len(results))
        result = results[0]

        # make sure our words are not empty
        class nullopvisitor(ast.nodevisitor):
            def visitword(_, node, word):
                self.assertTrue(word, 'node %r has no word' % node)

        nullopvisitor().visit(result)

        msg = 'ASTs not equal for %r\n\nresult:\n\n%s\n\n!=\n\nexpected:\n\n%s' % (s, result.dump(), expected.dump())
        self.assertEquals(result, expected, msg)
github idank / bashlex / bashlex / subst.py View on Github external
def _adjustpositions(node_, base, endlimit):
    class v(ast.nodevisitor):
        def visitnode(self, node):
            assert node.pos[1] + base <= endlimit
            node.pos = (node.pos[0] + base, node.pos[1] + base)
    visitor = v()
    visitor.visit(node_)
github idank / bashlex / bashlex / parser.py View on Github external
- list - a series of one or more pipelines
    - compound - contains constructs for { list; }, (list), if, for..

    leafs are word nodes (which in turn can also contain any of the
    aforementioned nodes due to command substitutions).

    when strictmode is set to False, we will:
    - skip reading a heredoc if we're at the end of the input

    expansionlimit is used to limit the amount of recursive parsing done due to
    command substitutions found during word expansion.
    '''
    p = _parser(s, strictmode=strictmode, expansionlimit=expansionlimit)
    parts = [p.parse()]

    class endfinder(ast.nodevisitor):
        def __init__(self):
            self.end = -1
        def visitheredoc(self, node, value):
            self.end = node.pos[1]

    # find the 'real' end incase we have a heredoc in there
    ef = _endfinder()
    ef.visit(parts[-1])
    index = max(parts[-1].pos[1], ef.end) + 1
    while index < len(s):
        part = _parser(s[index:], strictmode=strictmode).parse()

        if not isinstance(part, ast.node):
            break

        ast.posshifter(index).visit(part)
github idank / bashlex / bashlex / parser.py View on Github external
parserstate=self.parserstate,
                                       strictmode=strictmode,
                                       **tokenizerargs)

        self.redirstack = self.tok.redirstack

    def parse(self):
        # yacc.yacc returns a parser object that is not reentrant, it has
        # some mutable state. we make a shallow copy of it so no
        # state spills over to the next call to parse on it
        theparser = copy.copy(yaccparser)
        tree = theparser.parse(lexer=self.tok, context=self)

        return tree

class _endfinder(ast.nodevisitor):
    '''helper class to find the "real" end pos of a node that contains
    a heredoc. this is a hack because heredoc aren't really part of any node
    since they don't always follow the end of a node and might appear on
    a different line'''
    def __init__(self):
        self.end = -1
    def visitheredoc(self, node, value):
        self.end = node.pos[1]
github idank / bashlex / examples / commandsubstitution-remover.py View on Github external
import sys

import argparse
from argparse import RawTextHelpFormatter

from bashlex import parser, ast

class nodevisitor(ast.nodevisitor):
    def __init__(self, positions):
        self.positions = positions

    def visitcommandsubstitution(self, n, command):
        # log the start and end positions of this command substitution
        self.positions.append(n.pos)

        # do not recurse into child nodes
        return False

desc = '''replace all occurrences of $() and `` with the string given in -s

  $ commandsubstitution-remover.py -s nope -c 'foo $(bar)'
  foo nope

within words:
github idank / bashlex / bashlex / ast.py View on Github external
def findfirstkind(parts, kind):
    for i, node in enumerate(parts):
        if node.kind == kind:
            return i
    return -1

class posconverter(nodevisitor):
    def __init__(self, string):
        self.string = string

    def visitnode(self, node):
        assert hasattr(node, 'pos'), 'node %r is missing pos attr' % node
        start, end = node.__dict__.pop('pos')
        node.s = self.string[start:end]

class posshifter(nodevisitor):
    def __init__(self, count):
        self.count = count

    def visitnode(self, node):
        #assert node.pos[1] + base <= endlimit
        node.pos = (node.pos[0] + self.count, node.pos[1] + self.count)
github idank / explainshell / explainshell / matcher.py View on Github external
self.results = []

    def __repr__(self):
        return '' % (self.name, len(self.results))

class matchresult(collections.namedtuple('matchresult', 'start end text match')):
    @property
    def unknown(self):
        return self.text is None

matchwordexpansion = collections.namedtuple('matchwordexpansion',
                                            'start end kind')

logger = logging.getLogger(__name__)

class matcher(bashlex.ast.nodevisitor):
    '''parse a command line and return a list of matchresults describing
    each token.
    '''
    def __init__(self, s, store):
        self.s = s.encode('latin1', 'replace')
        self.store = store
        self._prevoption = self._currentoption = None
        self.groups = [matchgroup('shell')]

        # a list of matchwordexpansions where expansions happened during word
        # expansion
        self.expansions = []

        # a stack to manage nested command groups: whenever a new simple
        # command is started, we push a tuple with:
        # - the node that started this group. this is used to find it when
github nickdiego / compiledb / compiledb / parser.py View on Github external
result.compdb.append({
                    'directory': working_dir,
                    'command': command_str,
                    'file': filepath,
                })
            else:
                result.compdb.append({
                    'directory': working_dir,
                    'arguments': arguments,
                    'file': filepath,
                })

    return result


class SubstCommandVisitor(bashlex.ast.nodevisitor):
    """Uses bashlex to parse and process sh/bash substitution commands.
       May result in a parsing exception for invalid commands."""
    def __init__(self):
        self.substs = []

    def visitcommandsubstitution(self, n, cmd):
        self.substs.append(n)
        return False


class CommandProcessor(bashlex.ast.nodevisitor):
    """Uses bashlex to parse and traverse the resulting bash AST
       looking for and extracting compilation commands."""
    @staticmethod
    def process(line, wd):
        trees = bashlex.parser.parse(line)
github idank / bashlex / bashlex / ast.py View on Github external
else:
                lines[-1] += ']'
            return '\n'.join(lines)
        return repr(n)

    if not isinstance(tree, node):
        raise TypeError('expected node, got %r' % tree.__class__.__name__)
    return _format(tree)

def findfirstkind(parts, kind):
    for i, node in enumerate(parts):
        if node.kind == kind:
            return i
    return -1

class posconverter(nodevisitor):
    def __init__(self, string):
        self.string = string

    def visitnode(self, node):
        assert hasattr(node, 'pos'), 'node %r is missing pos attr' % node
        start, end = node.__dict__.pop('pos')
        node.s = self.string[start:end]

class posshifter(nodevisitor):
    def __init__(self, count):
        self.count = count

    def visitnode(self, node):
        #assert node.pos[1] + base <= endlimit
        node.pos = (node.pos[0] + self.count, node.pos[1] + self.count)