use crate::*; pub enum SyntacticToken { Comment(String), LabelDefinition(String), MacroDefinition(SyntacticMacroDefinition), RawValue(Value), Instruction(Instruction), Invocation(String), Padding(Value), String(Vec), BlockOpen, BlockClose, } pub struct SyntacticMacroDefinition { pub name: Tracked, pub body: Vec>, } pub enum SyntacticError { UnterminatedBlock, UnterminatedComment, UnterminatedRawString, UnterminatedNullString, UnterminatedMacroDefinition, UnmatchedBlockTerminator, UnmatchedCommentTerminator, UnmatchedMacroTerminator, InvalidPaddingValue, MacroDefinitionInMacroDefinition, LabelDefinitionInMacroDefinition, } pub fn report_syntactic_errors(errors: &[Tracked], source_code: &str) { for error in errors { report_syntactic_error(error, source_code); } } fn report_syntactic_error(error: &Tracked, source_code: &str) { let context = Context { source_code: &source_code, source: &error.source }; let message = match &error.value { SyntacticError::UnterminatedBlock => "Block was not terminated, add a '}' character to terminate", SyntacticError::UnterminatedComment => "Comment was not terminated, add a ')' character to terminate", SyntacticError::UnterminatedRawString => "Raw string was not terminated, add a ' character to terminate", SyntacticError::UnterminatedNullString => "Null-terminated string was not terminated, add a '\"' character to terminate", SyntacticError::UnterminatedMacroDefinition => "Macro definition was not terminated, add a ';' character to terminate", SyntacticError::UnmatchedBlockTerminator => "Attempted to terminate a block, but no block was in progress", SyntacticError::UnmatchedCommentTerminator => "Attempted to terminate a comment, but no comment was in progress", SyntacticError::UnmatchedMacroTerminator => "Attempted to terminate a macro definition, but no macro definition was in progress", SyntacticError::InvalidPaddingValue => "The padding value must be either two or four hexadecimal digits", SyntacticError::MacroDefinitionInMacroDefinition => "A macro cannot be defined inside another macro", SyntacticError::LabelDefinitionInMacroDefinition => "A label cannot be defined inside a macro", }; report_source_issue(LogLevel::Error, &context, message); } pub fn print_syntactic_token(i: usize, token: &SyntacticToken) { match token { SyntacticToken::Comment(_) => indent!(i, "Comment"), SyntacticToken::LabelDefinition(name) => indent!(i, "LabelDefinition({name})"), SyntacticToken::MacroDefinition(definition) => { indent!(i, "MacroDefinition({})", definition.name); for token in &definition.body { print_syntactic_token(i+1, token); } } SyntacticToken::RawValue(value) => indent!(i, "RawValue({value})"), SyntacticToken::Instruction(instruction) => indent!(i, "Instruction({instruction})"), SyntacticToken::Invocation(name) => indent!(i, "Invocation({name})"), SyntacticToken::Padding(value) => indent!(i, "Padding({value})"), SyntacticToken::String(bytes) => indent!(i, "String({})", String::from_utf8_lossy(bytes)), SyntacticToken::BlockOpen => indent!(i, "BlockOpen"), SyntacticToken::BlockClose => indent!(i, "BlockOpen"), } }