(* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. *) module import common, cstdio, cstdlib, lexer, ast type ElnaErrorKind* = ( unexpected_token, undefined_symbol, undefined_member, duplicate_declaration ) ElnaError* = record(ElnaListNode) kind: ElnaErrorKind; position: ElnaPosition end ElnaErrorUnexpectedToken* = record(ElnaError) expected: [16]ElnaLexerKind; possibilities: Word; got: ElnaLexerKind end ElnaErrorUndefinedSymbol* = record(ElnaError) symbol_name: []const Word8 end ElnaErrorUndefinedMember* = record(ElnaError) aggregate_name: []const Word8; member_name: []const Word8 end ElnaErrorDuplicateDeclaration* = record(ElnaError) symbol_name: []const Word8 end proc elna_error_unexpected_token_create*(cursor: ^ElnaLexerCursor; number_of_expected: Word) -> ^ElnaErrorUnexpectedToken var parser_error: ^ElnaErrorUnexpectedToken begin parser_error := malloc#[ElnaErrorUnexpectedToken](#size(ElnaErrorUnexpectedToken)); parser_error^.next := nil; parser_error^.kind := ElnaErrorKind.unexpected_token; parser_error^.position := cursor^.position; parser_error^.possibilities := number_of_expected; parser_error^.got := cursor^.token^.kind return parser_error proc elna_error_duplicate_declaration_create*(position: ElnaPosition; symbol_name: []const Word8) -> ^ElnaErrorDuplicateDeclaration var declaration_error: ^ElnaErrorDuplicateDeclaration begin declaration_error := malloc#[ElnaErrorDuplicateDeclaration](#size(ElnaErrorDuplicateDeclaration)); declaration_error^.next := nil; declaration_error^.kind := ElnaErrorKind.duplicate_declaration; declaration_error^.position := position; declaration_error^.symbol_name := symbol_name return declaration_error proc elna_error_undefined_symbol_create*(position: ElnaPosition; symbol_name: []const Word8) -> ^ElnaErrorUndefinedSymbol var result: ^ElnaErrorUndefinedSymbol begin result := malloc#[ElnaErrorUndefinedSymbol](#size(ElnaErrorUndefinedSymbol)); result^.next := nil; result^.kind := ElnaErrorKind.undefined_symbol; result^.position := position; result^.symbol_name := symbol_name return result proc elna_error_undefined_member_create*(position: ElnaPosition; aggregate, member: []const Word8) -> ^ElnaErrorUndefinedMember var result: ^ElnaErrorUndefinedMember begin result := malloc#[ElnaErrorUndefinedMember](#size(ElnaErrorUndefinedMember)); result^.next := nil; result^.kind := ElnaErrorKind.undefined_member; result^.position := position; result^.aggregate_name := aggregate; result^.member_name := member return result proc elna_error_print_token*(kind: ElnaLexerKind) begin case kind of ElnaLexerKind._const: write_s("\"const\"") | ElnaLexerKind._var: write_s("\"var\"") | ElnaLexerKind._proc: write_s("\"proc\"") | ElnaLexerKind._type: write_s("\"type\"") | ElnaLexerKind._begin: write_s("\"begin\"") | ElnaLexerKind._end: write_s("\"end\"") | ElnaLexerKind._if: write_s("\"if\"") | ElnaLexerKind._then: write_s("\"then\"") | ElnaLexerKind._else: write_s("\"else\"") | ElnaLexerKind._elsif: write_s("\"elsif\"") | ElnaLexerKind._extern: write_s("\"extern\"") | ElnaLexerKind._record: write_s("\"record\"") | ElnaLexerKind.boolean: write_s("BOOLEAN") | ElnaLexerKind.null: write_s("NIL") | ElnaLexerKind.and: write_s("\"&\"") | ElnaLexerKind._or: write_s("\"or\"") | ElnaLexerKind._xor: write_s("\"xor\"") | ElnaLexerKind.not: write_s("\"~\"") | ElnaLexerKind._return: write_s("\"return\"") | ElnaLexerKind._cast: write_s("\"cast\"") | ElnaLexerKind.trait: write_s("TRAIT") | ElnaLexerKind.left_paren: write_s("\"(\"") | ElnaLexerKind.right_paren: write_s("\")\"") | ElnaLexerKind.left_square: write_s("\"[\"") | ElnaLexerKind.right_square: write_s("\"]\"") | ElnaLexerKind.greater_equal: write_s("\">=\"") | ElnaLexerKind.less_equal: write_s("\"<=\"") | ElnaLexerKind.greater_than: write_s("\">\"") | ElnaLexerKind.less_than: write_s("\"<\"") | ElnaLexerKind.not_equal: write_s("\"<>\"") | ElnaLexerKind.equals: write_s("\"=\"") | ElnaLexerKind.semicolon: write_s("\";\"") | ElnaLexerKind.dot: write_s("\".\"") | ElnaLexerKind.comma: write_s("\",\"") | ElnaLexerKind.plus: write_s("\"+\"") | ElnaLexerKind.arrow: write_s("\"->\"") | ElnaLexerKind.minus: write_s("\"-\"") | ElnaLexerKind.multiplication: write_s("\"*\"") | ElnaLexerKind.division: write_s("\"/\"") | ElnaLexerKind.remainder: write_s("\"%\"") | ElnaLexerKind.assignment: write_s("\":=\"") | ElnaLexerKind.colon: write_s("\":\"") | ElnaLexerKind.hat: write_s("\"^\"") | ElnaLexerKind.at: write_s("\"@\"") | ElnaLexerKind.comment: write_s("COMMENT") | ElnaLexerKind.string: write_s("STRING") | ElnaLexerKind.character: write_s("CHARACTER") | ElnaLexerKind.integer: write_s("INTEGER") | ElnaLexerKind.word: write_s("WORD") | ElnaLexerKind.eof: write_s("EOF") else write_s("UNKNOWN") end return proc elna_error_print_unexpected_token*(current_error: ^ElnaErrorUnexpectedToken) begin write_s("Parse error: Expecting token "); elna_error_print_token(current_error^.expected[1]); write_s("; got "); elna_error_print_token(current_error^.got); write_s(". ") return proc elna_error_print_undefined_member*(current_error: ^ElnaErrorUndefinedMember) begin write_s("Semantic error: Member \""); write_s(current_error^.member_name); write_s("\" is not accessible on \""); write_s(current_error^.aggregate_name); write_s("\". ") return proc elna_error_print_undefined_symbol*(current_error: ^ElnaErrorUndefinedSymbol) begin write_s("Semantic error: Undefined symbol \""); write_s(current_error^.symbol_name); write_s("\". ") return proc elna_error_print_duplicate_declaration*(current_error: ^ElnaErrorDuplicateDeclaration) begin write_s("Semantic error: Duplicate declaration \""); write_s(current_error^.symbol_name); write_s("\". ") return proc elna_error_print*(current_error: ^ElnaError) begin case current_error^.kind of ElnaErrorKind.unexpected_token: elna_error_print_unexpected_token(cast(current_error: ^ElnaErrorUnexpectedToken)) | ElnaErrorKind.undefined_symbol: elna_error_print_undefined_symbol(cast(current_error: ^ElnaErrorUndefinedSymbol)) | ElnaErrorKind.undefined_member: elna_error_print_undefined_member(cast(current_error: ^ElnaErrorUndefinedMember)) | ElnaErrorKind.duplicate_declaration: elna_error_print_duplicate_declaration(cast(current_error: ^ElnaErrorDuplicateDeclaration)) else write_s("Unknown error. ") end; write_s("Line "); write_u(current_error^.position.start_location.line); write_s(", column "); write_u(current_error^.position.start_location.column); write_s(".\n") return end.