momiji
m68k emulator infrastructure
About Source codeTable of contents
Parser
MISSING DESCRIPTION
This component allows the user to parse and analyze a string with valid m68k source code.
Basic usage example
The straightforward usage of this component is the following:
std::string code = /* ... */;
// Parse the source code
momiji::ParsingResult res = momiji::parse(code);
// Check if there was an error during parsing
if (!res)
{
momiji::ParserError error = res.error();
// Handle error in some way
return false;
}
// If there was no error, get the parsed instructions and labels
momiji::ParsingInfo parsingInfo = *res;
// Inspect the instructions
for (const auto& instruction : parsingInfo.instructions)
{
// ...
}
// Inspect the labels
for (const auto& label : parsingInfo.labels)
{
// ...
}
Most of the time, you may not need to go beyond handling a parsing error: almost all the other classes here are for introspecting and representing every sort of state.
You can manipulate the momiji::ParsingInfo
struct to do any sort of fun stuff
(injecting instructions?) but, ultimately, the most useful thing you can do with
it is passing it to the Compiler to compile the
instructions and get an executable.
Handling errors
The source code passed to the parser may be ill-formed. That’s ok! The parser
will let you know by returning a momiji::ParserError
and let you recover from
the error.
Handling it is fairly simple:
auto res = momiji::parse(/* ... */);
if (!res)
{
// Something happened
auto error = res.error();
// Obviously you can do whatever you want here, this is just an example
std::cout << "Error happened at line " << std::to_string(error.line)
<< "when parsing string '" << error.codeStr << "'.\n";
std::visit(error.errorType, asl::overload{
[] (const momiji::errors::InvalidRegisterNumber& x) {
std::cout << "Invalid register number '" << std::to_string(x.input)
<< "'.\n";
},
[] (const momiji::errors::DataTypeMismatch& x) {
// ...
},
[] (const momiji::errors::MissingCharacter& x) {
// ...
},
// ...
});
return false;
}
To visit the variant containing the type of error you can make a functor with
the appropriate operator()
s or use asl::overload
with lambdas.
No direct function to translate error codes to string is provided because of
localization issues: an application may want to translate the strings
differently or word them differently, so I think there’s no use in providing a
way to directly convert the errors to strings. You can make your own function
that calls Qt::tr()
or whatever you have to handle translations.
Inspecting instructions
Advanced users may need to inspect the vector of instructions and inject their own (or run some sort of static analysis of a program). It’s not that difficult, provided that you know what you’re doing.
auto res = momiji::parse(/* ... */);
if (!res)
{
/* ... */
}
auto parsingInfo = *res;
// Print information about each instruction
// The stuff with "custom::" is your own stuff, it's not provided by the library
for (const momiji::ParsedInstruction& instr : parsingInfo.instructions)
{
std::cout << "Instruction: " << custom::to_string(instr.instructionType) << "\n"
<< "Operands: " << custom::to_string(instr.operands) << "\n"
<< "Virtual PC: " << instr.programCounter << "\n"
<< "Source line: " << instr.sourceLine << "\n";
if (instr.instructionType == momiji::InstructionType::BranchCondition)
{
std::cout << "Branch condition: "
<< custom::to_string(instr.branchCondition) << "\n";
}
}
// Inject an "add.w d0, d1" in the third position
{
auto it = parsingInfo.instructions.begin() + 2;
momiji::ParsingInstruction instr;
instr.instructionType = momiji::InstructionType::Add;
// Two operands are ALWAYS provided for you
instr.operands[0] = momiji::operands::DataRegister{0};
instr.operands[1] = momiji::operands::DataRegister{1};
instr.dataType = momiji::DataType::Word;
parsingInfo.instructions.insert(it, instr);
}
Similar stuff can be done to inspect labels.
ASTs
An AST describes a compile-time mathematical expression which can be resolved to yield a 32-bit signed integer. An expression can be made of 32-bit signed integer numbers (…, -2, -1, 0, 1, 2, …), labels, binary operators and parenthesis.
When parsing move.w #123, some_label + 4
two ASTs
are created: one for the #123
immediate and the other for the
some_label + 4
address.
It’s possible to build complex expressions: move.w #(2 * 4 * a_label) / 2, d0
;
in that case the first operand is an immediate value corresponding to 4 times
the location of a label.
A generated AST is not optimized, which means that the parser doesn’t try to
reduce expressions (for example, reduce 2 + 2
from three nodes to just one
with the value 4
).
An optimizer is out of the scope of the library, you can write your own if you
need to.
In the future callable functions may be implemented (to calculate sin, cos, pow,
etc… at compile-time) along with miscellaneous utilities (eg: an !here
expression that would yield the current source location of the instruction).
Components
AST objects | Classes that represent the types of nodes that are present in a math AST |
Instruction operands | Classes that represent operand types in an instruction |
Parsing errors | Classes that represent parsing errors |
Classes
momiji::Breakpoint |
Breakpoint to be injected by the parser |
momiji::Label |
Vocabulary type to describe a label. |
momiji::ParsedInstruction |
A struct representing a parsed instruction. |
momiji::ParserError |
A struct representing a parsing error. |
momiji::ParserSettings |
Settings for the parser |
momiji::ParsingInfo |
Output of the parser describing all the found instructions and labels. |
Free functions
momiji::convertOperand |
|
||||
momiji::extractASTValue |
Extracts the AST value from an ASTOperand. |
||||
momiji::extractRegister |
Extracts the register number from a RegOperand. |
||||
momiji::mapOperand |
Executes a functor to an [ |
||||
momiji::parse |
Parses an m68k source code |
Enums
momiji::ParserOperand |
A lightweight enum describing the possible operand types |
momiji::ParserSection |
A lightweight enum describing a code section encountered during parsing. |
Typedefs
Type | Definition | Notes |
---|---|---|
momiji::Operand |
|
A discriminated union representing an operand in an instruction. |
momiji::LabelInfo |
|
The labels found in the source code. |
momiji::ParsingResult |
|
A value representing either the parsed data or an error. |