summaryrefslogtreecommitdiff
path: root/src/print.rs
blob: 9306984ddd28e7dbd3c564b76bd772f084532242 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
use crate::*;

use log::LogLevel;

use SemanticTokenVariant as SemVar;
use SemanticParseError as SemErr;
use SyntacticParseError as SynErr;


/// Print all errors found in the semantic tokens, including those inside macro
/// definitions. Returns true if at least one error was printed.
pub fn print_semantic_errors(semantic_tokens: &[SemanticToken], source_code: &str) -> bool {
    let mut found_error = false;
    for semantic_token in semantic_tokens {
        match &semantic_token.variant {
            SemVar::Error(err) => {
                let context = Context {
                    source_code: source_code,
                    source: &semantic_token.source,
                };
                found_error = true;
                print_semantic_error(&err, context)
            }
            SemVar::MacroDefinition(definition) => {
                for body_token in &definition.body_tokens {
                    if let SemVar::Error(err) = &body_token.variant {
                        let context = Context {
                            source_code: source_code,
                            source: &body_token.source,
                        };
                        found_error = true;
                        print_semantic_error(err, context)
                    }
                }
            }
            _ => (),
        }
    }
    return found_error;
}

fn print_semantic_error(error: &SemanticParseError, context: Context) {
    let message = get_message_for_semantic_error(error);
    report_source_issue(LogLevel::Error, &context, &message);
}

fn get_message_for_semantic_error(error: &SemanticParseError) -> String {
    match error {
        SemErr::LabelDefinitionInMacroDefinition =>
            format!("Label cannot be defined inside a macro"),
        SemErr::MacroDefinitionInMacroDefinition =>
            format!("Macro cannot be defined inside a macro"),
        SemErr::StrayMacroTerminator =>
            format!("Macro definition terminator is missing a macro definition"),
        SemErr::StrayBlockClose =>
            format!("Block was not opened, add a '{{' character to open"),
        SemErr::UnclosedBlock =>
            format!("Block was not closed, add a '}}' character to close"),
        SemErr::UndefinedSymbol(name) =>
            format!("Undefined symbol, no label or macro has been defined with the name {name:?}"),
        SemErr::RedefinedSymbol((_, source)) =>
            format!("Redefined symbol, first defined at {}", source.location()),
        SemErr::MacroInvocationBeforeDefinition((_, source)) =>
            format!("Macro used before definition, definition is at {}", source.location()),
        SemErr:: SyntaxError(syntax_error) => match syntax_error {
            SynErr::UnterminatedComment =>
                format!("Unclosed comment, add a ')' character to close"),
            SynErr::UnterminatedRawString =>
                format!("Unclosed string, add a ' character to close"),
            SynErr::UnterminatedNullString =>
                format!("Unclosed string, add a \" character to close"),
            SynErr::InvalidPaddingValue(_) =>
                format!("Padding value must be two or four hexadecimal digits"),
        }
    }
}