2016-07-15 2 views
2

Я пытался создать Haskell AST, чтобы узнать, какие AST-узлы существуют на строках исходного файла. До сих пор я использую Language.Haskell.Parser и Language.Haskell.Syntax, которые, похоже, работают достаточно хорошо. Я могу сгенерировать дерево, а затем пропустить через каждую его часть, вывести номер строки, используя srcLine loc (где loc - это SrcLoc).Haskell AST Неполная информация о местоположении

Однако, я бегу в проблемы, когда разобранный файл выглядит следующим образом:

ФАЙЛ 1

1| rangeLeq :: Integer -> NonnegRange 
2| rangeLeq n = 
3| Range BoundaryBelowAll (BoundaryAbove n) 

Файл легко можно было написано так:

FILE 2

1| rangeLeq :: Integer -> NonnegRange 
2| rangeLeq n = Range BoundaryBelowAll (BoundaryAbove n) 

Проблема заключается в том, что анализатор видит эти два эквивалента. Он не присваивает SrcLoc всему, только определенным частям AST. Так что я в конечном итоге является следующим выводом как для файла 1 и файла 2:

line 1: HsTypeSig 
     |--HsIdent (rangeLeq) 
     |--HsQualType 
      |--HsContext 
      |--HsTyFun 
       |--HsTyCon 
       |--HsUnQual 
        |--HsIdent (Integer) 
       |--HsTyCon 
       |--HsUnQual 
        |--HsIdent (NonnegRange) 
line 2: HsMatch 
     |--HsIdent (rangeLeq) 
     |--HsPVar 
      |--HsIdent (n) 
     |--HsUnGuardedRhs 
      |--HsApp 
       |--HsApp 
       |--HsCon 
        |--HsUnQual 
         |--HsIdent (Range) 
       |--HsCon 
        |--HsUnQual 
         |--HsIdent (BoundaryBelowAll) 
       |--HsParen 
       |--HsApp 
        |--HsCon 
         |--HsUnQual 
          |--HsIdent (BoundaryAbove) 
        |--HsVar 
         |--HsUnQual 
          |--HsIdent (n) 

Так что вопрос здесь в том, что нет никакой информации местоположения на большинстве узлов, поэтому он видит определение функции (HsMatch) как одна строка. В случае непонятности, HsMatch представляет rangeLeq n = Range BoundaryBelowAll (BoundaryAbove n) в коде. Поскольку единственная часть AST, которая поставляется с SrcLoc, является самой HsMatch, парсер предполагает, что все части HsMatch находятся на одной линии.

tl;dr Как я могу получить правильный синтаксический анализ, так что строки в исходном файле, которые разделены без необходимости, по-прежнему будут помечены соответствующей строкой? Id est, я хочу, чтобы синтаксис отображал каждый узел с SrcLoc, а не только определенные узлы.

+0

Если модули Language.Haskell. * Не работают на вас, возможно, попробуйте библиотеки за этим проектом: http://haskelltools.org Похоже, их код доступен как в Hackage, так и в github. – ErikR

+0

Невозможно - [большинство] (https://hackage.haskell.org/package/haskell-src-1.0.2.0/docs/Language-Haskell-Syntax.html#t:HsExp) конструкторов выражений просто не содержат «SrcLoc». Я не думаю, что этот парсер нацелен на то, чтобы дать пользователю полностью точные номера строк - даже ghc не делает это совершенно правильным все время. – user2407038

+0

Я понимаю, что конструкторы не содержат информацию SrcLoc. То, что я ищу, - это либо другой парсер, либо альтернативный метод определения номеров строк. – nullromo

ответ

0

haskell-src-exts имеет пометку местоположения (SrcSpanInfo) по every subexpression; у него должно быть достаточно деталей, чтобы устранить ваши два примера.

+0

Использование 'Language.Haskell.Exts.Parser.parse', я все равно получаю ту же проблему. Я получаю «Модуль», а не «HsModule», и информация о местоположении на каждом узле по-прежнему отсутствует. – nullromo