2013-05-08 1 views
5

ANTLR이 전체 파일을 메모리에로드하지 않도록 지시 할 수 있습니까? 하나씩 규칙을 적용하고 파일 읽기와 함께 노드의 최상위 목록을 순차적으로 생성 할 수 있습니까? 또한 분석 된 노드를 어떻게 든 삭제할 수 있습니까?대용량 파일을 ANTLR로 구문 분석 할 수 있습니까?

+0

왜 필요합니까? 아마도 충분한 메모리를 위해 거대한 트리를 메모리에 구축 할 수 있습니다. –

+3

분명히 내 파일이 메모리보다 큽니다 –

+0

예? 파일 크기가 얼마나 큽니까? 그리고 그것이 정말로 큰 것이면, 그것을 처리하는 데 얼마나 많은 가치가 있습니까? 충분한 가치가 없다면 문제를 해결하는 데는 거의 중요하지 않습니다. 충분한 가치가있는 경우 큰 리소스 (시간, 공간, 사용자 정의 도구)가 옵션으로 테이블에 있어야합니다. –

답변

10

예, 사용할 수 있습니다

  • UnbufferedCharStream을 (렉서로 전달) 캐릭터 스트림
  • UnbufferedTokenStream 위해 (파서에 전달) 토큰 스트림
    • 이 토큰 스트림 구현은 '아무튼 위해 t는 토큰 채널에서 차별화되므로 구문 분석기로 보내지 않아야하는 렉서 규칙의 명령으로 ->channel(HIDDEN) 대신 ->skip을 사용해야합니다.
  • 파서에서 setBuildParseTree(false)으로 전화를 걸면 전체 파일에 대해 거대한 구문 분석 트리가 생성됩니다.

몇 가지 추가 해설 편집 :

  • 내가 UnbufferedCharStream 확인하는에 작업 꽤 넣어 UnbufferedTokenStream는 특히 mark, release과 관련, 가장 "제정신"방식으로 가능한 운영 seekgetText 방법. 필자의 목표는 사용되지 않는 메모리를 해제하는 스트림의 기능을 손상시키지 않고 가능하면 해당 메서드의 많은 기능을 유지하는 것이 었습니다.
  • ANTLR 4는 참된 무제한 미리보기를 허용합니다. 문법에 결정을 내리기 위해 EOF를 미리 생각해야한다면 전체 입력을 메모리에로드하는 것을 피할 수 없습니다. 문법을 작성할 때 이러한 상황을 피하기 위해 세심한주의를 기울여야합니다.
+0

숨겨진 토큰을 건너 뛰기 위해 UnbufferedTokenStream의 하위 클래스를 만들면 (필자가 fill 메서드에서 수행 한) 건너 뛰기를 사용하도록 문법을 수정하지 않아도됩니다. UnbufferedTokenStream이 필터링 옵션을 제공하면 좋을 것입니다. –

+0

생성 된 파서의 메서드를 직접 사용하여 최상위 구문을 점진적으로 구문 분석하는 경우 setBuildParseTree (true)를 사용하는 것이 좋습니다. –

+0

마지막으로,이 대답은 Java 백엔드에만 적용되는 것처럼 보입니다. 예를 들어 필자는 Python API에서 비교 가능한 클래스를 볼 수 없다. –

3

Antlr.org의 어딘가에 묻혀있는 위키 페이지가 있습니다. 지금은 찾을 수없는 것 같습니다.

사실상, 렉서는 표준 InputStream 인터페이스, 특히 ANTLRInputStream.java를 사용하여 데이터를 읽습니다. 일반적인 구현은 전체 입력 데이터 파일을 메모리로 미리 읽어들입니다. 당신이해야 할 일은 필요에 따라 소스 파일에서 읽는 버퍼링 된 자신의 버전 ("ANTLRBufferedFileStream.java")을 작성하는 것입니다. 또는 표준 BufferedInputStream/FileInputStream을 AntlrInputStream의 데이터 소스로 설정하면됩니다.

Antlr4는 제한없는 미리보기를 수행 할 가능성이 있습니다. 정상적인 작동에서 적당히 크기가 조정 된 버퍼의 문제는 아닙니다. 파서가 오류 복구를 시도 할 때 더 자주 발생합니다. Antlr4는 오류 복구 전략을 조정할 수 있으므로 문제를 관리 할 수 ​​있습니다.

추가 세부 사항 : 사실상

, ANTLR은 풀 파서를 구현한다. 첫 번째 파서 규칙을 호출하면 구문 분석기는 입력 스트림에서 문자 데이터를 요청하는 렉서 (lexer)에서 토큰을 요청합니다. 파서/렉서 인터페이스는 버퍼링 된 토큰 스트림 (보통은 BufferedTokenStream)에 의해 구현됩니다.

구문 분석 트리는 토큰의 트리 데이터 구조에 불과합니다. 음, 훨씬 더 많지만 데이터 크기 측면에서는 그렇지 않습니다. 각 토큰은 일반적으로 토큰 정의와 일치하는 입력 데이터 스트림의 단편으로 뒷받침되는 INT 값입니다. 렉서 자체는 lex'd 입력 문자 스트림의 전체 사본을 메모리에 보관할 필요가 없습니다. 그리고 토큰 텍스트 조각은 0이 될 수 있습니다. 렉서에 대한 중요한 메모리 요구 사항은 버퍼링 된 파일 입력 스트림이 주어진 경우 입력 문자 스트림 룩어 헤드 스캔입니다.

필요에 따라 100GB + 입력 파일이있는 경우에도 메모리 내 구문 분석 트리가 작을 수 있습니다.

더 도움을 받으려면 Antlr에서 무엇을하려고하는지 더 자세히 설명하고 최소 중요 메모리 요구 사항을 정의해야합니다. 그것은 어떤 추가 전략을 추천 할 수 있는지 안내 할 것입니다. 예를 들어, 소스 데이터를 사용할 수있는 경우, 렉서 (lexer)에서 처리 할 소스 데이터의 다른 부분을 subselect 할 때마다 여러 렉서/파서 실행을 사용할 수 있습니다. 빠른 디스크에서도 파일 읽기 및 DB 쓰기와 비교할 때 Antlr 실행은 거의 눈에 띄지 않습니다.

+1

스트림을 다시 구현하는 것이 어떻게 도움이되는지 이해하지 못합니다. ANTLR은 전체 트리를 메모리에 생성하지 않습니까? 이것이 내가 생각하는 문제이다. –

+0

답변 됨. – GRosenberg

+1

전체 트리가 메모리에 남아있는 동안 접근 방식이 문자 스트림에서만 메모리를 비울 수 있다는 것을 확인할 수 있습니까? –

관련 문제