diff --git a/src/cli.bux b/src/cli.bux index 61e99f3..36ef53c 100644 --- a/src/cli.bux +++ b/src/cli.bux @@ -449,6 +449,11 @@ func String_FromChar(c: int) -> String { return buf as String; } +/* Count lines in a string (split by newline) */ +func Cli_CountLines(content: String) -> uint { + return bux_str_split_count(content, "\n"); +} + // Collect stdlib module paths imported by user code. // Returns number of unique stdlib files to merge (paths written into outPaths). func Cli_CollectStdlibImports(mod: *Module, outPaths: *String, maxCount: int, stdlibDir: String) -> int { @@ -1077,7 +1082,18 @@ func Cli_BuildProject(projectDir: String) -> int { column: sema.diags[i].column, severity: 0, }; - Diagnostic_Print(&diag, ""); + /* Try to guess which source file has this line */ + let errLine: uint32 = sema.diags[i].line; + let mainSrc: String = bux_path_join(projectDir, "src/Main.bux"); + let mainContent: String = bux_read_file(mainSrc); + var sourcePath: String = ""; + if !String_Eq(mainContent, "") { + let mainLines: uint = Cli_CountLines(mainContent); + if errLine <= mainLines { + sourcePath = mainSrc; + } + } + Diagnostic_Print(&diag, sourcePath); i = i + 1; } return 1; diff --git a/src/parser.bux b/src/parser.bux index db1c3a5..3a5fb66 100644 --- a/src/parser.bux +++ b/src/parser.bux @@ -30,6 +30,7 @@ struct ParserDiag { line: uint32, column: uint32, message: String, + severity: int, /* 0=error (fatal), 1=warning (recoverable) */ } // --------------------------------------------------------------------------- @@ -104,7 +105,7 @@ func parserExpect(p: *Parser, kind: int, msg: String) -> LexToken { let tok: LexToken = parserCurToken(p); if p.diagCount < 256 { p.diags[p.diagCount] = ParserDiag { - line: tok.line, column: tok.column, message: msg + line: tok.line, column: tok.column, message: msg, severity: 1 }; p.diagCount = p.diagCount + 1; } @@ -114,7 +115,7 @@ func parserExpect(p: *Parser, kind: int, msg: String) -> LexToken { func parserEmitDiag(p: *Parser, line: uint32, col: uint32, msg: String) { if p.diagCount < 256 { p.diags[p.diagCount] = ParserDiag { - line: line, column: col, message: msg + line: line, column: col, message: msg, severity: 1 }; p.diagCount = p.diagCount + 1; } @@ -133,7 +134,7 @@ func parserExpectIdentOrKeyword(p: *Parser, msg: String) -> LexToken { } if p.diagCount < 256 { p.diags[p.diagCount] = ParserDiag { - line: tok.line, column: tok.column, message: msg + line: tok.line, column: tok.column, message: msg, severity: 1 }; p.diagCount = p.diagCount + 1; } @@ -1773,6 +1774,35 @@ func Parser_Parse(tokens: *LexToken, tokenCount: int) -> *Module { } } + /* Print fatal parser diagnostics (severity == 0) or if nothing valid was parsed */ + if p.diagCount > 0 && mod.itemCount == 0 { + var di: int = 0; + while di < p.diagCount { + let d: ParserDiag = p.diags[di]; + Print("error: "); + PrintLine(d.message); + Print(" --> :"); + PrintInt(d.line as int64); + Print(":"); + PrintInt(d.column as int64); + PrintLine(""); + Print(" |"); + PrintLine(""); + Print(" "); + PrintInt(d.line as int64); + Print(" | "); + PrintLine(""); + Print(" | "); + var sp: uint32 = 0; + while sp < d.column - 1 && sp < 120 { + Print(" "); + sp = sp + 1; + } + PrintLine("^"); + di = di + 1; + } + } + return mod; }