Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Side by Side Diff: chrome/tools/profile_reset/jtl_compiler.cc

Issue 24998003: Compiler for the JSON Traversal Language. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed comments, added some unittests. Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/tools/profile_reset/jtl_compiler.h"
6
7 #include <map>
8 #include <string>
9
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/strings/string_util.h"
13 #include "chrome/browser/profile_resetter/jtl_foundation.h"
14 #include "chrome/tools/profile_reset/jtl_parser.h"
15
16 namespace jtl = jtl_foundation;
17
18 namespace {
19
20 // Serializes symbols into byte-code in a streaming manner.
21 class ByteCodeWriter {
22 public:
23 explicit ByteCodeWriter(std::string* output) : output_(output) {}
24 ~ByteCodeWriter() {}
25
26 void WriteUint8(uint8 value) { output_->push_back(static_cast<char>(value)); }
27 void WriteOpCode(uint8 op_code) { WriteUint8(op_code); }
28 void WriteHash(const std::string& hash) {
29 CHECK(hash.size() == jtl::kHashSizeInBytes);
battre 2013/10/01 12:18:26 nit: CHECK_EQ(jtl::kHashSizeInBytes, hash.size());
engedy 2013/10/01 15:09:33 Done.
30 *output_ += hash;
31 }
32 void WriteBool(bool value) { WriteUint8(value ? 1u : 0u); }
33
34 private:
35 std::string* output_;
36
37 DISALLOW_COPY_AND_ASSIGN(ByteCodeWriter);
38 };
39
40 // Encapsulates meta-data about all instructions, and is capable of transcoding
41 // each instruction from a parsed text-based format to byte-code.
42 class InstructionSet {
43 public:
44 InstructionSet() {
45 // Define each instruction in this list.
46 Add(Instruction("node", jtl::NAVIGATE, Arguments(Hash)));
47 Add(Instruction("any", jtl::NAVIGATE_ANY, Arguments()));
48 Add(Instruction("back", jtl::NAVIGATE_BACK, Arguments()));
49 Add(Instruction("store_bool", jtl::STORE_BOOL, Arguments(Hash, Bool)));
50 Add(Instruction("compare_stored_bool",
51 jtl::COMPARE_STORED_BOOL,
52 Arguments(Hash, Bool, Bool)));
53 Add(Instruction("store_hash", jtl::STORE_HASH, Arguments(Hash, Hash)));
54 Add(Instruction("compare_stored_hash",
55 jtl::COMPARE_STORED_HASH,
56 Arguments(Hash, Hash, Hash)));
57 Add(Instruction("compare_bool", jtl::COMPARE_NODE_BOOL, Arguments(Bool)));
58 Add(Instruction("compare_hash", jtl::COMPARE_NODE_HASH, Arguments(Hash)));
59 Add(Instruction("break", jtl::STOP_EXECUTING_SENTENCE, Arguments()));
60 }
61
62 JtlCompiler::CompileError::ErrorCode TranscodeInstruction(
63 const std::string& name,
64 const ListValue& arguments,
65 bool ends_sentence,
66 const jtl::Hasher& hasher,
67 ByteCodeWriter* target) const {
68 if (instruction_map_.count(name) == 0)
69 return JtlCompiler::CompileError::INVALID_OPERATION_NAME;
70 const Instruction& instruction(instruction_map_.at(name));
71 if (instruction.argument_types.size() != arguments.GetSize())
72 return JtlCompiler::CompileError::INVALID_ARGUMENT_COUNT;
73 target->WriteOpCode(instruction.op_code);
74 for (size_t i = 0; i < arguments.GetSize(); ++i) {
75 switch (instruction.argument_types[i]) {
76 case Bool: {
77 bool value;
battre 2013/10/01 12:18:26 nit: initialize to false.
engedy 2013/10/01 15:09:33 Done.
78 if (!arguments.GetBoolean(i, &value))
79 return JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE;
80 target->WriteBool(value);
81 break;
82 }
83 case Hash: {
84 std::string value;
85 if (!arguments.GetString(i, &value))
86 return JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE;
87 target->WriteHash(hasher.GetHash(value));
88 break;
89 }
90 default:
91 NOTREACHED();
92 return JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE;
93 }
94 }
95 if (ends_sentence)
96 target->WriteOpCode(jtl::END_OF_SENTENCE);
97 return JtlCompiler::CompileError::NO_ERROR;
98 }
99
100 private:
101 // The possible types of an operation's argument.
102 enum ArgumentType {
103 None,
104 Bool,
105 Hash
106 };
107
108 // Encapsulates meta-data about one instruction.
109 struct Instruction {
110 Instruction() : op_code(jtl::END_OF_SENTENCE) {}
111 Instruction(const char* name,
112 jtl_foundation::OpCodes op_code,
113 const std::vector<ArgumentType>& argument_types)
114 : name(name), op_code(op_code), argument_types(argument_types) {}
115
116 std::string name;
117 jtl::OpCodes op_code;
118 std::vector<ArgumentType> argument_types;
119 };
120
121 static std::vector<ArgumentType> Arguments(ArgumentType arg1_type = None,
122 ArgumentType arg2_type = None,
123 ArgumentType arg3_type = None) {
124 std::vector<ArgumentType> result;
125 if (arg1_type != None)
126 result.push_back(arg1_type);
127 if (arg2_type != None)
128 result.push_back(arg2_type);
129 if (arg3_type != None)
130 result.push_back(arg3_type);
131 return result;
132 }
133
134 void Add(const Instruction& instruction) {
135 instruction_map_[instruction.name] = instruction;
136 }
137
138 std::map<std::string, Instruction> instruction_map_;
139
140 DISALLOW_COPY_AND_ASSIGN(InstructionSet);
141 };
142
143 } // namespace
144
145 bool JtlCompiler::Compile(const std::string& source_code,
146 const std::string& hash_seed,
147 std::string* output_bytecode,
148 CompileError* error_details) {
149 DCHECK(output_bytecode);
150 InstructionSet instruction_set;
151 ByteCodeWriter bytecode_writer(output_bytecode);
152 jtl::Hasher hasher(hash_seed);
153
154 std::string compacted_source_code;
155 std::vector<size_t> newline_indices;
156 size_t mismatched_quotes_line;
157 if (!JtlParser::RemoveCommentsAndAllWhitespace(source_code,
158 &compacted_source_code,
159 &newline_indices,
160 &mismatched_quotes_line)) {
161 if (error_details) {
162 error_details->context = ""; // No meaningful intra-line context here.
163 error_details->line_number = mismatched_quotes_line;
164 error_details->error_code = CompileError::MISMATCHED_DOUBLE_QUOTES;
165 }
166 return false;
167 }
168
169 JtlParser parser(compacted_source_code, newline_indices);
170 while (!parser.HasFinished()) {
171 std::string operation_name;
172 ListValue arguments;
173 bool ends_sentence = false;
174 if (!parser.ParseNextOperation(
175 &operation_name, &arguments, &ends_sentence)) {
176 if (error_details) {
177 error_details->context = parser.last_context();
178 error_details->line_number = parser.last_line_number();
179 error_details->error_code = CompileError::PARSING_ERROR;
180 }
181 return false;
182 }
183 CompileError::ErrorCode error_code = instruction_set.TranscodeInstruction(
184 operation_name, arguments, ends_sentence, hasher, &bytecode_writer);
185 if (error_code != CompileError::NO_ERROR) {
186 if (error_details) {
187 error_details->context = parser.last_context();
188 error_details->line_number = parser.last_line_number();
189 error_details->error_code = error_code;
190 }
191 return false;
192 }
193 }
194
195 return true;
196 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698