2013-12-15 26 views
20

我正在學習使用Alex和Happy編寫一個小型編譯器。我想維護我的AST節點的行和列信息,以便我可以向用戶提供有意義的錯誤消息。爲了說明我打算如何做,我寫了一個小例子(請參閱下面的代碼),並且我想知道我是否接近問題的方式(將AlexPosn附加到標記,將多態屬性字段附加到AST節點,使用tkPos和astAttr)是很好的風格,或者如果有更好的方法來處理位置信息。使用Alex和Happy管理位置信息

Lexer.x:

{ 
module Lexer where 
} 

%wrapper "posn" 

$white = [\ \t\n] 

tokens :- 

$white+ ; 
[xX] { \pos s -> MkToken pos X } 
"+" { \pos s -> MkToken pos Plus } 
"*" { \pos s -> MkToken pos Times } 
"(" { \pos s -> MkToken pos LParen } 
")" { \pos s -> MkToken pos RParen } 

{ 
data Token = MkToken AlexPosn TokenClass 
      deriving (Show, Eq) 

data TokenClass = X 
       | Plus 
       | Times 
       | LParen 
       | RParen 
        deriving (Show, Eq) 

tkPos :: Token -> (Int, Int) 
tkPos (MkToken (AlexPn _ line col) _) = (line, col) 
} 

Parser.y:

{ 
module Parser where 

import Lexer 
} 

%name simple 
%tokentype { Token } 
%token 
    '(' { MkToken _ LParen } 
    ')' { MkToken _ RParen } 
    '+' { MkToken _ Plus } 
    '*' { MkToken _ Times } 
    x { MkToken _ X } 

%% 

Expr : Term '+' Expr  { NAdd $1 $3 (astAttr $1) } 
    | Term    { $1 } 

Term : Factor '*' Term { NMul $1 $3 (astAttr $1) } 
    | Factor   { $1 } 

Factor : x    { NX (tkPos $1) } 
     | '(' Expr ')' { $2 } 


{ 
data AST a = NX a 
      | NMul (AST a) (AST a) a 
      | NAdd (AST a) (AST a) a 
      deriving (Show, Eq) 

astAttr :: AST a -> a 
astAttr (NX a)  = a 
astAttr (NMul _ _ a) = a 
astAttr (NAdd _ _ a) = a 

happyError :: [Token] -> a 
happyError _ = error "parse error" 
} 

Main.hs:

module Main where 

import Lexer 
import Parser 

main :: IO() 
main = do 
    s <- getContents 
    let toks = alexScanTokens s 
    print $ simple toks 
+1

找到你想要分享的解決方案?想知道同樣的事情 – mfaerevaag

回答

1

我個人會與你所描述的風格很OK 。然而,這是非常手動的,我希望至少提供一個可能更容易管理的替代方案。

如果你看一下documentation for alex wrappers,你會注意到monad和monadstate包裝都包含位置信息。缺點是你現在已經把所有東西都包裝在一個monad中,並且它使解析器稍微複雜化了。但是,通過將其包裝爲monad,解析的結果是Alex a,這意味着您在創建ast節點時可以完全訪問行和列信息。現在,這只是從詞法分析器中刪除了一些鍋爐板,並沒有做更多的事情。

通過這樣做,你也可以隨身攜帶AlexState令牌,但這可能是不必要的。

如果你需要真正幫助固定解析器來處理單子/ monadstate包裝,我寫了一篇關於我如何管理的響應得到它的工作在這裏:How to use an Alex monadic lexer with Happy?