2010-01-18 4 views
1

게시판의 메시지가 가득한 데이터베이스가 있습니다. 보드는 BB 코드를 포맷 스타일로 사용합니다. 즉 :임의의 사용자 입력을 구문 분석합니다.

  • 나는 형식 아니에요
  • 이 [B] 굵은 [/ B] 텍스트입니다
  • 태그 할 수도 있습니다 [I] [B] 수 [/ B] [/ I]
  • 중첩
  • 그리고 [B] 중첩 [내가] 수 있습니다 [/ B]가 아니라 [/ I]는 추한

내 궁극적 인 목표는 몇 가지 잘 구성된 XML에 이러한 메시지를 변환하지 않는 것입니다 (여기에 토론을)). 정규 표현식을 사용하고 싶지는 않습니다. 사실 어떤 시점에서는 실패 할 것입니다.

첫 번째 단계 : 메시지를 일종의 내부 표현 (그래프, 트리 등)으로 구문 분석합니다. 그리고 나는이 시점에서 붙어있다. 실제 추출은 그다지 큰 문제는 아니지만 저장소가 있습니다.

일부 의미있는 구조에이 종류의 마크 업을 어떻게 나타내야합니까? 내 문제는 HTML 파일에서 DOM을 작성하는 브라우저와 비슷하거나 거의 동일합니다. 그래서 나는 그것을 해결할 몇 가지 전략이 있다고 생각합니다. 나는 솔루션이 완벽하지는 않을 것이지만 최대한 많은 시간을 투자하여 기꺼이 최선을 다할 것을 확신합니다.

질문 : 힌트/의견/의견이 있으십니까? 당신이 추천 할 수있는 어떤 논문이나 논문? 또는이 주제를 다루는 책? 나는 어떤 입력에도 감사하고있다.

답변

2
그리고 [내가]가 될 수는 [B] 중첩 [/ B]는 오히려 [/ I] 난 당신이 그것을 것을 제외 할 찾고있는 것과 매우 유사한 파서를 작성했습니다

추한 것 네 번째 예제에 오류를 던지십시오. "[i] 내의 예기치 않은 종료 태그 [/ b]"의 효과

나는 싶은 것은 매우 행할 수 있다고 생각하지만, 내부적으로는 원래의 텍스트 인 것처럼 트리를 만들 것입니다 :

"And the [b]nesting [i]can be[/i][/b][i] rather[/i] ugly". (XML로 변환 할 필요가 없다면 필요하지 않다고 생각합니다 .XML로 변환 할 필요가 없다면 각 섹션이 형식 조합으로 표시되는 텍스트 섹션의 링크 된 목록을 유지할 수 있습니다)

이 문제에 대한 두 가지 가능한 접근법이 마음에 듭니다 (물론 더 나은 가능성이있을 수 있습니다). 1) 누락 된 끝을 사전 처리하고 삽입하고 필요한 경우 태그를 시작하십시오. 2) 구문 분석 트리를 작성하고 겹치는 태그가있는 경우 현재 컨텍스트를 기반으로 누락 된 태그를 의미합니다. 나는 접근 번호 (2)가 더 간단하고 깨끗하다고 ​​생각한다.

AbstractElement 클래스, AbstractElement를 확장하는 TextElement 클래스 및 AbstractElement를 확장하고 AbstractElement 유형의 하위 요소 목록을 포함하는 Tag 클래스가있는 복합 패턴을 기반으로 트리를 모델링 할 수 있습니다.

루트 태그 인스턴스를 만드는 것으로 시작합니다. 그런 다음 rootTag.parse (text)를 호출합니다. 3 가지 유형의 토큰, 즉 텍스트, 시작 태그 및 종료 태그를 반환 할 수있는 스캐너가 필요합니다. 스캐너를 사용하면 토큰을 정상적으로 스캔 토큰보다 먼저 반환 할 수 있습니다. 이렇게하면 예기치 않은 종료 태그를 만나고 처리 한 후에 새 시작 태그 토큰을 밀어 넣을 수 있습니다. 당신은 또한 당신이 입력으로 끝났을 때 알아야 할 것입니다. 나는 4 번째 토큰 타입을 사용할 것이다.

 
    /* methods within class Tag */ 
    public void parse(String text) { 
     MyScanner scanner = new MyScanner(text); 
     parse(scanner); 
    } 

    /* returns next token */ 
    private Token parse(MyScanner scanner) { 
     Token firstToken = scanner.getNextToken(); 
     return parse(scanner,firstToken); 
    } 

    private Token parse(MyScanner scanner) { 
     Token firstToken = scanner.getNextToken(); 
     return parse(scanner,firstToken); 
    } 

    private Token parse(MyScanner scanner, Token token) { 
     while (!token.isDone() && !token.isEndTag()) { 
      if (token.isStartTag()) { 
       Tag subTag = new Tag(token.getValue()); 
       token = scanner.getNextToken(); 
       token = subTag.parse(scanner,token); 
       addElement(subTag); 
      } 

      else { 
       TextElement text = new TextElement(token.getValue()); 
       addElement(text); 
       token = scanner.getNextToken(); 
      } 
     } 

     if (token.isEndTag()) { 
      if (!token.getValue().equals(getName()) { 
       scanner.push(new Token(Token.START_TAG,token.getValue())); 
      } 
      else { 
       token = scanner.getNextToken(); 
      } 
     } 

     return token; 
    } 

그래서 당신은 구문 분석 할 수 있다면 "그리고는 [B] 중첩 [내가] 수 있습니다 [/ B]가 아니라 [/ 난] 추한", 다음이 생성을하셔야합니다.

 
rootTag.parse should be adding: 
    TextElement: "And the " 
    Tag: "b" 
      TextElement: "nesting " 
      Tag: "i" 
        TextElement: "can be" 
        (... at this point the odd [/b] is encountered ...) 
        (... push "i" start tag on the scanner ...) 
      (... here the [/b] is encountered (again) ...) 
    Tag: "i" (this was scanned because it had been pushed to the scanner) 
      TextElement: " rather" 
    TextElement: " ugly" 

참고 : 텍스트 영역 내에서의 코딩은 테스트 및 디버깅에 적합하지 않습니다. 이 답변을 힌트 또는 가능성으로 받아 들여야합니다.

+0

와우. 고맙습니다. 귀하의 샘플 코드는 거의 모든 문제를 해결했습니다 :) –

+0

감사합니다. 행운을 빕니다. 난 그냥 오타를 수정하고 푸시 통화에 잘못된 매개 변수를 전달하고 있었고, 지금도 고쳐졌습니다. – rayd09

관련 문제