diff --git a/doc/manual/generate_latex.py b/doc/manual/generate_latex.py index 884fef6..41841ba 100644 --- a/doc/manual/generate_latex.py +++ b/doc/manual/generate_latex.py @@ -1,332 +1,251 @@ +import os + + +def protectString(_str): + _str = _str.replace("\n\n", 'qwertzuiop') + _str = _str.replace("\n", "") + _str = _str.replace('qwertzuiop', "\n\n").strip() + return _str def makeTypeString(doc): - # // std:: cerr << "doing " << doc.c_type << std: : endl + if 'c_type' not in doc: + return "NOT YET ACCESSIBLE" + return doc['c_type'] + # boost:: smatch what # # const boost:: regex my_filter_quantity_plus_brackets("Quantity<([^,]+),?(.*)>\\[(.*)\\]") # # bool res = boost:: regex_match(doc.c_type, what, my_filter_quantity_plus_brackets) # # if (res){ # std: : cerr << doc.filename.native() << ":0:Error the type " # << doc.c_type << " is invalid" << std: : endl # exit(EXIT_FAILURE) # } # # const boost:: regex my_filter_quantity("Quantity<([^,]+),([^,]+)>") # res = boost:: regex_match(doc.c_type, what, my_filter_quantity) # # if (res) { # // std: : cerr << "AAAAAAA" # const boost: : regex my_filter2("Keyword\\s\\[(.*)\\]") # boost:: smatch what2 # res = boost: : regex_match(doc.type, what2, my_filter2) # if (!res) return doc.c_type # # // std: : cerr << "AAAAAAA " + doc.type << std: : endl # std: : string ret = what2.str(1) # if (what.str(2) != "") ret += " x " # ret += what.str(1) # return ret # } # # const boost:: regex my_filter_single_quantity("Quantity<(.*)>") # res = boost:: regex_match(doc.c_type, what, my_filter_single_quantity) # if (res) { # // std: : cerr << "BBBBBBBBB" # return what.str(1) # } # # const boost:: regex my_filter_brackets("(.*)\\[(.*)\\]") # res = boost: : regex_match(doc.c_type, what, my_filter_brackets) # if (res) { # // std: : cerr << "CCCCCCCC" # const boost: : regex my_filter2("Keyword\\s\\[(.*)\\]") # boost:: smatch what2 # res = boost: : regex_match(doc.type, what2, my_filter2) # if (!res) return doc.c_type # # std: : string ret = what2.str(1) # if (what.str(2) != "") ret += " x " # ret += what.str(1) # return ret # } # # return doc.c_type # } - pass - - -def removeUnderscore(_str): - - # const boost:: regex my_filter("\\\\_") - # - # std:: string copy_str = - # boost:: regex_replace(str, my_filter, "", - # boost: : match_default | boost: : format_all) - # - # return copy_str - pass + raise def getSubPath(_file): - # boost: : filesystem: : path: : iterator end = file.end() - # boost: : filesystem: : path: : iterator begin = file.begin() - # - # for ( - # end != begin - # - -end) { - # if (end -> native() == "src"){ - # break - # } - # } - # if (end == file.end()){ - # std:: cerr << "problem in the file structure" << std: : endl - # exit(EXIT_FAILURE) - # } - # - # begin = end - # end = file.end() - # - # boost: : filesystem: : path p - # - # for ( - # begin != end - # + +begin) { - # p /= *begin - # } - # return protectString(p.native()) - pass - - -def getMainSection(_file): - - # boost:: filesystem: : path: : iterator end = file.end() - # boost:: filesystem: : path: : iterator begin = file.begin() - # - # for ( - # end != begin - # - -end) { - # if (end -> native() == "src"){ - # break - # } - # } - # if (end == file.end()){ - # std: : cerr << "problem in the file structure" << std: : endl - # exit(EXIT_FAILURE) - # } - # + +end - # - # return end -> native() - pass - - -def makeLatexFunction(fout, func_name, - params): - - # fout << "\\" << func_name - # for (UInt i=0 - # i < params.size() - # + +i) { - # fout << "{" << params[i] << "}" - # } - # fout << std:: endl << std: : endl - pass - - -def generateSyntax(fout, doc): - # std:: string func_name = removeUnderscore(std: : string("syntax") + getMainSection(doc.filename)) - # - # std: : vector < std: : string > params - # params.push_back(doc.name) - # makeLatexFunction(fout, func_name, params) - pass - - -def generateLatexCall(fout, func): - - # std: : vector < std: : string > params - # makeLatexFunction(fout, func, params) - pass - + dirs = _file.split('/') + i = 0 + for i in range(0, len(dirs)): + if dirs[i] == 'src': + break + ++i -def generateLatexCall(fout, func, arg1): + if i == len(dirs): + raise RuntimeError("problem in the file structure") - # std: : vector < std: : string > params - # params.push_back(arg1) - # makeLatexFunction(fout, func, params) - pass + return os.path.join(*dirs[i:]) -def generateLatexCall(fout, func, arg1, arg2): - - # std: : vector < std: : string > params - # params.push_back(arg1) - # params.push_back(arg2) - # makeLatexFunction(fout, func, params) - pass - - -def generateLatexCall(fout, func, arg1, arg2, arg3): +def getMainSection(_file): - # std: : vector < std: : string > params - # params.push_back(arg1) - # params.push_back(arg2) - # params.push_back(arg3) - # makeLatexFunction(fout, func, params) - pass + dirs = _file.split('/') + i = 0 + for i in range(0, len(dirs)): + if dirs[i] == 'src': + break + ++i + if i == len(dirs): + raise RuntimeError("problem in the file structure") -def generateLatexSection(fout, title, label, level): + return dirs[i+1] - # std: : vector < std: : string > params - # params.push_back(removeUnderscore(label)) - # params.push_back(title) - # params.push_back(label) - # - # makeLatexFunction(fout, "my"+level, params) - pass +def generateSyntax(fout, doc, level): + func_name = "syntax " + getMainSection(doc['filename']) + params = [doc['name']] + # fout.write(f"{func_name} {params}\n\n") + generateLatexSection(fout, "**Syntax**", level+1) + fout.write(f"TODO\n\n") -def generateKeywordsLatexBloc(fout, keywords): - # if (keywords.size() == 0) return - # - # std:: string key_list = keywords[0].name - # for(UInt i=1 - # i < keywords.size() - # + +i) - # key_list += ", " + keywords[i].name - # - # generateLatexCall(fout, "keywordlist", key_list) - # - # for (UInt i=0 - # i < keywords.size() - # + +i){ - # LMDocData & keyword = keywords[i] - # - # std: : vector < std: : string > params - # params.push_back(keyword.name) - # params.push_back(makeTypeString(keyword)) - # params.push_back(keyword.c_type) - # // std:: cerr << keyword.name << " " << keyword.c_type << std: : endl - # params.push_back(keyword.var_name) - # params.push_back(keyword.description) - # if (keyword.defaults == "") - # params.push_back("\\textbf{MANDATORY}") - # else - # params.push_back("Default: " + keyword.defaults) - # makeLatexFunction(fout, "keyword", params) - # } - pass +def generateLatexSection(fout, title, level): + # params = [label, level, title, label] -def generateHeritanceList(doc, hlist): + if level == 0: + sep = '=' + elif level == 1: + sep = '-' + elif level == 2: + sep = '`' + elif level == 3: + sep = '~' + elif level == 4: + sep = '~' + else: + raise RuntimeError("what the fuck ", level) - # std:: vector < std: : string > & heritance = doc.heritance - # for (UInt i=0 - # i < heritance.size() - # + +i) { - # std:: string class_name = heritance[i] - # if (sorted_by_name.count(class_name) == 0){ - # std: : cout << doc.filename.native() << ":0:" - # << "Unknown heritance " << class_name << std: : endl - # exit(EXIT_FAILURE) - # } - # hlist[class_name] += 1 - # // std:: cerr << "hlist[" << class_name << "] = " << hlist[class_name] << std: : endl - # LMDocData & herit = sorted_by_name[class_name] - # std:: stringstream sstr - # generateHeritanceList(herit, hlist) - # } - pass + fout.write(f''' +{title} +{sep*len(title)} +''') -def generateHeritance(fout, doc, hlist): +def generateKeywordsLatexBloc(fout, keywords, level): - # std:: vector < std: : string > & heritance = doc.heritance - # for (UInt i=0 - # i < heritance.size() - # + +i) { - # std:: string class_name = heritance[i] - # if (sorted_by_name.count(class_name) == 0){ - # std: : cout << doc.filename.native() << ":0:" - # << "Unknown heritance " << class_name << std: : endl - # exit(EXIT_FAILURE) - # } - # if (!hlist.count(class_name)) { - # std: : cerr << "internal error" << std: : endl - # exit(EXIT_FAILURE) - # } - # if (hlist[class_name] > 1){ - # hlist[class_name] -= 1 - # // std: : cerr << "not outputing " << class_name - # // << " since hlist[" << class_name << "] = " << hlist[class_name] << std: : endl - # continue - # } - # // std:: cerr << "outputing " << class_name - # // << " since hlist[" << class_name << "] = " << hlist[class_name] << std:: endl - # - # LMDocData & herit = sorted_by_name[class_name] - # std:: stringstream sstr - # sstr << class_name << "[\\ref{" << - # removeUnderscore(class_name) << "}]" - # generateLatexCall(fout, "heritance", sstr.str()) - # generateKeywordsLatexBloc(fout, herit.children) - # generateHeritance(fout, herit, hlist) - # } - pass + if not keywords: + return + key_list = ", ".join([k['name'] for k in keywords]) -def generateClassInfo(fout, doc): + generateLatexSection(fout, "**Keywords** " + f"({key_list})", level+1) + fout.write("\n\n\n") - # // get heritance info - # std:: map < std: : string, UInt > hlist - # generateHeritanceList(doc, hlist) - # // std: : map < std: : string, UInt > : : iterator it = hlist.begin() - # // std: : map < std: : string, UInt > : : iterator end = hlist.end() - # - # // std:: cerr << "4 " << doc.name << " heritance is " << std: : endl - # // while(it != end){ - # // std:: cerr << it -> first << ": " << it -> second << std: : endl - # // ++it - # //} - # std:: string & description = doc.description - # - # if (description != "") generateLatexCall(fout, "description", description) - # generateSyntax(fout, doc) - # if (doc.example != "" & & doc.example.find("NONE") == std: : string: : npos) - # generateLatexCall(fout, "example", doc.example) - # generateLatexCall(fout, "file", getSubPath(doc.filename)) - # - # generateKeywordsLatexBloc(fout, doc.children) - # generateHeritance(fout, doc, hlist) - pass + for i, keyword in enumerate(keywords): + name = keyword['name'] + description = protectString(keyword['description']) -def generateLatex(fout, sorted_by_section, sorted_by_name, level='root'): + default = "*MANDATORY*" + # params = [keyword['name'], makeTypeString(keyword), + # # keyword['var_name'], + # ] - print('AAAA', sorted_by_section) - # this -> sorted_by_name = sorted_by_name - # - if len(sorted_by_section.children): - if level != "root": - generateLatexSection(fout, sorted_by_section.name, - sorted_by_section.name, level) - level = "sub" + level + if 'defaults' not in keyword: + default = "(**MANDATORY**)" else: - level = "section" - - for name, child in sorted_by_section.children: - - generateLatex(fout, child, sorted_by_name, level) + default = f"Default: {keyword['defaults']}" + + fout.write(f""" +- **{name}** : + {description}. {default} + +""") + + +def generateHeritanceList(doc, hlist, sorted_by_name): + + heritance = doc['heritance'] + for i, class_name in enumerate(heritance): + if class_name not in sorted_by_name: + print(doc['filename'] + ":0:" + + "Error: Unknown heritance " + class_name) + continue + if class_name not in hlist: + hlist[class_name] = 0 + hlist[class_name] += 1 + print(f"hlist[{class_name}] = {hlist[class_name]}") + herit = sorted_by_name[class_name] + generateHeritanceList(herit, hlist) + + +def generateHeritance(fout, doc, hlist, sorted_by_name): + + heritance = doc['heritance'] + for i, class_name in enumerate(heritance): + if class_name not in sorted_by_name: + print(doc['filename'] + ":0:" + + "Error: Unknown heritance " + class_name) + continue + if class_name not in hlist: + print("internal error") + continue + if hlist[class_name] > 1: + hlist[class_name] -= 1 + print("not outputing " + class_name, + "since hlist[" + class_name + "] = " + hlist[class_name]) + herit = sorted_by_name[class_name] + sstr = class_name + "[\\ref{" + class_name + "}]" + fout.write("heritance" + sstr) + fout.write(herit.children) + fout.write(herit, hlist) + + +def generateClassInfo(fout, doc, sorted_by_name, level): + + # get heritance info + hlist = {} + generateHeritanceList(doc, hlist, sorted_by_name) + + print("4 " + doc['name'] + " heritance is") + for k, v in hlist.items(): + print(k + ":", v) + + description = protectString(doc['description'].strip()) + + generateLatexSection(fout, "**Description**", level+1) + if description != "": + fout.write(f"{description}\n\n") + generateSyntax(fout, doc, level) + if doc['example']: + generateLatexSection(fout, "**Examples**", level+1) + print('AAAA', doc['example']) + examples = doc['example'][0].strip().replace( + '\n', '').split(r"COMPUTE") + print('AAAA', examples) + for ex in examples[1:]: + print(ex) + fout.write('- COMPUTE ' + ex + "\n") + + generateLatexSection( + fout, "**File** " + f"{getSubPath(doc['filename'])}", level+1) + + generateKeywordsLatexBloc(fout, doc['children'], level) + generateHeritance(fout, doc, hlist, sorted_by_name) + + +def generateLatex(fout, sorted_by_section, sorted_by_name, level=0): + + if sorted_by_section['children']: + if level != 0: + generateLatexSection( + fout, sorted_by_section['name'], level) + fout.write("\n------------\n") + + for name, child in sorted_by_section['children'].items(): + generateLatex(fout, child, sorted_by_name, level+1) else: - for name, data in sorted_by_section.data: - - title = data.name - generateLatexSection(fout, title, data.filename, level) - generateClassInfo(fout, data) - pass + for data in sorted_by_section['data']: + generateLatexSection(fout, data['name'], level) + generateClassInfo(fout, data, sorted_by_name, level) + fout.write("\n------------\n") diff --git a/doc/manual/libmultiscale_doc_parser.py b/doc/manual/libmultiscale_doc_parser.py index 32cd273..f7791ad 100644 --- a/doc/manual/libmultiscale_doc_parser.py +++ b/doc/manual/libmultiscale_doc_parser.py @@ -1,372 +1,373 @@ #!/usr/bin/env python3 import pyparsing as pp from attrdict import AttrDict def test_parse(parser, to_test): if __name__ != "__main__": return for _str in to_test: try: res = pp.Combine(parser).parseString(_str) except pp.ParseException as e: print('error while parsing: ', _str, '\n', e) raise e except pp.ParseSyntaxException as e: print('error while parsing: ', _str, '\n', e) raise e print(res, _str) if res[0] != _str.replace(" ", ""): raise RuntimeError('error while parsing: ', _str, res[0]) ################################################################ # Grammar rules for C++ expressions ################################################################ _ref = pp.Literal('&') _star = pp.Literal('*') _plus = pp.Literal('+') _div = pp.Literal('/') _minus = pp.Literal('-') ws = pp.White() _operator = _star | _plus | _div | _minus _float = pp.Combine( pp.Regex(r"[+-]?\d+(:?\.\d*)?(:?[eE][+-]?\d+)?") + pp.Optional('u')) _integer = _float lpar = pp.Literal("(") rpar = pp.Literal(")") lcurl = pp.Literal("{") rcurl = pp.Literal("}") lsqr = pp.Literal("[") rsqr = pp.Literal("]") ltri = pp.Literal('<') rtri = pp.Literal('>') _l_brackets = lpar | lcurl | lsqr _r_brackets = rpar | rcurl | rsqr _this = pp.Literal('this->') _var_name = pp.Word(pp.alphas, pp.alphanums + '_:') _expr = pp.Forward() _term = pp.Optional(_minus) + ((pp.Optional(_this) + _var_name) | _float | pp.Group(lpar - _expr - rpar)) _expr << ((_term + pp.ZeroOrMore(_operator - _term)) | (_star - _term) | (_ref - _term) | pp.QuotedString('"', unquoteResults=False) | pp.QuotedString('\'', unquoteResults=False) ) test_parse(_float, ["2", "2.", "2.2", "2E-3", "-2", "+2", "+2.e-3"]) test_parse(_expr, ["2", "-2*2", "2/4", "toto", "toto*2", "std::toto", "this->toto", "* toto", "& toto", '"toto"', 'dim * 2']) ################################################################ # Grammar rules for C++ types ################################################################ _template = pp.Forward() _type = pp.Combine(_var_name + pp.Optional(_template)) _template <<= ( ltri - pp.Optional((_type | _integer) + pp.Optional(_ref | _star)) + pp.ZeroOrMore(pp.Literal(',') - (_type | pp.Word(pp.nums))) - rtri) test_parse(_type, [ 'std::map>', 'int', 'vector<2>', 'list', 'Vector<2u>']) ################################################################ # Grammar rules for C++ call ################################################################ _arguments = pp.Forward() _constructor = _type + _l_brackets - _arguments - _r_brackets _arg = pp.Combine(_constructor | _expr | _float) _arguments <<= ( pp.Optional(_arg) + pp.ZeroOrMore(pp.Literal(',') - _arg)) test_parse(_constructor, [ 'int()', 'std::map>{}', 'vector<2>()', 'list(3,4)', 'Vector<2u>{2,4}']) test_parse(_arguments, ['2', 'toto, 2', '2 * 2', 'dim * 2', '0u']) _arguments_nocomma = ( pp.Optional(_arg) + pp.ZeroOrMore(pp.Literal(',').suppress() + pp.Optional(pp.White() | pp.LineEnd()).suppress() - _arg)) _call = pp.Literal('(') - _arguments - pp.Literal(')') test_parse(_call, ['(2)', '(toto, 2)', '(2*2)', '(dim)', '(dim * 2)']) ################################################################ # Grammar rules libmultiscale ################################################################ etag = pp.Literal("*/") tag_desc = pp.Literal("/* LMDESC") tag_keyword = pp.Literal("/* LMKEYWORD") tag_heritance = pp.Literal("/* LMHERITANCE") tag_example = pp.Literal("/* LMEXAMPLE") def block(tag): _header = pp.SkipTo(tag) + tag _content = pp.SkipTo(etag) _block = _header.suppress() - _content _block -= etag.suppress() return _block def named_block(tag): _header = pp.SkipTo(tag) + tag _header += pp.ZeroOrMore(pp.White()) _block = _header.suppress() - pp.Word(pp.alphanums+"_") _block -= pp.OneOrMore(pp.White() | pp.LineEnd()).suppress() _block -= pp.SkipTo(etag) _block -= etag.suppress() res = _block return res description = named_block(tag_desc) example = block(tag_example) heritance = block(tag_heritance) ################################################################ def setTag(tok, tag): print(tok) tok.tag = tag return tok parse_tag = (pp.Literal("this->parseTag").suppress() - pp.Literal('(').suppress() - pp.QuotedString('"') + _arguments_nocomma - pp.Literal(')').suppress()) parse_keyword = (pp.Literal("this->parseKeyword").suppress() - pp.Literal('(').suppress() - pp.QuotedString('"') + _arguments_nocomma - pp.Literal(')').suppress()) parse_veckeyword = (pp.Literal("this->parseVectorKeyword").suppress() - pp.Literal('(').suppress() - pp.QuotedString('"') + _arguments_nocomma - pp.Literal(')').suppress()) parse_declaration = (parse_tag | parse_keyword | parse_veckeyword) + pp.Literal(';').suppress() def check_declaration(toks): return toks[0] == toks[2] keyword = (named_block(tag_keyword) - parse_declaration).addCondition(check_declaration, message="Documentation != Code") lm_content = pp.Group(description).setResultsName("description") lm_content += pp.Group(pp.Optional(example)).setResultsName("example") lm_content += pp.Group(pp.Optional(heritance)).setResultsName("heritance") -lm_content += pp.Group(pp.ZeroOrMore(keyword)).setResultsName("keywords") +lm_content += pp.Group(pp.ZeroOrMore(pp.Group(keyword)) + ).setResultsName("keywords") ################################################################ # Grammar tests ################################################################ test_parse(_type, ['std::map>']) test_parse(_arg, ['toto', 'std::toto', '"toto"', '2', '-toto', '2.', '2.2', 'toto()', 'dim * 2', 'this->toto', 'toto()', 'toto<3>()', 'toto()' ]) test_parse(_arguments, ['1., 2, "toto"', '1., -2, -toto', '1., 2, "toto", std::map>(), toto()']) test_parse(_call, ['(1., 2, "toto")', '(1., 2, "toto", std::map>(), toto())', '(-2)', '(-toto)', '(1., -2, -toto)', '(dim * 2)', '(1., dim * 2)' ]) res = description.parseString(""" /* LMDESC TIMEAVG This computes a time averaged version of a set of reals */ """) assert(res[0] == 'TIMEAVG') assert(res[1] == 'This computes a time averaged version of a set of reals\n') res = example.parseString(""" /* LMEXAMPLE COMPUTE disp EXTRACT INPUT md FIELD displacement\\ COMPUTE time_average TIMEAVG INPUT disp\\ */ """) assert(res[0] == '''COMPUTE disp EXTRACT INPUT md FIELD displacement\\ COMPUTE time_average TIMEAVG INPUT disp\\ ''') res = heritance.parseString(""" /* LMHERITANCE action_interface*/ """) assert(res[0] == 'action_interface') res = keyword.parseString(""" /* LMKEYWORD PROC Flag to request processor number to each DOF */ this->parseTag("PROC", proc_field, false); """) assert(res[0] == 'PROC') assert(res[1].strip() == 'Flag to request processor number to each DOF') assert(res[2] == 'PROC') assert(res[3] == 'proc_field') assert(res[4] == 'false') res = keyword.parseString(""" /* LMKEYWORD BOUNDARY flag to request output of nodal blockage */ this->parseKeyword("BOUNDARY", boundary_field, false); """) assert(res[0] == 'BOUNDARY') assert(res[1].strip() == 'flag to request output of nodal blockage') assert(res[2] == 'BOUNDARY') assert(res[3] == 'boundary_field') assert(res[4] == 'false') res = keyword.parseString(""" /* LMKEYWORD DIR Whether to block in x direction*/ this->parseVectorKeyword("DIR", Dim, this->block, VEC_DEFAULTS(false, false, false)); """) assert(res[0] == 'DIR') assert(res[1].strip() == 'Whether to block in x direction') assert(res[2] == 'DIR') assert(res[3] == 'Dim') assert(res[4] == 'this->block') assert(res[5] == 'VEC_DEFAULTS(false,false,false)') res = keyword.parseString(""" /* LMKEYWORD MAX specify a maximum threshold */ this->parseKeyword("MAX", max, -lm_real_max); """) assert(res[0] == 'MAX') assert(res[1].strip() == 'specify a maximum threshold') assert(res[2] == 'MAX') assert(res[3] == 'max') assert(res[4] == '-lm_real_max') res = keyword.parseString(""" /* LMKEYWORD PBC Specify the pbc flags (one per direction) for neighbor detection */ this->parseVectorKeyword("PBC", spatial_dimension, pbc_flag, VEC_DEFAULTS(false, false, false)); """) assert(res[0] == 'PBC') assert(res[1].strip() == 'Specify the pbc flags (one per direction) for neighbor detection') assert(res[2] == 'PBC') assert(res[3] == 'spatial_dimension') assert(res[4] == 'pbc_flag') assert(res[5] == 'VEC_DEFAULTS(false,false,false)') res = lm_content.parseString(""" /* LMDESC PYTHON This computes an array of reals based on a python script */ /* LMEXAMPLE COMPUTE disp EXTRACT INPUT md FIELD displacement \\\\ COMPUTE disp2 PYTHON INPUT disp FILENAME script \\\\ with a python script stored in a file script.py with the content such as:\\\\ import numpy as np\\ \\ def compute(**kwargs):\\ ~~vec = np.copy(kwargs["disp"])\\ ~~vec *= 2. \\ ~~return vec */ void ComputePython::declareParams() { """) try: res = keyword.parseString(""" /* LMKEYWORD DIR Whether to block in x direction*/ this->parseVectorKeyword("DIR2", Dim, this->block); """) raise RuntimeError("should not parse") except pp.ParseException: pass ################################################################ # Libmultiscale parser ################################################################ class LibMultiScaleParser: def parse(self, filename, internal_key_list): fin = open(filename, 'r') inp = fin.read() fin.close() res = lm_content.parseString(inp) - return AttrDict(res.asDict()) + return res.asDict() diff --git a/doc/manual/main.py b/doc/manual/main.py index 5e1f85b..bdef6fb 100644 --- a/doc/manual/main.py +++ b/doc/manual/main.py @@ -1,211 +1,200 @@ #!/usr/bin/env python3 import sys import os import re import pylibmultiscale as lm import pyparsing as pp from libmultiscale_doc_parser import LibMultiScaleParser from generate_latex import generateLatex ################################################################ def LMDocData(): return { 'name': None, 'type': None, 'description': None, 'children': [], 'var_name': None, 'c_type': None, 'filename': None, 'heritance': None, 'example': None, 'defaults': None } def LMDataNode(): return { 'name': None, 'children': {}, 'data': [] } ################################################################ def readListOfSourceFiles(fname): _f = open(fname) list_files = [] for line in _f.readlines(): fname = line.strip() if (line == ""): continue _str = open(fname).read() m = re.search(r'.*(declareParams\(\))\s+(\{).*', _str) if not m: continue source_file = fname list_files.append(source_file) return list_files ################################################################ def addDoc(root, doc, _file): dirs = _file.split('/') i = 0 for i in range(0, len(dirs)): if dirs[i] == 'src': break ++i if i == len(dirs): raise RuntimeError("problem in the file structure") dirs = dirs[i+1:] _file = os.path.join(*dirs) print(_file) node = root sublevel = dirs[0] for sublevel in dirs: if sublevel not in node['children']: node['children'][sublevel] = LMDataNode() node = node['children'][sublevel] node['name'] = sublevel node['data'].append(doc) ################################################################ def addDocByName(sorted_by_name, doc, _file): # std: : string short_name = file.stem().native() # // std: : cerr << "record heritance " << short_name << std: : endl # sorted_by_name[protectString(short_name)] = doc pass ################################################################ -def protectUnderscoreInDoc(doc): - - # doc.name = protectString(doc.name) - # doc.type = protectString(doc.type) - # doc.var_name = protectString(doc.var_name) - # doc.defaults = protectString(doc.defaults) - # doc.c_type = protectString(doc.c_type) - # doc.example = protectString(doc.example) - # for (UInt i=0 - # i < doc.heritance.size() - # + +i) { - # doc.heritance[i] = protectString(doc.heritance[i]) - # } - # for (UInt i=0 - # i < doc.children.size() - # + +i) - # protectUnderscoreInDoc(doc.children[i]) - pass - -################################################################ - - def generatorInternalKeyWordList(): return [ 'DomainDD', 'DomainAtomic', 'DomainContinuum', 'ActionInterface', 'DomainInterface', 'Dumper', 'ComposedGeom', 'CouplerManager', 'DofAssociation', 'Bridging', 'Geometry', 'ArlequinTemplate', 'PointAssociation', 'LAMMPS_BASE', 'AKANTU_BASE', 'AKANTU_DYNAMIC', 'AKANTU_STATIC', 'FILTER'] ################################################################ def checkKeywordExistance(key, key_list, internal_key_list): if (key not in key_list) and (key not in internal_key_list): print("Warning:Undeclared " + key + ": keywords are " + ', '.join(key_list)) return elif key in key_list: key_list[key].pop() if not key_list[key]: del key_list[key] print("removing key") print('') ################################################################ def main(): p = sys.argv[1] files = readListOfSourceFiles(p) key_list = lm.getKeyWordList() internal_key_list = generatorInternalKeyWordList() parser = LibMultiScaleParser() root = LMDataNode() sorted_by_name = {} for fname in files: res_doc = LMDocData() res_doc['filename'] = fname print("parsing " + res_doc['filename']) try: res = parser.parse(fname, internal_key_list) for k, v in res.items(): print(f'{k}:{v}') res_doc['name'] = res['description'][0] res_doc['description'] = res['description'][1] if 'example' in res: res_doc['example'] = res['example'] + if 'heritance' in res: + res_doc['heritance'] = res['heritance'] + if 'keywords' in res: + res_doc['children'] = [{'name': k[0], 'value': k} + for k in res['keywords']] checkKeywordExistance(res_doc['name'], key_list, internal_key_list) - protectUnderscoreInDoc(res) + for child in res_doc['children']: - child['filename'] = res['filename'] + child['filename'] = res_doc['filename'] + child['description'] = child['value'][1] - protectUnderscoreInDoc(res_doc) - addDoc(root, res, fname) + addDoc(root, res_doc, fname) addDocByName(sorted_by_name, res, fname) except pp.ParseException as e: print(f'{res_doc["filename"]}:{e.lineno}:{e.col}:{e}') except pp.ParseSyntaxException as e: print(f'{res_doc["filename"]}:{e.lineno}:{e.col}:{e}') for k, v in key_list.items(): print("Warning: keyword " + k + " was not documented ") print(root) - fout = open("manual-generated.tex", 'w') + fout = open("../source/keywords.rst", 'w') + fout.write(""" +Keywords +======== + +""") generateLatex(fout, root, sorted_by_name) + fout.close() ################################################################ if __name__ == "__main__": main() diff --git a/doc/source/index.rst b/doc/source/index.rst index c9d04fe..9182408 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -1,42 +1,43 @@ .. LibMultiScale documentation master file, created by sphinx-quickstart on Tue Apr 28 18:41:08 2020. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. LibMultiScale manual ========================================= .. toctree:: :maxdepth: 2 :caption: Contents: Installation Conffile - + keywords + The LibMultiScale Library has been designed to be a high performance tool to study the mutiscale methods currently employed in material simulations. The component design of the project distinct the base code components (Continuum mechanics code implemented through finite element, meshless, XFEM or molecular dynamics codes) from the coupling components. Other services like dumpers (logging the state of the simulated system to files or memory), stimulators (initial conditions, thermostats) or computes (general computation) are provided. LibMultiScale was initiated in a collaboration between INRIA Futurs Bordeaux within ScAlApplix team and CEA/DPTA Ile de France. The project is now continued at the Ecole Polytechnique Fédérale of Lausanne within the ENAC/IIC/LSMS laboratory. In consequence, the files of the source code are under two distinct Copyrights and distributed under two distinct licenses: CECILL-C and LGPL. These licenses are compatible with each other. The complete text of the licenses are joined in the files cecill-c.txt and LGPL.txt Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search`