kaist-plrg / python-analyzer

Python analysis framework in Scala
2 stars 0 forks source link

[Beautifier] ForStmt에 elseStmt가 없음에도 else: 를 출력하는 현상 #7

Closed yusungsim closed 3 years ago

yusungsim commented 3 years ago

Problem

Target String:

def func(c):
    for i in c:
        pass

class Cls:
    def __init__(self, max=0):
        self.max = max

    def __iter__(self):
        self.n = 0
        return self

    def __next__(self):
        if self.n > self.max:
            raise StopIteration

        result = 2 ** self.n
        self.n += 1
        return func

func(Cls())

Tokenize result:

 List(def, id(func), (, id(c), ), :, \NL
, INDENT, for, id(i), in, id(c), :, \NL
, INDENT, pass, \NL
, DEDENT, DEDENT, class, id(Cls), :, \NL
, INDENT, def, id(__init__), (, id(self), ,, id(max), =, 0, ), :, \NL
, INDENT, id(self), ., id(max), =, id(max), \NL
, DEDENT, def, id(__iter__), (, id(self), ), :, \NL
, INDENT, id(self), ., id(n), =, 0, \NL
, return, id(self), \NL
, DEDENT, def, id(__next__), (, id(self), ), :, \NL
, INDENT, if, id(self), ., id(n), >, id(self), ., id(max), :, \NL
, INDENT, raise, id(StopIteration), \NL
, DEDENT, id(result), =, 2, **, id(self), ., id(n), \NL
, id(self), ., id(n), +=, 1, \NL
, return, id(func), \NL
, DEDENT, DEDENT, id(func), (, id(Cls), (, ), ), \NL
)

Goal production: statements

Parse result: [0.586] parsed:

List(FunDef(List(),Id(func),Args(List(),List((Arg(Id(c),None,None),None)),None,List(),None),None,None,List(ForStmt(None,EName(Id(i)),EName(Id(c)),List(PassStmt),List()))), ClassDef(List(),Id(Cls),List(),List(),List(FunDef(List(),Id(__init__),Args(List(),List((Arg(Id(self),None,None),None), (Arg(Id(max),None,None),Some(EConst(IntLiteral(0))))),None,List(),None),None,None,List(AssignStmt(List(Attribute(EName(Id(self)),EName(Id(max)))),EName(Id(max)),None))), FunDef(List(),Id(__iter__),Args(List(),List((Arg(Id(self),None,None),None)),None,List(),None),None,None,List(AssignStmt(List(Attribute(EName(Id(self)),EName(Id(n)))),EConst(IntLiteral(0)),None), ReturnStmt(Some(EName(Id(self)))))), FunDef(List(),Id(__next__),Args(List(),List((Arg(Id(self),None,None),None)),None,List(),None),None,None,List(IfStmt(CompExpr(Attribute(EName(Id(self)),EName(Id(n))),List((CGt,Attribute(EName(Id(self)),EName(Id(max)))))),List(RaiseStmt(Some(EName(Id(StopIteration))),None)),List()), AssignStmt(List(EName(Id(result))),BinaryExpr(OPow,EConst(IntLiteral(2)),Attribute(EName(Id(self)),EName(Id(n)))),None), AugAssign(Attribute(EName(Id(self)),EName(Id(n))),OAdd,EConst(IntLiteral(1))), ReturnStmt(Some(EName(Id(func)))))))), ExprStmt(Call(EName(Id(func)),List(Call(EName(Id(Cls)),List(),List())),List())))

Beautify result:

def func(c, ):
  for i in c:
    pass
  else:
def Cls():
  def __init__(self, max=0, ):
    self.max = max
  def __iter__(self, ):
    self.n = 0
    return self
  def __next__(self, ):
    if self.n > self.max:
      raise StopIteration
    result = 2 ** self.n
    self.n += 1
    return func
func(Cls(), )

line 2번부터 시작한 ForStmt의 끝에 elseStmt가 없음에도 불구하고 else:를 출력. 따라서 이 Beautify result를 다시 파싱 시도하면 실패하게됨.

yusungsim commented 3 years ago

d48faf675de2f53fa78ba4e5697263ba3c7dd583

해결은 되었으나 리팩토링 필요