File indexing completed on 2022-10-04 15:12:36

0001 #!/usr/bin/env python
0002 #
0003 # This file is part of KDevelop
0004 #
0005 # Copyright 2016 Anton Anikin <anton.anikin@htower.ru>
0006 #
0007 # This program is free software; you can redistribute it and/or
0008 # modify it under the terms of the GNU General Public
0009 # License as published by the Free Software Foundation; either
0010 # version 2 of the License, or (at your option) any later version.
0011 #
0012 # This program is distributed in the hope that it will be useful,
0013 # but WITHOUT ANY WARRANTY; without even the implied warranty of
0014 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0015 # General Public License for more details.
0016 #
0017 # You should have received a copy of the GNU General Public License
0018 # along with this program; see the file COPYING.  If not, write to
0019 # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0020 # Boston, MA 02110-1301, USA.
0021 
0022 from xml.sax.saxutils import escape, unescape
0023 import pyparsing as pp
0024 import string
0025 import re
0026 
0027 # escape() and unescape() takes care of &, < and >.
0028 html_escape_table = {
0029     '"': "&quot;",
0030     "'": "&apos;"
0031     }
0032 
0033 html_unescape_table = {v:k for k, v in html_escape_table.items()}
0034 
0035 def html_escape(text):
0036     return escape(text, html_escape_table)
0037 
0038 def html_unescape(text):
0039     return unescape(text, html_unescape_table)
0040 
0041 def parseFile(fileName):
0042     EOL = pp.LineEnd().suppress()
0043     endTag = pp.Literal('**Compliance:**')
0044 
0045     ruleTitle = pp.Regex(r'[A-Z]\d{3}') + pp.White().suppress() + pp.restOfLine() + pp.ZeroOrMore(EOL)
0046     ruleTitle.setParseAction(
0047         lambda t: '\ntitles[type("%s")] = "%s";\nexplanations[type("%s")] =\n<html>\n%s: %s' %
0048             (t[0], html_unescape(t[1]),
0049              t[0], t[0], t[1])
0050     )
0051 
0052     ruleEnd = endTag + pp.restOfLine() + pp.ZeroOrMore(EOL)
0053     ruleEnd.setParseAction( lambda t: '%s\n</html>' % (t[0] + t[1]) )
0054 
0055     hline = pp.Regex(r'-{3,}') + pp.ZeroOrMore(EOL)
0056     hline.setParseAction( lambda t: '<hr>' )
0057 
0058     textLine  = pp.LineStart() + pp.NotAny('~') + pp.NotAny(endTag) + pp.NotAny(EOL) + pp.restOfLine() + EOL
0059     textBlock = pp.OneOrMore(textLine) + pp.ZeroOrMore(EOL)
0060     textBlock.setParseAction( lambda t: '%s\n<br><br>' % ' '.join(t) )
0061 
0062     codeTag   = pp.Regex(r'~~~~.*') + EOL
0063     codeLine  = pp.LineStart().leaveWhitespace() + pp.NotAny(codeTag) + pp.restOfLine() + pp.ZeroOrMore(EOL)
0064     codeBlock = codeTag.suppress() + pp.OneOrMore(codeLine) + codeTag.suppress() + pp.ZeroOrMore(EOL)
0065 
0066     parametersLine = pp.Literal(' ').leaveWhitespace() + pp.restOfLine() + EOL
0067     parametersLine.setParseAction( lambda t: ''.join(t) )
0068     parametersBlock = pp.OneOrMore(parametersLine) + pp.ZeroOrMore(EOL)
0069 
0070     listLine = pp.Literal('-') + pp.restOfLine() + EOL
0071     listLine.setParseAction( lambda t: ("&#8226;"+t[1]).replace('`', '') )
0072     listBlock = pp.OneOrMore(listLine) + pp.ZeroOrMore(EOL)
0073 
0074     preBlock = codeBlock ^ parametersBlock ^ listBlock
0075     preBlock.setParseAction( lambda t: '<pre>\n%s\n</pre>' % '\\n\n'.join(t) )
0076 
0077     rule = ruleTitle + hline + pp.OneOrMore(preBlock ^ textBlock) + ruleEnd
0078     rule.setParseAction( lambda t: '\n'.join(t) )
0079 
0080     rules = pp.Literal("Rules").suppress() + pp.Literal("=====").suppress() + EOL + pp.OneOrMore(rule)
0081     rules.setParseAction( lambda t: '\n'.join(t) )
0082 
0083     t = open(fileName, 'r').read()
0084 
0085     # escaping
0086     t = html_escape(t)
0087     t = re.sub(r'\\', r'\\\\', t)
0088 
0089     t = rules.parseString(t)[0]
0090 
0091     # add bold and italic
0092     t = re.sub(r'\*\*(.+)\*\*', r'<b>\1</b>', t)
0093     t = re.sub(r'\*(.+)\*', r'<i>\1</i>', t)
0094 
0095     # remove <br> before and after <pre> blocks
0096     t = re.sub(r'<br><br>\n<pre>', r'<pre>', t)
0097     t = re.sub(r'</pre>\n<br><br>', r'</pre>', t)
0098 
0099     # 'stringify' lines
0100     t = re.sub(r'(.+)', r'"\1"', t)
0101 
0102     # fix begin ane end of code
0103     t = re.sub(r'</html>"', r'</html>";', t)
0104     t = re.sub(r'"(titles\[.*)"', r'\1', t)
0105     t = re.sub(r'"(explanations\[.*)"', r'\1', t)
0106 
0107     #r = re.sub(r'^"', r'    "', r, flags = re.MULTILINE)
0108 
0109     return t
0110 
0111 prefix=\
0112     '// This file is generated by \'rules_db_create.py\' from \'Rules.md\'.\n' \
0113     '// Please don\'t edit it\n\n' \
0114     '#include "rules.h"\n\n' \
0115     '#include <QString>\n\n' \
0116     'namespace verapp\n' \
0117     '{\n\n' \
0118     'namespace rules\n' \
0119     '{\n\n' \
0120     'void initDb(QString* titles, QString* explanations)\n' \
0121     '{\n'
0122 
0123 suffix='\n\n}\n\n}\n\n}\n'
0124 
0125 f = open('rules_db.cpp', 'w')
0126 f.write(prefix)
0127 f.write(parseFile('Rules.md'))
0128 f.write(suffix)