def parseSourceString(sourceString): global lastLoc, currentPackage successful = True cntlr.showStatus("Compiling sphinx file {0}".format( os.path.basename(sphinxFile))) try: lastLoc = 0 currentPackage = None prog = sphinxGrammar.parseString(sourceString, parseAll=True) xmlns.clear() # dereference xmlns definitions prog.insert(0, astSourceFile(sphinxFile)) # keep the source file name sphinxProgs.append(prog) except (ParseException, ParseSyntaxException) as err: from arelle.XPathParser import exceptionErrorIndication file = os.path.basename(sphinxFile) logMessage("ERROR", "sphinxCompiler:syntaxError", _("Parse error: \n%(error)s"), sphinxFile=sphinxFile, sourceFileLines=((file, lineno(err.loc, err.pstr)), ), error=exceptionErrorIndication(err)) successful = False except (ValueError) as err: file = os.path.basename(sphinxFile) logMessage("ERROR", "sphinxCompiler:valueError", _("Parsing terminated due to error: \n%(error)s"), sphinxFile=sphinxFile, sourceFileLines=((file, lineno(lastLoc, sourceString)), ), error=err) successful = False except Exception as err: file = os.path.basename(sphinxFile) logMessage("ERROR", "sphinxCompiler:parserException", _("Parsing of terminated due to error: \n%(error)s"), sphinxFile=sphinxFile, sourceFileLines=((file, lineno(lastLoc, sourceString)), ), error=err, exc_info=True) successful = False cntlr.showStatus("Compiled sphinx files {0}".format({ True: "successful", False: "with errors" }[successful]), clearAfter=5000) xmlns.clear() return successful
def compileHyperspaceAxis( sourceStr, loc, toks ): try: return astHyperspaceAxis( sourceStr, loc, toks ) except PrefixError as err: logMessage("ERROR", "sphinxCompiler:missingXmlnsDeclarations", _("Missing xmlns for prefix in %(qname)s"), sourceFileLines=((sphinxFile, lineno(loc, sourceStr)),), qname=err.qname) return None
def compileNamespaceDeclaration( sourceStr, loc, toks ): global lastLoc; lastLoc = loc prefix = None if len(toks) == 2 else toks[1] namespaceNode = toks[-1] if prefix in xmlns: logMessage("ERROR", "sphinxCompiler:multipleXmlnsDeclarations", _("Duplicate xmlns for prefix %(prefix)s"), sourceFileLines=((sphinxFile, lineno(loc, sourceStr)),), prefix=prefix) elif not isinstance(namespaceNode, astStringLiteral): logMessage("ERROR", "sphinxCompiler:xmlnsNotStringConstant", _("Xmlns for prefix %(prefix)s does not assign a string constant."), sourceFileLines=((sphinxFile, lineno(loc, sourceStr)),), prefix=prefix) else: namespace = namespaceNode.text xmlns[prefix] = namespace return astNamespaceDeclaration(sourceStr, loc, prefix, namespace) return astNoOp(sourceStr, loc)
def compileHyperspaceExpression(sourceStr, loc, toks): try: return astHyperspaceExpression(sourceStr, loc, toks) except PrefixError as err: logMessage("ERROR", "sphinxCompiler:missingXmlnsDeclarations", _("Missing xmlns for prefix in %(qname)s"), sourceFileLines=((sphinxFile, lineno(loc, sourceStr)), ), qname=err.qname) return None
def parseSourceString(sourceString): global lastLoc, currentPackage successful = True cntlr.showStatus("Compiling sphinx file {0}".format(os.path.basename(sphinxFile))) try: lastLoc = 0 currentPackage = None prog = sphinxGrammar.parseString( sourceString, parseAll=True ) xmlns.clear() # dereference xmlns definitions prog.insert(0, astSourceFile(sphinxFile)) # keep the source file name sphinxProgs.append( prog ) except (ParseException, ParseSyntaxException) as err: from arelle.XPathParser import exceptionErrorIndication file = os.path.basename(sphinxFile) logMessage("ERROR", "sphinxCompiler:syntaxError", _("Parse error: \n%(error)s"), sphinxFile=sphinxFile, sourceFileLines=((file, lineno(err.loc,err.pstr)),), error=exceptionErrorIndication(err)) successful = False except (ValueError) as err: file = os.path.basename(sphinxFile) logMessage("ERROR", "sphinxCompiler:valueError", _("Parsing terminated due to error: \n%(error)s"), sphinxFile=sphinxFile, sourceFileLines=((file,lineno(lastLoc,sourceString)),), error=err) successful = False except Exception as err: file = os.path.basename(sphinxFile) logMessage("ERROR", "sphinxCompiler:parserException", _("Parsing of terminated due to error: \n%(error)s"), sphinxFile=sphinxFile, sourceFileLines=((file,lineno(lastLoc,sourceString)),), error=err, exc_info=True) successful = False cntlr.showStatus("Compiled sphinx files {0}".format({True:"successful", False:"with errors"}[successful]), clearAfter=5000) xmlns.clear() return successful
def compileMethodReference(sourceStr, loc, toks): if len(toks) == 1: return toks global lastLoc lastLoc = loc if len(toks) > 1 and toks[ 0] == "::": # method with no object, e.g., ::taxonomy result = None methNameTokNdx = 1 elif len(toks) > 2 and toks[1] == "::": result = toks[0] methNameTokNdx = 2 else: return toks while methNameTokNdx < len(toks): taggedExpr = toks[methNameTokNdx] if isinstance(taggedExpr, astTagAssignment): methArg = taggedExpr.expr else: methArg = taggedExpr if isinstance(methArg, str): methName = methArg methArgs = [] elif isinstance( methArg, astQnameLiteral) and methArg.value.namespaceURI is None: methName = methArg.value.localName methArgs = [] elif isinstance(methArg, astFunctionReference): methName = methArg.name methArgs = methArg.args else: logMessage("ERROR", "sphinxCompiler:methodNameNotRecognized", _("Method name not recognized: %(name)s"), sourceFileLines=((sphinxFile, lineno(loc, sourceStr)), ), name=methArg) return "none" # probably syntax error?? need message??? result = astMethodReference(sourceStr, loc, methName, [result] + methArgs) if isinstance(taggedExpr, astTagAssignment): taggedExpr.expr = result result = taggedExpr if methNameTokNdx + 2 < len(toks) and toks[methNameTokNdx + 1] == "::": methNameTokNdx += 2 else: # probably suntax if extra toks break return result
def compileNamespaceDeclaration(sourceStr, loc, toks): global lastLoc lastLoc = loc prefix = None if len(toks) == 2 else toks[1] namespaceNode = toks[-1] if prefix in xmlns: logMessage("ERROR", "sphinxCompiler:multipleXmlnsDeclarations", _("Duplicate xmlns for prefix %(prefix)s"), sourceFileLines=((sphinxFile, lineno(loc, sourceStr)), ), prefix=prefix) elif not isinstance(namespaceNode, astStringLiteral): logMessage( "ERROR", "sphinxCompiler:xmlnsNotStringConstant", _("Xmlns for prefix %(prefix)s does not assign a string constant." ), sourceFileLines=((sphinxFile, lineno(loc, sourceStr)), ), prefix=prefix) else: namespace = namespaceNode.text xmlns[prefix] = namespace return astNamespaceDeclaration(sourceStr, loc, prefix, namespace) return astNoOp(sourceStr, loc)
def compileFunctionReference( sourceStr, loc, toks ): global lastLoc; lastLoc = loc name = toks[0] if isinstance(name, astFunctionReference) and not name.args: name = name.name if name == "unit": try: return astFunctionReference(sourceStr, loc, name, toks[astQnameLiteral(sourceStr, loc, toks[1])]) except PrefixError as err: logMessage("ERROR", "sphinxCompiler:missingXmlnsDeclarations", _("Missing xmlns for prefix in unit %(qname)s"), sourceFileLines=((sphinxFile, lineno(loc, sourceStr)),), qname=err.qname) return None # compile any args return astFunctionReference(sourceStr, loc, name, toks[1:])
def __init__(self, sourceStr, loc, functionType, name, params, expr): try: super(astFunctionDeclaration, self).__init__(sourceStr, loc) self.functionType = functionType # "function", "macro" self.name = name self.params = params if (expr) == "unit": # expr is a QName self.expr = astQnameLiteral(sourceStr, loc, expr) else: self.expr = expr except PrefixError as err: logMessage("ERROR", "sphinxCompiler:missingXmlnsDeclarations", _("Missing xmlns for prefix in %(qname)s"), sourceFileLines=((sphinxFile, lineno(loc, sourceStr)),), qname=err.qname) return None
def __init__(self, sourceStr, loc, toks): super(astHyperspaceExpression, self).__init__(sourceStr, loc) self.isClosed = False self.axes = [] for i, tok in enumerate(toks): if tok in ('[', '[['): if i == 1: self.axes.append(astHyperspaceAxis(sourceStr, loc, ["primary", "=", toks[i-1]])) self.isClosed = tok == '[[' elif tok in (']', ']]'): if self.isClosed != tok == ']]': logMessage("ERROR", "sphinxCompiler:mismatchedClosed", _("Axis restrictions syntax mismatches closed brackets."), sourceFileLines=((sphinxFile, lineno(loc, sourceStr)),)) elif isinstance(tok, astHyperspaceAxis): self.axes.append(tok)
def __init__(self, sourceStr, loc, functionType, name, params, expr): try: super(astFunctionDeclaration, self).__init__(sourceStr, loc) self.functionType = functionType # "function", "macro" self.name = name self.params = params if (expr) == "unit": # expr is a QName self.expr = astQnameLiteral(sourceStr, loc, expr) else: self.expr = expr except PrefixError as err: logMessage("ERROR", "sphinxCompiler:missingXmlnsDeclarations", _("Missing xmlns for prefix in %(qname)s"), sourceFileLines=((sphinxFile, lineno(loc, sourceStr)), ), qname=err.qname) return None
def compileMethodReference( sourceStr, loc, toks ): if len(toks) == 1: return toks global lastLoc; lastLoc = loc if len(toks) > 1 and toks[0] == "::": # method with no object, e.g., ::taxonomy result = None methNameTokNdx = 1 elif len(toks) > 2 and toks[1] == "::": result = toks[0] methNameTokNdx = 2 else: return toks while methNameTokNdx < len(toks): taggedExpr = toks[methNameTokNdx] if isinstance(taggedExpr, astTagAssignment): methArg = taggedExpr.expr else: methArg = taggedExpr if isinstance(methArg, str): methName = methArg methArgs = [] elif isinstance(methArg, astQnameLiteral) and methArg.value.namespaceURI is None: methName = methArg.value.localName methArgs = [] elif isinstance(methArg, astFunctionReference): methName = methArg.name methArgs = methArg.args else: logMessage("ERROR", "sphinxCompiler:methodNameNotRecognized", _("Method name not recognized: %(name)s"), sourceFileLines=((sphinxFile, lineno(loc, sourceStr)),), name=methArg) return "none" # probably syntax error?? need message??? result = astMethodReference(sourceStr, loc, methName, [result] + methArgs) if isinstance(taggedExpr, astTagAssignment): taggedExpr.expr = result result = taggedExpr if methNameTokNdx + 2 < len(toks) and toks[methNameTokNdx + 1] == "::": methNameTokNdx += 2 else: # probably suntax if extra toks break return result
def compileFunctionReference(sourceStr, loc, toks): global lastLoc lastLoc = loc name = toks[0] if isinstance(name, astFunctionReference) and not name.args: name = name.name if name == "unit": try: return astFunctionReference( sourceStr, loc, name, toks[astQnameLiteral(sourceStr, loc, toks[1])]) except PrefixError as err: logMessage("ERROR", "sphinxCompiler:missingXmlnsDeclarations", _("Missing xmlns for prefix in unit %(qname)s"), sourceFileLines=((sphinxFile, lineno(loc, sourceStr)), ), qname=err.qname) return None # compile any args return astFunctionReference(sourceStr, loc, name, toks[1:])
def __init__(self, sourceStr, loc, toks): super(astHyperspaceExpression, self).__init__(sourceStr, loc) self.isClosed = False self.axes = [] for i, tok in enumerate(toks): if tok in ('[', '[['): if i == 1: self.axes.append( astHyperspaceAxis(sourceStr, loc, ["primary", "=", toks[i - 1]])) self.isClosed = tok == '[[' elif tok in (']', ']]'): if self.isClosed != tok == ']]': logMessage( "ERROR", "sphinxCompiler:mismatchedClosed", _("Axis restrictions syntax mismatches closed brackets." ), sourceFileLines=((sphinxFile, lineno(loc, sourceStr)), )) elif isinstance(tok, astHyperspaceAxis): self.axes.append(tok)
def sourceLine(self): if self.sourceStr and self.loc: return lineno(self.loc, self.sourceStr) return None # no line number available
def __init__(self, sourceStr, loc, toks): STATE_AXIS_NAME_EXPECTED = 0 STATE_AXIS_NAMED = 1 STATE_EQ_VALUE = 10 STATE_IN_LIST = 11 STATE_AS_NAME = 20 STATE_AS_NAMED = 21 STATE_AS_EQ_VALUE = 22 STATE_AS_EQ_WHERE = 23 STATE_AS_RESTRICTION = 30 STATE_WHERE = 40 STATE_INDETERMINATE = 99 super(astHyperspaceAxis, self).__init__(sourceStr, loc) self.aspect = None # case of only a where clause has no specified aspect self.name = None self.asVariableName = None self.restriction = None # qname, expr, * or ** self.whereExpr = None state = STATE_AXIS_NAME_EXPECTED for tok in toks: if tok == "where" and state in (STATE_AXIS_NAME_EXPECTED, STATE_AS_EQ_WHERE): state = STATE_WHERE elif tok == "=" and state == STATE_EQ_VALUE: state = STATE_EQ_VALUE elif tok == "in" and state == STATE_AXIS_NAMED: state = STATE_IN_LIST elif tok == "as" and state == STATE_AXIS_NAMED: state = STATE_AS_NAME elif tok == "=" and state == STATE_AXIS_NAMED: state = STATE_EQ_VALUE elif tok == "=" and state == STATE_AS_NAMED: state = STATE_AS_EQ_VALUE elif state == STATE_AXIS_NAME_EXPECTED: if isinstance(tok, astQnameLiteral): axisQname = tok.value if axisQname.namespaceURI is None and axisQname.localName in namedAxes: self.name = axisQname.localName self.aspect = namedAxes[self.name] else: self.name = self.aspect = axisQname elif isinstance(tok, astVariableReference): self.name = '$' + tok.variableName self.aspect = tok elif tok in namedAxes: # e.g., "primary" self.name = tok self.aspect = namedAxes[tok] state = STATE_AXIS_NAMED elif state in (STATE_EQ_VALUE, STATE_AS_EQ_VALUE): if isinstance(tok, astNode): self.restriction = [tok] elif tok == '*': self.restriction = (NONDEFAULT, ) elif tok == '**': self.restriction = (DEFAULTorNONDEFAULT, ) elif tok == 'none': self.restriction = (DEFAULT, ) elif isinstance(tok, str): self.restriction = [astQnameLiteral(sourceStr, loc, tok)] elif isinstance(tok, astQnameLiteral): self.restriction = [tok] state = { STATE_EQ_VALUE: STATE_INDETERMINATE, STATE_AS_EQ_VALUE: STATE_AS_EQ_WHERE }[state] elif state == STATE_IN_LIST: self.restriction = tok state = STATE_INDETERMINATE elif state == STATE_AS_NAME: self.asVariableName = tok state = STATE_AS_NAMED elif state == STATE_WHERE: self.whereExpr = tok state = STATE_INDETERMINATE else: logMessage("ERROR", "sphinxCompiler:axisIndeterminate", _("Axis indeterminte expression at %(element)s."), sourceFileLines=((sphinxFile, lineno(loc, sourceStr)), ), element=tok)
def __init__(self, sourceStr, loc, toks): STATE_AXIS_NAME_EXPECTED = 0 STATE_AXIS_NAMED = 1 STATE_EQ_VALUE = 10 STATE_IN_LIST = 11 STATE_AS_NAME = 20 STATE_AS_NAMED = 21 STATE_AS_EQ_VALUE = 22 STATE_AS_EQ_WHERE = 23 STATE_AS_RESTRICTION = 30 STATE_WHERE = 40 STATE_INDETERMINATE = 99 super(astHyperspaceAxis, self).__init__(sourceStr, loc) self.aspect = None # case of only a where clause has no specified aspect self.name = None self.asVariableName = None self.restriction = None # qname, expr, * or ** self.whereExpr = None state = STATE_AXIS_NAME_EXPECTED for tok in toks: if tok == "where" and state in (STATE_AXIS_NAME_EXPECTED, STATE_AS_EQ_WHERE): state = STATE_WHERE elif tok == "=" and state == STATE_EQ_VALUE: state = STATE_EQ_VALUE elif tok == "in" and state == STATE_AXIS_NAMED: state = STATE_IN_LIST elif tok == "as" and state == STATE_AXIS_NAMED: state = STATE_AS_NAME elif tok == "=" and state == STATE_AXIS_NAMED: state = STATE_EQ_VALUE elif tok == "=" and state == STATE_AS_NAMED: state = STATE_AS_EQ_VALUE elif state == STATE_AXIS_NAME_EXPECTED: if isinstance(tok, astQnameLiteral): axisQname = tok.value if axisQname.namespaceURI is None and axisQname.localName in namedAxes: self.name = axisQname.localName self.aspect = namedAxes[self.name] else: self.name = self.aspect = axisQname elif isinstance(tok, astVariableReference): self.name = '$' + tok.variableName self.aspect = tok elif tok in namedAxes: # e.g., "primary" self.name = tok self.aspect = namedAxes[tok] state = STATE_AXIS_NAMED elif state in (STATE_EQ_VALUE, STATE_AS_EQ_VALUE): if isinstance(tok, astNode): self.restriction = [tok] elif tok == '*': self.restriction = (NONDEFAULT,) elif tok == '**': self.restriction = (DEFAULTorNONDEFAULT,) elif tok == 'none': self.restriction = (DEFAULT,) elif isinstance(tok, str): self.restriction = [astQnameLiteral(sourceStr, loc, tok)] elif isinstance(tok, astQnameLiteral): self.restriction = [tok] state = {STATE_EQ_VALUE: STATE_INDETERMINATE, STATE_AS_EQ_VALUE: STATE_AS_EQ_WHERE}[state] elif state == STATE_IN_LIST: self.restriction = tok state = STATE_INDETERMINATE elif state == STATE_AS_NAME: self.asVariableName = tok state = STATE_AS_NAMED elif state == STATE_WHERE: self.whereExpr = tok state = STATE_INDETERMINATE else: logMessage("ERROR", "sphinxCompiler:axisIndeterminate", _("Axis indeterminte expression at %(element)s."), sourceFileLines=((sphinxFile, lineno(loc, sourceStr)),), element=tok)