Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: info switch python parsing #1317

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,23 @@ matrix:
script:
- docker run -it -v "$(pwd)":/workdir -w /workdir unibeautify/uncrustify -c ci/uncrustify.cfg --check **/**.cxx || exit 0

- language: python
python: "3.7"
env: JOB="Parsing xAODAnaHelpers/HelperClasses.h for InfoSwitches"
dist: xenial
sudo: true
addons:
apt:
packages: libclang-6.0-dev
before_script:
- sudo ln -s /usr/lib/x86_64-linux-gnu/libclang-6.0.so /usr/lib/libclang.so
install:
- pip install clang
script:
- python3 ci/parse_infoswitches.py
- git diff --no-prefix -- data/xAH_infoswitches.json
- git diff --exit-code --name-only -- data/xAH_infoswitches.json

notifications:
email:
on_success: never
Expand Down
83 changes: 83 additions & 0 deletions ci/parse_infoswitches.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/usr/bin/env python3

import clang.cindex
import json
import tempfile

def find_inheritance(node):
"""
If given a class declaration, will grab the inheritance of the class if one exists.
Returns None if no class inheritance.
"""
if node.kind != clang.cindex.CursorKind.CLASS_DECL: return
for c in node.get_children():
if c.kind != clang.cindex.CursorKind.CXX_BASE_SPECIFIER: continue
children = list(c.get_children())
if children[0].get_definition():
return children[0].get_definition().spelling

def infoswitch_parser(node, index=0):
"""
Given a node that is believed to be the initialize() of an InfoSwitch struct,
parse all the tokens, and extract the relevant information for pattern
matching, and yield it back.
"""
tokens = []
for token in node.get_tokens():
if token.spelling == node.spelling: continue
if token.kind in [clang.cindex.TokenKind.COMMENT, clang.cindex.TokenKind.KEYWORD]: continue
if token.spelling in ['(', ')', '=', '{', '}']: continue
# what's the token?
spelling = token.spelling
# chunks of 3 (variable, matcing type, string to match)
if token.kind == clang.cindex.TokenKind.PUNCTUATION:
if token.spelling not in ';': continue
else:
match_type = None
if 'has_exact' in tokens:
match_type = 'has_exact'
elif 'get_working_point' in tokens:
match_type = 'get_working_point'
if match_type:
match_index = tokens.index(match_type)
identifier = tokens[match_index-1]
rest = iter(tokens[match_index:])
for match_type, match_string in zip(rest,rest):
yield [identifier, match_type, match_string]
tokens = []
else:
# strip quotes
if token.kind == clang.cindex.TokenKind.LITERAL: spelling = spelling.replace('"','').replace("'",'')
tokens.append(spelling)
yield []

def find_infoswitches(infoswitches, node):
"""
This top-level entry recursive function goes through all children provided to
identify nodes which are to contain an InfoSwitch struct and then parse out
the appropriate tokens from that node.
"""
if node.spelling == 'initialize' and node.kind == clang.cindex.CursorKind.CXX_METHOD:
infoswitches[node.semantic_parent.spelling] = [token for token in infoswitch_parser(node) if token]
for child in node.get_children():
find_infoswitches(infoswitches, child)

clang.cindex.Config.set_library_path('/usr/lib')
index = clang.cindex.Index.create()

f = tempfile.NamedTemporaryFile(mode='w+', delete=False)
for fname in ['xAODAnaHelpers/HelperClasses.h', 'Root/HelperClasses.cxx']:
with open(fname) as infile:
f.write(infile.read())
tu = index.parse(f.name, args=['-x', 'c++'])
print('Translation unit:', tu.spelling)

infoswitches = {}
find_infoswitches(infoswitches, tu.cursor)

for infoswitch, tokens in infoswitches.items():
print('Tokens for {}'.format(infoswitch))
for var, match_type, match_string in tokens:
print(' -',var, match_type, match_string)

json.dump(infoswitches, open('data/xAH_infoswitches.json', 'w+'), sort_keys=True, indent=4)
Loading