Commits

Lenard Lindstrom  committed df5ca4f

Add some parser code.

The initial parser returns a block of instructions. Also correct a problem
with the ClassReference Reference convertion operator, which prevented
parser.cpp from compiling.

  • Participants
  • Parent commits ccebe7a

Comments (0)

Files changed (6)

File include/imgblit/memory.hpp

         virtual ~ClassReference();
         ClassReference<D> &operator =(const ClassReference<D> &rvalue);
         ClassReference<D> &operator =(const Reference &rvalue);
-        operator Reference() { return Reference(ref_datum_p); }
+        operator Reference() const { return Reference(ref_datum_p); }
         D *operator ->() const { assert(ref_datum_p); return ref_datum_p; }
         D &operator *() const { assert(ref_datum_p); return *ref_datum_p; }
         bool operator !() const { return ref_datum_p == 0; }

File include/imgblit/parser.h

-#ifndef IMGBLIT_PARSER_H
-#define IMGBLIT_PARSER_H
-
-#include "scanner.h"
-
-namespace imgblit {
-    class Parser {
-
-    public:
-        Parser(Scanner &source);
-        virtual ~Parser();
-        Reference parse();
-    protected:
-        Scanner &psr_source;
-    private:
-        Parser();
-        Parser(const Parser &);
-        Parser & operator=(const Parser &);
-    };
-};
-
-#endif

File include/imgblit/parser.hpp

+#ifndef IMGBLIT_PARSER_HPP
+#define IMGBLIT_PARSER_HPP
+
+#include "imgblit/scanner.hpp"
+#include <string>
+#include <map>
+
+namespace imgblit {
+    using std::string;
+    using std::map;
+
+    class Node : public Datum {
+
+    public:
+        const string nd_identifier;
+        Node(const char *identifier) : nd_identifier(identifier) { }
+        Node(const string &identifier) : nd_identifier(identifier) { }
+        void write(ostream &os) const;
+    };
+
+    typedef ClassReference<Node> NodeRef;
+
+
+    class Value : public Node {
+
+    public:
+        Value(const string &identifier, const char *type) :
+            Node(identifier), v_type(type) { }
+        const char *v_type;
+        void write(ostream &os) const;
+    };
+
+    typedef ClassReference<Value> ValueRef;
+
+
+    class Instruction : public Node {
+
+    public:
+        Instruction(const char *identifier) : Node(identifier) { }
+        vector<ValueRef> insn_arguments;
+        void write(ostream &os) const;
+    };
+
+    typedef ClassReference<Instruction> InstructionRef;
+    InstructionRef &operator <<(InstructionRef &r, ValueRef arg);
+    InstructionRef &operator <<(InstructionRef &r, Value *arg);
+    size_t size(const InstructionRef &r);
+
+
+    class Block : public Node {
+
+    public:
+        Block() : Node("<block>") { }
+        Block(const char *identifier) : Node(identifier) { }
+        Block(const string &identifier) : Node(identifier) { }
+        vector<InstructionRef> blk_instructions;
+        void write(ostream &os) const;
+    };
+
+    typedef ClassReference<Block> BlockRef;
+    BlockRef &operator <<(BlockRef &r, InstructionRef arg);
+    BlockRef &operator <<(BlockRef &r, Instruction *arg);
+    size_t size(const BlockRef &r);
+
+
+    class Parser {
+
+    public:
+        typedef InstructionRef (*instruction_parser)(Scanner &source);
+        typedef map<const string, instruction_parser> reserved_words;
+        Parser(Scanner &source) : psr_source(source) { }
+        virtual ~Parser();
+        instruction_parser &operator [](const char *identifier);
+        instruction_parser &operator [](const string &identifier);
+        BlockRef parse();
+    protected:
+        Scanner &psr_source;
+        reserved_words instruction_set;
+    private:
+        Parser();
+        Parser(const Parser &);
+        Parser &operator=(const Parser &);
+    };
+};
+
+#endif

File include/imgblit/scanner.hpp

         Scanner(const Scanner &);
         Scanner & operator=(const Scanner &);
     };
-
-    class Parser {
-
-    public:
-        Parser(Scanner &source);
-        virtual ~Parser();
-        Reference parse();
-    protected:
-        Scanner &psr_source;
-    private:
-        Parser();
-        Parser(const Parser &);
-        Parser & operator=(const Parser &);
-    };
 };
 
 #endif

File src/parser.cpp

+#include "imgblit/parser.hpp"
+#include "imgblit/exceptions.hpp"
+#include "imgblit/internal.hpp"
+#include <ostream>
+#include <sstream>
+#include <list>
+#include <cstddef>
+
+using namespace imgblit;
+using std::stringstream;
+using std::size_t;
+using std::ostream;
+using std::endl;
+
+
+void
+Node::write(ostream &os) const
+{
+    os << "Node(" << nd_identifier.c_str() << ")";
+}
+
+
+void
+Value::write(ostream &os) const
+{
+    os << v_type << "(" << nd_identifier.c_str() << ")";
+}
+
+
+void
+Instruction::write(ostream &os) const
+{
+    size_t sz = insn_arguments.size();
+    size_t i = 0;
+
+    os << nd_identifier;
+    if (sz != 0) {
+        do {
+            os << " " << insn_arguments[i];
+            ++i;
+        }
+        while(i != sz);
+    }
+}
+
+
+void
+Block::write(ostream &os) const
+{
+    size_t sz = blk_instructions.size();
+
+    for (size_t i = 0; i < sz; ++i) {
+        os << blk_instructions[i] << endl;
+    }
+}
+
+
+namespace imgblit {
+    InstructionRef &
+    operator <<(InstructionRef &r, ValueRef arg)
+    {
+        if (!!r) {
+            r->insn_arguments.push_back(arg);
+        }
+        return r;
+    }
+
+    InstructionRef &
+    operator <<(InstructionRef &r, Value *arg)
+    {
+        assert(arg);
+        return r << ValueRef(arg);
+    }
+
+    size_t size(const InstructionRef &r)
+    {
+        if (!!r) {
+            return r->insn_arguments.size();
+        }
+        return 0;
+    }
+
+
+    BlockRef &
+    operator <<(BlockRef &r, InstructionRef arg)
+    {
+        if (!!r) {
+            r->blk_instructions.push_back(arg);
+        }
+        return r;
+    }
+
+    BlockRef &
+    operator <<(BlockRef &r, Instruction *arg)
+    {
+        assert(arg);
+        return r << InstructionRef(arg);
+    }
+
+    size_t size(const BlockRef &r)
+    {
+        if (!!r) {
+            return r->blk_instructions.size();
+        }
+        return 0;
+    }
+};
+
+
+Parser::~Parser()
+{
+}
+
+Parser::instruction_parser &
+Parser::operator [](const char *identifier)
+{
+    assert(identifier);
+    return instruction_set[string(identifier)];
+}
+
+Parser::instruction_parser &
+Parser::operator [](const string &identifier)
+{
+    return instruction_set[identifier];
+}
+
+BlockRef
+Parser::parse()
+{
+    BlockRef block(new Block);
+    psr_source.reset();
+    TokenRef next = psr_source.get_token();
+    instruction_parser parser = 0;
+    reserved_words::iterator i;
+    reserved_words::iterator end = instruction_set.end();
+
+    while (!!next) {
+        i = instruction_set.find(next->tk_lexeme);
+        if (i == end) {
+            stringstream emsg;
+            emsg << "Unknown instruction "
+                 << "\"" << next->tk_lexeme.c_str() << "\".";
+            throw ValueError(emsg.str());
+        }
+        block << i->second(psr_source);
+        next = psr_source.get_token();
+    }
+    return block;
+}

File test/testparser.cpp

+#include "imgblit/parser.hpp"
+#include <sstream>
+#include <cassert>
+
+#include <iostream>
+
+using namespace imgblit;
+using std::stringstream;
+
+void test();
+
+int main()
+{
+    test();
+    return 0;
+}
+
+
+const char *
+a_token(const string &s, intptr_t pos, intptr_t sz)
+{
+    const char * const class_name = "Value";
+    return class_name;
+}
+
+InstructionRef
+OP(Scanner &scanner)
+{
+    const char * const name = "OP";
+    return new Instruction(name);
+}
+
+InstructionRef
+UNARYOP(Scanner &scanner)
+{
+    const char * const name = "UNARYOP";
+    InstructionRef i(new Instruction(name));
+    TokenRef t = scanner.get_token();
+    i << new Value(t->tk_lexeme, t->tk_class);
+    return i;
+}
+
+InstructionRef
+BINOP(Scanner &scanner)
+{
+    const char * const name = "BINOP";
+    InstructionRef i(new Instruction(name));
+    TokenRef t = scanner.get_token();
+    i << new Value(t->tk_lexeme, t->tk_class);
+    t = scanner.get_token();
+    i << new Value(t->tk_lexeme, t->tk_class);
+    return i;
+}
+
+void
+test()
+{
+    const char * const code = "OP UNARYOP abc BINOP def ghi";
+    Scanner scanner;
+    Parser parser(scanner);
+    stringstream capture;
+
+    scanner << a_token << code;
+    parser["OP"] = OP;
+    parser["UNARYOP"] = UNARYOP;
+    parser["BINOP"] = BINOP;
+    capture << parser.parse();
+    assert(capture.str() == ("OP\n"
+                             "UNARYOP Value(abc)\n"
+                             "BINOP Value(def) Value(ghi)\n"));
+}