RecursiveDescentParsing 을 TFP 로 시도를 해보려고 하는데.. Parser부분에 대한 test 의 결과를 얻기 위해서는 AST를 얻도록 해야 하고, AST를 조금씩 구축해나가는 방향으로 디자인유도중인데. 이 아이디어 생각하려는데 1시간을 소비했다. 흡;
먼저 "1"을 넣으면 "1"을 리턴하는 프로그램을 만듭니다. 다음 "314"를 넣으면 "314"를 리턴하게 합니다. 다음엔, "1 + 0"을 넣으면 "1"을 리턴하게 합니다. 다음, "1 + 314"를 넣으면 "315"를 리턴합니다. 다음, "1 + 2 + 314"를 하면 "317"을 리턴합니다. 다음, "1 - 0"을 하면 "1"을 리턴합니다. 다음, "1 - 1"을 하면 "0"을 리턴합니다. 다음, "314 - 1 + 2"를 하면 "315"를 리턴합니다. 다음, "- 1"을 넣으면 "-1"을 리턴합니다. 다음, "( 1 )"을 넣으면 "1"을 리턴합니다. ...... AST는 아직 생각하지 말고 당장 현재의 테스트를 패스하게 만드는데 필요한 것만 만들어 나가고 OAOO를 지키면서(테스트코드와 시스템코드 사이, 그리고 시스템 코드 간) 리팩토링을 지속적으로 합니다 -- 그렇다고 파싱 이론을 전혀 이용하지 말라는 말은 아니고 YAGNI를 명심하라는 것입니다. 그러면 어느 누가 봐도 훌륭한 디자인의 파서를 만들 수 있습니다. DoTheSimplestThingThatCouldPossiblyWork. --김창준
- 아. 이번 레포트에서 요구하는 것이 계산기는 아니고, 간단한 언어에 대한 파싱 유도과정을 보여주고 에러처리하는 것이다보니, 구체적인 결과를 얻는 부분이 모호하다 판단이 들어서요. 그래서 조금 더 명시적으로 보이는 DOM 형태의 AST를 구하는 형태로 접근했습니다. --석천
문제점 : 테스트 가능할 수 있는 아이디어가 나오기까지가 오래걸렸다. 테스트 가능한 방법으로 접근하고 나서부터의 코딩은 1-1.5시간정도밖에 안걸렸지만. 그리고 본래의 스펙에는 AST 에 대한 언급이 없었다. 해당 함수가 제대로 호출되었는지를 근거로 접근하는 것이 나았을지도.
~cpp parser = RealParser() parser.setStringStream("a = b+c") doc = parser.parse() self.assert_(doc != None) # 이 테스트를 만족할때까지 프로그래밍 start = doc.getStart() self.assert_(start != None) # 이 테스트를 만족할때까지 프로그래밍 statements = start.getStatements() self.assert_(statements != None) # 이 테스트를 만족할때까지 프로그래밍 statement = statements.getStatement() self.assert_(statement != None) # 이 테스트를 만족할때까지 프로그래밍 identifier = statement.getIdentifier() token = identifier.getToken() self.assertEquals(token.tokenString, 'a') self.assertEquals(token.tokenType, Scanner.TOKEN_IDENTIFIER) # 이 테스트를 만족할때까지 프로그래밍 assignment_operator = statement.getAssignmentOperator() token = assignment_operator.getToken() self.assertEquals(token.tokenString, '=') self.assertEquals(token.tokenType, Scanner.TOKEN_ASSIGNMENT_OPERATOR) # 이 테스트를 만족할때까지 프로그래밍 expression = statement.getExpression() self.assert_(expression != None) # 이 테스트를 만족할때까지 프로그래밍 term = expression.getTerm() self.assert_(term != None) # 이 테스트를 만족할때까지 프로그래밍 factor = term.getFactor() self.assert_(factor != None) # 이 테스트를 만족할때까지 프로그래밍 identifier = factor.getIdentifier() self.assert_(identifier != None) # 이 테스트를 만족할때까지 프로그래밍 token = identifier.getToken() self.assertEquals(token.tokenString,'b') self.assertEquals(token.tokenType, Scanner.TOKEN_IDENTIFIER) # 이 테스트를 만족할때까지 프로그래밍 plus_operator = expression.getPlusOperator() token = plus_operator.getToken() self.assertEquals(token.tokenString, '+') self.assertEquals(token.tokenType, Scanner.TOKEN_PLUS_OPERATOR) # 이 테스트를 만족할때까지 프로그래밍