遍历和模式匹配抽象语法树

时间:2018-03-17 23:39:46

标签: parsing haskell pattern-matching abstract-syntax-tree happy

我用Alex和Happy构建了一个解析器和词法分析器,它生成和抽象我正在解析的语言(Solidity)的语法树。我现在的问题是如何正确地遍历和匹配语言的某些方面。目的是为了 创建一个规则引擎,它将对生成的AST执行代码分析,检查特定问题,如不正确使用函数,危险调用或缺少某些元素。

这是我的数据的布局,其中输出为AST。 (这不是完整的AST,只是一个快照

 data SourceUnit = SourceUnit PragmaDirective
                  | ImportUnit ImportDirective 
                  | ContractDef ContractDefinition
                  deriving (Show, Eq, Data, Typeable, Ord)

  -- Version Information
  data PragmaDirective = PragmaDirective PragmaName Version Int
                        deriving(Show, Eq, Data, Typeable, Ord)

  data Version = Version String 
                deriving (Show, Eq, Data, Typeable, Ord)

  data PragmaName = PragmaName Ident
                    deriving(Show, Eq, Typeable, Data, Ord)

  data PragmaValue = PragmaValue Dnum
                    deriving(Show, Eq, Data, Typeable, Ord)
  -- File imports/Contract Imports
  data ImportDirective = ImportDir String
                      | ImportMulti Identifier Identifier Identifier String 
                        deriving (Show, Eq, Data, Typeable, Ord)

  -- The definition of an actual Contract Code Block
  data ContractDefinition = Contract Identifier [InheritanceSpec] [ContractConts]
                            deriving (Show, Eq, Data, Typeable, Ord)

  data ContractConts = StateVarDec StateVarDeclaration
               | FunctionDefinition FunctionDef
               | UsingFor UsingForDec
               deriving (Show, Eq, Data, Typeable, Ord)

我目前的思路是通过将[SourceUnit]传递给函数并匹配特定情况来使用模式匹配。例如,以下函数匹配代码并返回状态变量声明的数据类型。

  getStateVar :: [SourceUnit] -> Maybe StateVarDeclaration
  getStateVar [SourceUnit _ , ContractDef (Contract _ _ [StateVarDec x]) ] = Just x
  getStateVar _ = Nothing

这会输出以下内容,这部分是我需要的。不幸的是,语言可能包含多个合同声明,并且有多个状态变量声明,因此我认为完全不可能以这种方式匹配它。

 Main> getStateVar $ runTest "pragma solidity ^0.5.0; contract test { address owner = msg.send;}"
  Just (StateVariableDeclaration (ElementaryTypeName (AddrType "address")) [] (Identifier "owner") [MemberAccess (IdentExpression "msg") "." (Identifier "send")])

我已经阅读了一些有关泛型编程和“废弃样板”的内容,但我并不完全了解它是如何工作的,或者是实现它的最佳方法。

问题是,我是否在这种模式匹配方面走上正轨,还是有更好的选择?

0 个答案:

没有答案