def SpanIdFromError(error): #print(parse_error) if error.span_id != const.NO_INTEGER: return error.span_id if error.token: return error.token.span_id if error.part: return word.LeftMostSpanForPart(error.part) if error.word: return word.LeftMostSpanForWord(error.word) return const.NO_INTEGER
def DoWordPart(self, node, local_symbols, quoted=False): span_id = word.LeftMostSpanForPart(node) if span_id is not None and span_id != const.NO_INTEGER: span = self.arena.GetLineSpan(span_id) self.cursor.PrintUntil(span_id) if node.tag == word_part_e.ArrayLiteralPart: pass elif node.tag == word_part_e.EscapedLiteralPart: if quoted: pass else: # If unquoted \e, it should quoted instead. ' ' vs. \<invisible space> # Hm is this necessary though? I think the only motivation is changing # \{ and \( for macros. And ' ' to be readable/visible. t = node.token val = t.val[1:] assert len(val) == 1, val if val != '\n': self.cursor.PrintUntil(t.span_id) self.cursor.SkipUntil(t.span_id + 1) self.f.write("'%s'" % val) elif node.tag == word_part_e.LiteralPart: # Print it literally. # TODO: We might want to do it all on the word level though. For # example, foo"bar" becomes "foobar" in oil. spid = node.token.span_id if spid == const.NO_INTEGER: #raise RuntimeError('%s has no span_id' % node.token) # TODO: Fix word.TildeDetect to construct proper tokens. log('WARNING: %s has no span_id' % node.token) else: self.cursor.PrintUntil(spid + 1) elif node.tag == word_part_e.TildeSubPart: # No change pass elif node.tag == word_part_e.SingleQuotedPart: # TODO: # '\n' is '\\n' # $'\n' is '\n' # TODO: Should print until right_spid # left_spid, right_spid = node.spids if node.tokens: # Empty string has no tokens last_spid = node.tokens[-1].span_id self.cursor.PrintUntil(last_spid + 1) elif node.tag == word_part_e.DoubleQuotedPart: for part in node.parts: self.DoWordPart(part, local_symbols, quoted=True) elif node.tag == word_part_e.SimpleVarSub: spid = node.token.span_id op_id = node.token.id if op_id == Id.VSub_DollarName: self.cursor.PrintUntil(spid + 1) elif op_id == Id.VSub_Number: self.cursor.PrintUntil(spid + 1) elif op_id == Id.VSub_Bang: # $! self.f.write( '$BgPid') # Job most recently placed in backgroudn self.cursor.SkipUntil(spid + 1) elif op_id == Id.VSub_At: # $@ self.f.write('$ifsjoin(Argv)') self.cursor.SkipUntil(spid + 1) elif op_id == Id.VSub_Pound: # $# self.f.write('$Argc') self.cursor.SkipUntil(spid + 1) elif op_id == Id.VSub_Dollar: # $$ self.f.write('$Pid') self.cursor.SkipUntil(spid + 1) elif op_id == Id.VSub_Star: # $* # PEDANTIC: Depends if quoted or unquoted self.f.write('$ifsjoin(Argv)') self.cursor.SkipUntil(spid + 1) elif op_id == Id.VSub_Hyphen: # $* self.f.write('$Flags') self.cursor.SkipUntil(spid + 1) elif op_id == Id.VSub_QMark: # $? self.f.write('$Status') self.cursor.SkipUntil(spid + 1) else: raise AssertionError(op_id) elif node.tag == word_part_e.BracedVarSub: left_spid, right_spid = node.spids # NOTE: Why do we need this but we don't need it in command sub? self.cursor.PrintUntil(left_spid) name_spid = node.token.span_id op_id = node.token.id parens_needed = True if node.bracket_op: # a[1] # These two change the sigil! ${a[@]} is now @a! # a[@] # a[*] pass if node.prefix_op: # len() pass if node.suffix_op: # foo.trimLeft() # foo.trimGlobLeft() # foo.trimGlobLeft(longest=True) # # python lstrip() does something different # a[1:1] # .replace() # .replaceGlob() pass if op_id == Id.VSub_QMark: self.cursor.PrintUntil(name_spid + 1) if parens_needed: # Skip over left bracket and write our own. self.f.write('$(') self.cursor.SkipUntil(left_spid + 1) # Placeholder for now self.cursor.PrintUntil(right_spid) # Skip over right bracket and write our own. self.f.write(')') else: pass self.cursor.SkipUntil(right_spid + 1) elif node.tag == word_part_e.CommandSubPart: left_spid, right_spid = node.spids #self.cursor.PrintUntil(left_spid) self.f.write('$[') self.cursor.SkipUntil(left_spid + 1) self.DoCommand(node.command_list, local_symbols) self.f.write(']') self.cursor.SkipUntil(right_spid + 1) # change to $[echo hi] elif node.tag == word_part_e.ArithSubPart: # We're not bothering to translate the arithmetic language. # Just turn $(( x ? 0 : 1 )) into $shExpr('x ? 0 : 1'). left_spid, right_spid = node.spids # Skip over left bracket and write our own. self.f.write("$shExpr('") self.cursor.SkipUntil(left_spid + 1) # NOTE: This doesn't do anything yet. #self.DoArithExpr(node.anode, local_symbols) # Placeholder for now self.cursor.PrintUntil(right_spid - 1) # Skip over right bracket and write our own. self.f.write("')") self.cursor.SkipUntil(right_spid + 1) elif node.tag == word_part_e.ExtGlobPart: # Change this into a function? It depends whether it is used as # a glob or fnmatch. # # Example of glob: # cloud/sandstorm/make-bundle.sh pass else: raise AssertionError(node.__class__.__name__)