diff --git a/src/components/Code.astro b/src/components/Code.astro index fa58787..bd76fc7 100644 --- a/src/components/Code.astro +++ b/src/components/Code.astro @@ -5,13 +5,13 @@ import CodeError from "./docs/CodeError.astro"; const { thpcode, no_warnings, level } = Astro.props; -const [native_html, error_type, error_message] = await native_highlighter(thpcode, level as HighlightLevel); +const [native_html, error_message] = await native_highlighter(thpcode, level as HighlightLevel); ---
thp
{ no_warnings !== true && error_message !== null && ( - + ) } diff --git a/src/components/docs/CodeError.astro b/src/components/docs/CodeError.astro index 3334ae9..06b5cb0 100644 --- a/src/components/docs/CodeError.astro +++ b/src/components/docs/CodeError.astro @@ -1,8 +1,8 @@ --- -const { error_type = "Unknown", error_message } = Astro.props; +const { error_message } = Astro.props; ---
- {error_type} error: + Compilation error: {error_message}
diff --git a/src/lexer/highlighter.ts b/src/lexer/highlighter.ts index 1447e53..fa09d99 100644 --- a/src/lexer/highlighter.ts +++ b/src/lexer/highlighter.ts @@ -5,93 +5,59 @@ import type { MistiErr, Token, TokenizeResult, TokenType } from "./types"; const error_classes = "underline underline-offset-4 decoration-wavy decoration-red-500"; -export async function native_highlighter(code: string, level = HighlightLevel.Syntactic): Promise<[string, string, string | null]> { +/** + * Highlights code using the compiler + * + * Returns: + * - The tokens as a list of elements + * - An error message, if any + */ +export async function native_highlighter(code: string, level = HighlightLevel.Syntactic): Promise<[string, string | null]> { let formatted_code = leftTrimDedent(code).join("\n"); try { - let result = await native_lex(formatted_code); - return highlight_syntax(formatted_code, result, level); + let result = await native_lex(formatted_code, level); + return highlight_syntax(formatted_code, result); } catch (error) { return compiler_error(formatted_code, error as MistiErr); } } -function highlight_syntax(code: string, result: TokenizeResult, level: HighlightLevel): [string, string, string | null] { - let tokens_final: Array; +/** + * Highlights code using the compiler + * + * Returns: + * - The tokens as a list of elements + * - An error message, if any + */ +function highlight_syntax(code: string, result: TokenizeResult): [string, string | null] { + if (result.Ok) { + const tokens_html = render_tokens(code, result.Ok); - if (result.SemanticError) { - const [tokens, semanticError] = result.SemanticError; + return [tokens_html, null]; + } else if (result.MixedErr) { + const [tokens, errors] = result.MixedErr; + // TODO: Implement error rendering, based on the new error schema - if (level === HighlightLevel.Semantic) { - return semantic_error_highlighter(code, tokens, semanticError); - } else { - tokens_final = tokens; - } - } else if (result.SyntaxError) { - const [tokens, syntaxError] = result.SyntaxError; + const tokens_html = render_tokens(code, tokens); + return [tokens_html, `error code ${errors.error_code}`]; + } else if (result.Err) { + // TODO: Implement error rendering, based on the new error schema - if (level === HighlightLevel.Semantic || level === HighlightLevel.Syntactic) { - return syntax_error_highlighter(code, tokens, syntaxError); - } else { - tokens_final = tokens; - } - } else if (result.LexError) { - // There is no error level that bypasses a lex error - return lex_error_highlighter(code, result.LexError!); - } else if (result.Ok) { - tokens_final = result.Ok; + return [code, `lexical error ${result.Err.error_code}`] } else { console.error(result); throw new Error("Web page error: The compiler returned a case that wasn't handled."); } - - // At this point all error cases have been handled - // and tokens_final contains valid tokens. - - const output = highlight_tokens(code, tokens_final); - return [output, "", null]; } -/** - * Highlights code that has a lexic error - */ -function lex_error_highlighter(code: string, error: MistiErr): [string, string, string] { - // Create a single error token - - const err_pos = error.position; - const before_err = code.substring(0, err_pos); - const err_str = code[err_pos]; - const after_err = code.substring(err_pos + 1); - - const token = `${err_str}`; - - const all = `${before_err}${token}${after_err}`; - const [error_line, error_column] = absolute_to_line_column(code, error.position); - - // TODO: Transform absolute posijion (error.position) into line:column - return [all, "Lexical", error.reason + ` at line ${error_line}:${error_column} `] +/** A fatal error with the THP compiler */ +function compiler_error(code: string, error: MistiErr): [string, string] { + console.log(error); + return [code, "Fatal compiler error"]; } -function syntax_error_highlighter(code: string, tokens: Array, error: MistiErr): [string, string, string] { - const highlighted = highlight_tokens(code, tokens, error.error_start, error.error_end); - const [error_line, error_column] = absolute_to_line_column(code, error.error_start); - - const error_message = `${error.reason} at line ${error_line}:${error_column}`; - return [highlighted, "Syntax", error_message]; -} - -function semantic_error_highlighter(code: string, tokens: Array, error: MistiErr): [string, string, string] { - const highlighted = highlight_tokens(code, tokens, error.error_start, error.error_end); - const [error_line, error_column] = absolute_to_line_column(code, error.error_start); - - const error_message = `${error.reason} at line ${error_line}:${error_column}`; - return [highlighted, "Semantic", error_message]; -} - -function compiler_error(code: string, error: MistiErr): [string, string, string] { - return [code, "Fatal Compiler", error.message]; -} /** * Transforms a list of tokens into colored HTML, and underlines errors @@ -102,7 +68,7 @@ function compiler_error(code: string, error: MistiErr): [string, string, string] * @param error_end Absolute position to where the error ends. * @returns */ -function highlight_tokens(input: string, tokens: Array, error_start = -1, error_end = -1): string { +function render_tokens(input: string, tokens: Array, error_start = -1, error_end = -1): string { const input_chars = input.split(""); let output = ""; @@ -233,14 +199,14 @@ function translate_token_type(tt: TokenType, value: string): string { } } -const native_lex = (code: string) => new Promise((resolve, reject) => { +const native_lex = (code: string, level: HighlightLevel) => new Promise((resolve, reject) => { // Get binary path from .env const binary = import.meta.env.THP_BINARY; if (!binary) { throw new Error("THP_BINARY not set in .env"); } - const subprocess = spawn(binary, ["tokenize"]); + const subprocess = spawn(binary, ["tokenize", "-l", level.toString()]); let response = ""; let error = ""; diff --git a/src/lexer/types.ts b/src/lexer/types.ts index d6b35c2..a7e1806 100644 --- a/src/lexer/types.ts +++ b/src/lexer/types.ts @@ -60,12 +60,10 @@ export interface ErrorLabel { export interface TokenizeResult { /** All checks passed */ Ok?: Array, - /** There were semantic errors */ - SemanticError?: [Array, MistiErr], - /** There were syntax errors */ - SyntaxError?: [Array, MistiErr], - /** No checks passed */ - LexError?: MistiErr, + /** A non lexic error was found */ + MixedErr?: [Array, MistiErr], + /** A lexic error was found */ + Err?: MistiErr, } export enum HighlightLevel {