104 lines
3.4 KiB
Nim
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import std/os
import std/osproc
import std/strutils
import std/streams
import std/pegs
type
CompileInfo* = object
templFile*: string
errorFile*: string
errorLine*, errorColumn*: int
templLine*, templColumn*: int
msg*: string
fullMsg*: string
compileTime*: float
exitCode*: int
let
# Error pegs, taken from testament tester
pegLineTemplate =
peg"{[^(]*} '(' {\d+} ', ' {\d+} ') ' 'template/generic instantiation from here'.*"
pegLineError =
peg"{[^(]*} '(' {\d+} ', ' {\d+} ') ' ('Error') ':' \s* {.*}"
pegOtherError = peg"'Error:' \s* {.*}"
pegError = pegLineError / pegOtherError
pegSuccess = peg"'Hint: operation successful' {[^;]*} '; ' {\d+} '.' {\d+} .*"
# Timestamp pegs
# peg for unix timestamp, basically any float with 6 digits after the decimal
# Not ideal - could also improve by checking for the location in the line
pegUnixTimestamp = peg"{\d+} '.' {\d\d\d\d\d\d} \s"
# peg for timestamp with format yyyy-MM-dd HH:mm:sszzz
pegRfcTimestamp = peg"{\d\d\d\d} '-' {\d\d} '-' {\d\d} ' ' {\d\d} ':' {\d\d} ':' {\d\d} {'+' / '-'} {\d\d} ':' {\d\d} \s"
# Thread/process id is unpredictable..
pegXid* = peg"""'tid' (('=') / ('":') / (': ') / (': ') / ('=') / ('>')) \d+"""
proc cmpIgnorePegs*(a, b: string, pegs: varargs[Peg]): bool =
## true when input strings are equal without regard to supplied pegs
var
aa = a
bb = b
for peg in pegs:
aa = aa.replace(peg, "dummy")
bb = bb.replace(peg, "dummy")
result = aa == bb
proc cmpIgnoreTimestamp*(a, b: string, timestamp = ""): bool =
## true when input strings are equal without regard to supplied timestamp form
if timestamp.len == 0:
result = cmpIgnorePegs(a, b, pegXid)
elif timestamp == "RfcTime":
result = cmpIgnorePegs(a, b, pegRfcTimestamp, pegXid)
elif timestamp == "UnixTime":
result = cmpIgnorePegs(a, b, pegUnixTimestamp, pegXid)
proc cmpIgnoreDefaultTimestamps*(a, b: string): bool =
## true when input strings are equal without regard to timestamp
if cmpIgnorePegs(a, b, pegRfcTimestamp, pegXid):
result = true
elif cmpIgnorePegs(a, b, pegUnixTimestamp, pegXid):
result = true
proc parseCompileStream*(p: Process, output: Stream): CompileInfo =
## parsing compiler output (based on testament tester)
result.exitCode = -1
var
line = newStringOfCap(120).TaintedString
suc, err, tmpl = ""
while true:
if output.readLine(line):
if line =~ pegError:
# `err` should contain the last error/warning message
err = line
elif line =~ pegLineTemplate and err == "":
# `tmpl` contains the last template expansion before the error
tmpl = line
elif line =~ pegSuccess:
suc = line
if err != "":
result.fullMsg.add(line.string & "\p")
else:
result.exitCode = peekExitCode(p)
if result.exitCode != -1:
break
if tmpl =~ pegLineTemplate:
result.templFile = extractFilename(matches[0])
result.templLine = parseInt(matches[1])
result.templColumn = parseInt(matches[2])
if err =~ pegLineError:
result.errorFile = extractFilename(matches[0])
result.errorLine = parseInt(matches[1])
result.errorColumn = parseInt(matches[2])
result.msg = matches[3]
elif err =~ pegOtherError:
result.msg = matches[0]
elif suc =~ pegSuccess:
result.msg = suc
result.compileTime = parseFloat(matches[1] & "." & matches[2])
proc parseExecuteOutput*() = discard