def check_good_use_of_special_paragraphs(md, filename): lines = md.split('\n') for i in range(1, len(lines)): line = lines[i] prev = lines[i - 1] prefix = has_special_line_prefix(line) if prefix: if prev.strip(): msg = ('Wrong use of special paragraph indicator. You have ' 'to leave an empty line before the special paragraph.') c = location(i, 1, md) c_end = c + len(prefix) where = Where(md, c, c_end).with_filename(filename) raise DPSyntaxError(msg, where=where) if False: def looks_like_list_item(s): if s.startswith('--'): return False if s.startswith('**'): return False return s.startswith('-') or s.startswith('*') if looks_like_list_item(line): if prev.strip() and not looks_like_list_item(prev): msg = ('Wrong use of list indicator. You have ' 'to leave an empty line before the list.') c = location(i, 1, md) c_end = c + 1 where = Where(md, c, c_end).with_filename(filename) raise DPSyntaxError(msg, where=where)
def make_rcompunit(units): try: s = units.strip() mcdp_dev_warning('obsolete?') if s.startswith('set of'): t = s.split('set of') u = make_rcompunit(t[1]) from mcdp_posets import FiniteCollectionsInclusion return FiniteCollectionsInclusion(u) mcdp_dev_warning('obsolete?') if s == 'any': return BottomCompletion(TopCompletion(Any())) if s == 'R': raise DPSyntaxError( 'Form R is not recognized anymore. Use "dimensionless".') s = 'm/m' unit = parse_pint(s) except DPSyntaxError: raise # msg = 'Cannot parse the unit %r.' % units # raise_wrapped(DPSemanticError, e, msg, compact=True, exc=sys.exc_info()) return RcompUnits(unit, s)
def bb(tokens, loc, s): where = Where(s, loc) try: try: res = b(tokens) except TypeError as e: ttokens = list(tokens) s = "\n".join("- %s " % str(x) for x in ttokens) msg = 'Cannot invoke %r\nwith %d tokens:\n%s.' % ( b, len(ttokens), s) raise_wrapped(TypeError, e, msg) except DPSyntaxError as e: if e.where is None: e.where = where raise DPSyntaxError(str(e), where=where) else: raise except DPSemanticError as e: if e.where is None: raise DPSemanticError(str(e), where=where) else: raise except BaseException as e: raise_wrapped(DPInternalError, e, "Error while parsing.", where=where.__str__(), tokens=tokens) if isnamedtupleinstance(res) and res.where is None: res = get_copy_with_where(res, where=where) return res
def assert_not_contains(s, what): if not what in s: return i = s.index(what) if i is not None: msg = 'Found forbidden sequence "%s".' % what where = Where(s, i, i + len(what)) raise DPSyntaxError(msg, where=where)
def replace_macros(s): ''' Replaces strings of the type @@{key} It looks in MCDPManualConstants.macros Also available @@{MCDPConstants.name} ''' macros = MCDPManualConstants.macros class MyTemplate(Template): delimiter = '@@' idpattern = r'[_a-z][\._a-z0-9]*' def _invalid(self, mo): i = mo.start('invalid') lines = self.template[:i].splitlines(True) if not lines: colno = 1 lineno = 1 else: colno = i - len(''.join(lines[:-1])) lineno = len(lines) char = location(lineno - 1, colno - 1, s) w = Where(s, char) raise DPSyntaxError('Invalid placeholder', where=w) class Sub(object): def __init__(self, data): self.data = data def __getitem__(self, key): if key in self.data: return self.data[key] if '.' in key: i = key.index('.') first, last = key[:i], key[i + 1:] #print('%s -> %s, %s' % (key, first, last)) return self[first][last] raise KeyError(key) t = MyTemplate(s) MyTemplate.idpattern = r'[_a-z][\._a-z0-9]*' try: s2 = t.substitute(Sub(macros)) except KeyError as e: key = str(e).replace("'", "") search_for = MyTemplate.delimiter + key logger.error('Could not find key %r' % key) char = s.index(search_for) w = Where(s, char) msg = 'Key %r not found - maybe use braces?' % key raise DPSyntaxError(msg, where=w) return s2
def check_misspellings(s): # check misspellings misspellings = ['mcpd', 'MCPD'] for m in misspellings: if m in s: c = s.index(m) msg = 'Typo, you wrote MCPD rather than MCDP.' where = Where(s, c, c + len(m)) raise DPSyntaxError(msg, where=where) return s
def check_no_forbidden(s): # pragma: no cover if '\t' in s: i = s.index('\t') msg = "Tabs bring despair (e.g. Markdown does not recognize them.)" where = Where(s, i) raise DPSyntaxError(msg, where=where) forbidden = { '>=': ['≥'], '<=': ['≤'], '>>': ['?'] # added by mistake by Atom autocompletion } for f in forbidden: if f in s: msg = 'Found forbidden sequence %r. This will not end well.' % f subs = forbidden[f] msg += ' Try one of these substitutions: %s' % format_list(subs) c = s.index(f) where = Where(s, c, c + len(f)) raise DPSyntaxError(msg, where=where)
def _invalid(self, mo): i = mo.start('invalid') lines = self.template[:i].splitlines(True) if not lines: colno = 1 lineno = 1 else: colno = i - len(''.join(lines[:-1])) lineno = len(lines) char = location(lineno - 1, colno - 1, s) w = Where(s, char) raise DPSyntaxError('Invalid placeholder', where=w)
def eat_tag(line_in, line_out): _first_line = l = line_in[0] approximate_line = len(line_out) assert l.startswith('<') tagname = '' l = l[1:] v = lambda _: _.isdigit() or _.isalpha() or _ in ['_', '-'] while l and v(l[0]): tagname += l[0] l = l[1:] if not tagname: # pragma: no cover msg = 'Cannot get tagname from line %r' % line_in[0] msg += '\n in:%s out= %s' % (line_in, line_out) raise ValueError(msg) # <tagname> okokokok </tagname> # <tagname /> okokokok can_close_by_short = True # search for end of tag i = 0 while line_in: l = line_in.pop(0) # print('xml tag line %r' % l) l2 = inside_tag(l) line_out.append(l2) if can_close_by_short and '/>' in l: # print('xml break by short') return effective = l if i > 0 else l[l.index(tagname):] if ('>' in effective or '<' in effective) and can_close_by_short: # print('xml cannot close by short anymore') can_close_by_short = False # if first line then </tag> can be anywhere # if not first line, it should be at the beginning end_tag = '</%s>' % tagname cond1 = (i == 0) and (end_tag in l) cond2 = (i > 0) and l.startswith(end_tag) if cond1 or cond2: # print('Found end tag %r' % end_tag) return else: pass # print ('No %r in %r; continue' % (end_tag, l)) i += 1 msg = 'Cannot find matching tag to %r. Around line %d.' % (tagname, approximate_line) msg += '\n Remember I want it either on the first line (anywhere) or at the start of a line.' character = location(approximate_line, 0, s) where = Where(s, character) raise DPSyntaxError(msg, where=where)
def check_parsable(s): from xml.etree import ElementTree as ET # parser = ET.XMLParser() # parser.entity["nbsp"] = unichr(160) s = '<add-wrap-for-xml-parser>' + s + '</add-wrap-for-xml-parser>' # print indent(s, ' for xml') # with open('rtmp.xml', 'w') as f: # f.write(s) try: _ = ET.fromstring(s) except Exception as e: line1, col1 = e.position line = line1 - 1 col = col1 - 1 character = find_location(line, col, s) msg = 'Invalid XML: %s' % e where = Where(s, character) logger.error('line %s col %s' % (where.line, where.col)) logger.error(where) raise DPSyntaxError(msg, where=where)
def substitute_command_ext(s, name, f, nargs, nopt): """ Subsitute \name[x]{y}{z} with f : args=(x, y), opts=None -> s if nargs=1 and nopt = 0: f : x -> s """ # noccur = s.count('\\'+name) #print('substitute_command_ext name = %s len(s)=%s occur = %d' % (name, len(s), noccur)) lookfor = ('\\' + name) # +( '[' if nopt > 0 else '{') try: start = get_next_unescaped_appearance(s, lookfor, 0, next_char_not_word=True) assert s[start:].startswith(lookfor) # print('s[start:] = %r starts with %r ' % (s[start:start+14], lookfor)) except NotFound: #print('no string %r found' % lookfor) return s before = s[:start] rest = s[start:] # print('before: %r' % before) assert s[start:].startswith(lookfor) # print('s[start:]: %r' % s[start:]) assert rest.startswith(lookfor) consume = consume0 = s[start + len(lookfor):] opts = [] args = [] # print('---- %r' % name) # print('consume= %r'% consume) for _ in range(nopt): consume = consume_whitespace(consume) if not consume or consume[0] != '[': # print('skipping option') opt = None else: opt_string, consume = get_balanced_brace(consume) opt = opt_string[1:-1] # remove brace # print('opt string %r consume %r opt = %r' % (opt_string, consume, opt)) opts.append(opt) # print('after opts= %r'% consume) for _ in range(nargs): consume = consume_whitespace(consume) if not consume or consume[0] != '{': msg = 'Command %r: Expected {: got %r. opts=%s args=%s' % ( name, consume[0], opts, args) character = start character_end = len(s) - len(consume) where = Where(s, character, character_end) raise DPSyntaxError(msg, where=where) arg_string, consume2 = get_balanced_brace(consume) assert arg_string + consume2 == consume consume = consume2 arg = arg_string[1:-1] # remove brace args.append(arg) # print('*') # print('substitute_command_ext for %r : args = %s opts = %s consume0 = %r' % (name, args, opts, consume0)) args = tuple(args) opts = tuple(opts) replace = f(args, opts) if replace is None: msg = 'function %s returned none' % f raise Exception(msg) # nchars = len(consume0) - len(consume) assert consume0.endswith(consume) # print('consume0: %r' % consume0[:nchars]) # print('%s %s %s -> %s ' % (f.__name__, args, opts, replace)) # print('substitute_command_ext calling itself len(s*)=%s occur* = %d' % # (len(consume), consume.count('\\'+name))) after_tran = substitute_command_ext(consume, name, f, nargs, nopt) res = before + replace + after_tran # print('before: %r' % before) # print('replace: %r' % replace) # print('after_tran: %r' % after_tran) # assert not ('\\' + name ) in res, res return res
def assert_not_inside(substring, s): if substring in s: i = s.index(substring) w = Where(s, i, i + len(substring)) msg = 'I found the forbidden substring %r in string.' % substring raise DPSyntaxError(msg, where=w)
def check_no_tabs(s): if '\t' in s: i = s.index('\t') msg = "Tabs bring despair (e.g. Markdown does not recognize them.)" where = Where(s, i) raise DPSyntaxError(msg, where=where)
def parse_wrap(expr, string): """ transparent to MemoryError """ from .refinement import namedtuple_visitor_ext if isinstance(string, unicode): msg = 'The string is unicode. It should be a str with utf-8 encoding.' msg += '\n' + string.encode('utf-8').__repr__() raise ValueError(msg) check_isinstance(string, bytes) # Nice trick: the remove_comments doesn't change the number of lines # it only truncates them... string0 = remove_comments(string) if not string0.strip(): msg = 'Nothing to parse.' where = Where(string, character=len(string)) raise DPSyntaxError(msg, where=where) try: try: w = str(find_parsing_element(expr)) except ValueError: w = '(unknown)' with timeit(w, MCDPConstants.parsing_too_slow_threshold): expr.parseWithTabs() parsed = expr.parseString(string0, parseAll=True) # [0] def transform(x, parents): # @UnusedVariable if x.where is None: # pragma: no cover msg = 'Where is None for this element' raise_desc(DPInternalError, msg, x=recursive_print(x), all=recursive_print(parsed[0])) where = translate_where(x.where, string) return get_copy_with_where(x, where) parsed_transformed = namedtuple_visitor_ext(parsed[0], transform) if hasattr(parsed_transformed, 'where'): # could be an int, str assert_equal(parsed_transformed.where.string, string) res = fix_whitespace(parsed_transformed) return [res] except (ParseException, ParseFatalException) as e: where1 = Where(string0, e.loc) where2 = translate_where(where1, string) s0 = e.__str__() check_isinstance(s0, bytes) s = s0 e2 = DPSyntaxError(s, where=where2) raise DPSyntaxError, e2.args, sys.exc_info()[2] except DPSemanticError as e: msg = 'This should not throw a DPSemanticError' raise_wrapped(DPInternalError, e, msg, exc=sys.exc_info()) except MemoryError as e: raise except RuntimeError as e: msg = 'RuntimeError %s while parsing string.' % (type(e).__name__) msg += '\n' + indent(string, 'string: ') compact = 'maximum recursion depth' in str(e) # compact = False # XXX raise_wrapped(DPInternalError, e, msg, compact=compact) except BaseException as e: msg = 'Unexpected exception %s while parsing string.' % ( type(e).__name__) msg += '\n' + indent(string, 'string: ') raise_wrapped(DPInternalError, e, msg)