Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- module fvmc.Compiler.Parser;
- import std.stdio, std.file, std.string;
- // A class encapsulating the parser functionality of fvmc. Use
- // this to parse any input into a set of statements.
- public class Parser {
- @property bool hasLoadedText() { return this.has_loaded; }
- @property Statement[] statements() { return this.fvmStmts; }
- public this(string filepath) {
- this.loadCodeFile(filepath);
- this.parseLoadedCode();
- if (parser_error) return;//throw new ParserException();
- }
- // load an FVM code file from a given path.
- private void loadCodeFile(string filepath)
- {
- try {
- if (!exists(filepath))
- throw new FileException("Could not access file \"" ~ filepath ~ "\":\n\t");
- this.fvm_Code = cast(string) read(filepath);
- this.has_loaded = true;
- }
- catch (FileException ex) {
- writeln(ex.msg);
- this.parser_error = true;
- }
- }
- private void parseLoadedCode() {
- if (!this.has_loaded) throw new Exception("No code loaded for parsing.");
- // The number of statements we've
- // parsed through so far.
- uint stmtCtr = 0;
- // The pieces of one statement
- string currMnemonic, arg0, arg1;
- string mnemonicValidChars = "abcdefghijklmnopqrstuvwxyz",
- argValidChars = "0123456789";
- // The current statement piece we're on
- string* currSection = &currMnemonic;
- // The curent set of valid characters.
- string* currValidChars = &mnemonicValidChars;
- // Counter for statement pieces iterated
- // through.
- int stmtPieceCtr = 0;
- // Whether we're currently parsing a
- // statement piece.
- bool onStmtPiece = false,
- newlineCheck = false;
- // Pass 1 - Transform into statements
- // Iterate through every character in
- // our loaded code. Statements are separated by
- // line-breaks (\n or \r\n).
- /*
- Statement Grammar:
- <statement> ::= <mnemonic> | " " <argument> | " " <argument>
- <mnemonic> ::= "mov" | "add" | "sub" | "mul" | "div" |
- "swap" | "and" | "or" | "xor" | "jmp" |
- "ret" | "bshr" | "bshl" | "end" | "not" |
- "push" | "pop"
- <argument> ::= <int-literal>
- */
- foreach (ubyte c; this.fvm_Code.toLower()) {
- // How we treat whitespace depends on whether
- // we're parsing a statement.
- if (c == ' ') {
- // If we're parsing a statement piece, it marks the end
- // of this piece, so we switch to the next piece.
- if (onStmtPiece) {
- if (stmtPieceCtr % 3 == 0) {
- currSection = &currMnemonic;
- currValidChars = &mnemonicValidChars;
- // If this isn't the first statement we're
- // parsing, increment our statement counter.
- stmtCtr = stmtPieceCtr > 0 ? 0 : ++stmtCtr;
- }
- else if (stmtPieceCtr % 3 == 1) {
- currSection = &arg0;
- currValidChars = &argValidChars;
- }
- else if (stmtPieceCtr % 3 == 2) {
- currSection = &arg1;
- currValidChars = &argValidChars;
- }
- // Increment our statement piece counter.
- ++stmtPieceCtr;
- // We're now in-between statement pieces.
- onStmtPiece = false;
- }
- // If we're not on a statement piece, whitespace has
- // no meaning and we can just disregard it by moving on.
- else continue;
- }
- else if (c == '\r') {
- continue;
- }
- else if (c == '\n') {
- if ((*currSection).length == 0) continue;
- this.fvmStmts.length++;
- this.fvmStmts[stmtCtr++] = Statement(currMnemonic, arg0, arg1);
- stmtPieceCtr = 3;
- onStmtPiece = false;
- currMnemonic = arg0 = arg1 = "";
- currSection = &currMnemonic;
- currValidChars = &mnemonicValidChars;
- }
- // If the character isn't one with a special meaning,
- // we can move on to determining whether it is a valid
- // character for the current statement piece.
- else {
- int equalities = 0;
- foreach (char vc; *currValidChars)
- equalities = vc == c ? ++equalities : equalities;
- if (equalities == 0) {
- writefln("Line %s: Invalid Character in statement (%s).",
- stmtCtr, cast(char) c);
- this.parser_error = true;
- } else {
- onStmtPiece = false;
- *currSection ~= c;
- }
- }
- }
- newlineCheck = false;
- }
- private:
- bool has_loaded;
- string fvm_Code;
- Statement[] fvmStmts;
- // If true, this will prevent the parser/compiler/thing
- // from advancing to its next pass and will throw a
- // ParserException.
- bool parser_error;
- };
- public class ParserException : Exception { public this() { super(""); }; }
- public struct Statement {
- public this (string mnemonic, string arg0, string arg1) {
- writefln("Statement Instantiated: %s :: %s :: %s",
- mnemonic, arg0, arg1
- );
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement