summaryrefslogtreecommitdiff
path: root/src/api/python/genkinds.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/api/python/genkinds.py')
-rw-r--r--src/api/python/genkinds.py187
1 files changed, 33 insertions, 154 deletions
diff --git a/src/api/python/genkinds.py b/src/api/python/genkinds.py
index c19364559..30ee18708 100644
--- a/src/api/python/genkinds.py
+++ b/src/api/python/genkinds.py
@@ -22,41 +22,22 @@ handle nested '#if 0' pairs.
"""
import argparse
-from collections import OrderedDict
+import os
+import sys
-#################### Default Filenames ################
-DEFAULT_HEADER = 'cvc4cppkind.h'
-DEFAULT_PREFIX = 'kinds'
+# the following command in CVC4/build/src/api/python/CMakeFiles/gen-pycvc4-kinds.dir/build.make
+# cd CVC4/build/src/api/python && /usr/bin/python3 CVC4/src/api/python/genkinds.py ...
+# indicates we are in directory CVC4/build/src/api/python
+# so we use ../../../../src/api to access CVC4/src/api/parsekinds.py
+sys.path.insert(0, os.path.abspath('../../../../src/api'))
-##################### Useful Constants ################
-OCB = '{'
-CCB = '}'
-SC = ';'
-EQ = '='
-C = ','
-US = '_'
-NL = '\n'
+from parsekinds import *
-#################### Enum Declarations ################
-ENUM_START = 'enum CVC4_EXPORT Kind'
-ENUM_END = CCB+SC
+#################### Default Filenames ################
+DEFAULT_PREFIX = 'kinds'
################ Comments and Macro Tokens ############
PYCOMMENT = '#'
-COMMENT = '//'
-BLOCK_COMMENT_BEGIN = '/*'
-BLOCK_COMMENT_END = '*/'
-MACRO_BLOCK_BEGIN = '#if 0'
-MACRO_BLOCK_END = '#endif'
-
-#################### Format Kind Names ################
-# special cases for format_name
-_IS = '_IS'
-# replacements after some preprocessing
-replacements = {
- 'Bitvector' : 'BV',
- 'Floatingpoint': 'FP'
-}
####################### Code Blocks ###################
CDEF_KIND = " cdef Kind "
@@ -126,130 +107,28 @@ cdef kind {name} = kind(<int> {kind})
setattr(kinds, "{name}", {name})
"""
-class KindsParser:
- tokenmap = {
- BLOCK_COMMENT_BEGIN : BLOCK_COMMENT_END,
- MACRO_BLOCK_BEGIN : MACRO_BLOCK_END
- }
-
- def __init__(self):
- self.kinds = OrderedDict()
- self.endtoken = None
- self.endtoken_stack = []
- self.in_kinds = False
-
- def format_name(self, name):
- '''
- In the Python API, each Kind name is reformatted for easier use
-
- The naming scheme is:
- 1. capitalize the first letter of each word (delimited by underscores)
- 2. make the rest of the letters lowercase
- 3. replace Floatingpoint with FP
- 4. replace Bitvector with BV
-
- There is one exception:
- FLOATINGPOINT_ISNAN --> FPIsNan
-
- For every "_IS" in the name, there's an underscore added before step 1,
- so that the word after "Is" is capitalized
-
- Examples:
- BITVECTOR_PLUS --> BVPlus
- APPLY_SELECTOR --> ApplySelector
- FLOATINGPOINT_ISNAN --> FPIsNan
- SETMINUS --> Setminus
-
- See the generated .pxi file for an explicit mapping
- '''
- name = name.replace(_IS, _IS+US)
- words = [w.capitalize() for w in name.lower().split(US)]
- name = "".join(words)
-
- for og, new in replacements.items():
- name = name.replace(og, new)
-
- return name
-
- def ignore_block(self, line):
- '''
- Returns a boolean telling self.parse whether to ignore a line or not.
- It also updates all the necessary state to track comments and macro
- blocks
- '''
-
- # check if entering block comment or macro block
- for token in self.tokenmap:
- if token in line:
- if self.tokenmap[token] not in line:
- if self.endtoken is not None:
- self.endtoken_stack.append(self.endtoken)
- self.endtoken = self.tokenmap[token]
- return True
-
- # check if currently in block comment or macro block
- if self.endtoken is not None:
- # check if reached the end of block comment or macro block
- if self.endtoken in line:
- if self.endtoken_stack:
- self.endtoken = self.endtoken_stack.pop()
- else:
- self.endtoken =None
- return True
-
- return False
-
- def parse(self, filename):
- f = open(filename, "r")
-
- for line in f.read().split(NL):
- line = line.strip()
- if COMMENT in line:
- line = line[:line.find(COMMENT)]
- if not line:
- continue
-
- if self.ignore_block(line):
- continue
-
- if ENUM_END in line:
- self.in_kinds = False
- break
- elif self.in_kinds:
- if line == OCB:
- continue
- if EQ in line:
- line = line[:line.find(EQ)].strip()
- elif C in line:
- line = line[:line.find(C)].strip()
- self.kinds[line] = self.format_name(line)
- elif ENUM_START in line:
- self.in_kinds = True
- continue
-
- f.close()
-
- def gen_pxd(self, filename):
- f = open(filename, "w")
- f.write(KINDS_PXD_TOP)
- # include the format_name docstring in the generated file
- # could be helpful for users to see the formatting rules
- for line in self.format_name.__doc__.split(NL):
- f.write(PYCOMMENT)
- if not line.isspace():
- f.write(line)
- f.write(NL)
- for kind in self.kinds:
- f.write(CDEF_KIND + kind + NL)
- f.close()
- def gen_pxi(self, filename):
- f = open(filename, "w")
- pxi = KINDS_PXI_TOP
- for kind, name in self.kinds.items():
- pxi += KINDS_ATTR_TEMPLATE.format(name=name, kind=kind)
- f.write(pxi)
- f.close()
+def gen_pxd(parser: KindsParser, filename):
+ f = open(filename, "w")
+ f.write(KINDS_PXD_TOP)
+ # include the format_name docstring in the generated file
+ # could be helpful for users to see the formatting rules
+ for line in parser.format_name.__doc__.split(NL):
+ f.write(PYCOMMENT)
+ if not line.isspace():
+ f.write(line)
+ f.write(NL)
+ for kind in parser.kinds:
+ f.write(CDEF_KIND + kind + NL)
+ f.close()
+
+def gen_pxi(parser : KindsParser, filename):
+ f = open(filename, "w")
+ pxi = KINDS_PXI_TOP
+ for kind, name in parser.kinds.items():
+ pxi += KINDS_ATTR_TEMPLATE.format(name=name, kind=kind)
+ f.write(pxi)
+ f.close()
if __name__ == "__main__":
@@ -270,5 +149,5 @@ if __name__ == "__main__":
kp = KindsParser()
kp.parse(kinds_header)
- kp.gen_pxd(kinds_file_prefix + ".pxd")
- kp.gen_pxi(kinds_file_prefix + ".pxi")
+ gen_pxd(kp, kinds_file_prefix + ".pxd")
+ gen_pxi(kp, kinds_file_prefix + ".pxi")
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback