1 /**
2  * Token types for Ethereum Virtual Machine (EVM) assembler scanner.
3  *
4  * Copyright © 2016, Eric Scrivner
5  *
6  * License: Subject to the terms of the MIT license, as written in the included
7  * LICENSE.txt file.
8  * Authors: Eric Scrivner
9  */
10 module phlogiston.assembler.token;
11 
12 import std.bigint;
13 import std.conv;
14 import std..string;
15 import std.traits;
16 
17 /**
18  * Base class for all token types
19  */
20 interface Token {
21 }
22 
23 /// Opcode representing whitespace
24 class Whitespace : Token {
25     public override string toString() {
26         return "Whitespace";
27     }
28 }
29 
30 ///
31 unittest {
32     auto token = new Whitespace();
33     assert(token.toString() == "Whitespace");
34 }
35 
36 /// Opcode representing end of the input stream
37 class EndOfStream : Token {
38     public override string toString() {
39         return "EndOfStream";
40     }
41 }
42 
43 ///
44 unittest {
45     auto token = new EndOfStream();
46     assert(token.toString() == "EndOfStream");
47 }
48 
49 /// Represents a numerical value
50 class Number : Token {
51     /// The numerical value
52     public BigInt m_value;
53 
54     this(BigInt value) {
55         this.m_value = value;
56     }
57 
58     public override string toString() {
59         return format("Number(0x%x)", m_value);
60     }
61 }
62 
63 ///
64 unittest {
65     BigInt value = BigInt("0x1234");
66     auto token = new Number(value);
67     assert(token.toString() == "Number(0x1234)");
68     assert(token.m_value == value);
69 }
70 
71 /**
72  * Represents an opcode that works only with the EVM stack, and therefore has
73  * no arguments.
74  */
75 class StackOpcode : Token {
76     /// The stack-based opcode
77     public string m_opcode;
78 
79     this(string opcode) {
80         this.m_opcode = opcode;
81     }
82 
83     public override string toString() {
84         return format("StackOpcode(%s)", m_opcode);
85     }
86 }
87 
88 ///
89 unittest {
90     auto token = new StackOpcode("STOP");
91     assert(token.toString() == "StackOpcode(STOP)");
92     assert(token.m_opcode == "STOP");
93 }
94 
95 /**
96  * Represents an opcode that pushes values onto the EVM stack and so takes an
97  * argument.
98  */
99 class PushOpcode : Token {
100     /// The push opcode
101     public string m_opcode;
102 
103     this(string opcode) {
104         this.m_opcode = opcode;
105     }
106 
107     public override string toString() {
108         return format("PushOpcode(%s)", m_opcode);
109     }
110 }
111 
112 ///
113 unittest {
114     auto token = new PushOpcode("PUSH1");
115     assert(token.toString() == "PushOpcode(PUSH1)");
116     assert(token.m_opcode == "PUSH1");
117 }