# imba$inlineHelpers=1 # create separate error-types with all the logic var util = require './helpers' const meta = WeakMap.new export class ImbaParseError < Error def self.wrap err # what about the stacktrace? self.new(err) def initialize e,o this:error = e @options = o or {} this:severity = @options:severity or 'error' let msg = e:message if let m = msg.match(/Unexpected '([\w\-]+)'/) if m[1] == 'TERMINATOR' msg = 'Unexpected newline' this:message = msg this:sourcePath = e:sourcePath this:line = e:line self get _options meta.get(self) set _options value meta.set(self,value) def set opts @options ||= {} for own k,v of opts @options[k] = v self def start var o = @options var idx = o:pos - 1 var tok = o:tokens and o:tokens[idx] while tok and (tok.@loc == -1 or tok.@loc == 0 or tok.@len == 0) tok = o:tokens[--idx] return tok get token return @token if @token var o = @options var idx = o:pos - 1 var tok = o:tokens and o:tokens[idx] while tok and (tok.@loc == -1 or tok.@loc == 0 or tok.@len == 0) tok = o:tokens[--idx] return @token = tok def desc var o = @options let msg = self:message if o:token and o:token.@loc == -1 'Syntax Error' else msg def loc @loc or start?.region def toJSON var o = @options var tok = start return {warn: yes, message: desc, loc: loc} def toNativeError let err = SyntaxError.new("hello") err:fileName = @sourcePath err:message = self:message err:stack = excerpt(colors: no, details: yes) err:lineNumber = self:lineNumber err:columnNumber = self:columnNumber return err def excerpt gutter: yes, colors: no, details: yes try var code = @code var loc = loc var lines = code.split(/\n/g) var locmap = util.locationToLineColMap(code) var lc = locmap[loc[0]] or [0,0] var ln = lc[0] var col = lc[1] var line = lines[ln] self:lineNumber = ln + 1 self:columnNumber = col var ln0 = Math.max(0,ln - 2) var ln1 = Math.min(ln0 + 5,lines:length) let lni = ln - ln0 var l = ln0 var colorize = do $1 if colors let color = self:severity == 'warn' ? 'yellow' : 'red' color = colors if colors isa String colorize = do util:ansi[color](util:ansi.bold($1)) var out = while l < ln1 var line = lines[l++] if gutter out = out.map do |line,i| let prefix = "{ln0 + i + 1}" while prefix:length < String(ln1):length prefix = " {prefix}" if i == lni " -> {prefix} | {line}" else " {prefix} | {line}" out[lni] = colorize(out[lni]) if details out.unshift(colorize(self:message)) return out.join('\n') + '\n' catch e return "" def prettyMessage var excerpt = self.excerpt export class ImbaTraverseError < ImbaParseError def loc @loc def excerpt var excerpt = super excerpt + '\n---\n' + this:error:stack