def parsesingle(s, strictmode=True, expansionlimit=None, convertpos=False): '''like parse, but only consumes a single top level node, e.g. parsing 'a\nb' will only return a node for 'a', leaving b unparsed''' p = _parser(s, strictmode=strictmode, expansionlimit=expansionlimit) tree = p.parse() if convertpos: ast.posconverter(s).visit(tree) return tree
def parse(s, strictmode=True, expansionlimit=None, convertpos=False): '''parse the input string, returning a list of nodes top level node kinds are: - command - a simple command - pipeline - a series of simple commands - 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) parts.append(part) ef = _endfinder() ef.visit(parts[-1]) index = max(parts[-1].pos[1], ef.end) + 1 if convertpos: for tree in parts: ast.posconverter(s).visit(tree) return parts
def parse(s, strictmode=True, expansionlimit=None, convertpos=False): '''parse the input string, returning a list of nodes top level node kinds are: - command - a simple command - pipeline - a series of simple commands - 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. ''' # s is the input from the bash scripts # _parse is a Class: line--709 # 传入了所有的文本 p = _parser(s, strictmode=strictmode, expansionlimit=expansionlimit) # Call parse function to deal with those part parts = [p.parse()] # print "[Parse_PART1]",parts # print " " class endfinder(ast.nodevisitor): def __init__(self): self.end = -1 def visitheredoc(self, node, value): self.end = node.pos[1] # Find the 'real' end in case we have a heredoc in there ef = _endfinder() ef.visit(parts[-1]) index = max(parts[-1].pos[1], ef.end) + 1 # Call the _parser function to deal with each line. while index < len(s): part = _parser(s[index:], strictmode=strictmode).parse() # print "[Parse_PART2]",parts # print " " if not isinstance(part, ast.node): break line_index = parts[-1].lineno # disregard next newline in line count # it is either a product of a same-line comment or trailing whitespaces if parts[-1].kind == 'command' and hasattr(parts[-1].parts[-1], 'discard'): if parts[-1].parts[-1].discard and part.kind == 'newline': part.lineno = 0 ast.posshifter(index, line_index).visit(part) # Append each line's output for bash scripts parts.append(part) ef = _endfinder() ef.visit(parts[-1]) index = max(parts[-1].pos[1], ef.end) + 1 if convertpos: for tree in parts: ast.posconverter(s).visit(tree) parts = list(filter(lambda x: x.kind != 'newline', parts)) # print "[Parse_Final]",parts # print " " return parts