Обход и сопоставление с образцом абстрактного синтаксического дерева

Я создал парсер и лексер с 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 ответов

Другие вопросы по тегам