about summary refs log tree commit diff stats
path: root/cpp
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-02-17 12:26:17 -0800
committerKartik K. Agaram <vc@akkartik.com>2015-02-17 12:26:17 -0800
commit4a753480074e3a3dda4d4414fe9a60e9704b799d (patch)
treefcad3a42bcde17b843908b20c4e469da27a2c2fb /cpp
parentf1e1cac414c34449113ca7196ceb82cbcbb2517f (diff)
downloadmu-4a753480074e3a3dda4d4414fe9a60e9704b799d.tar.gz
769 - first recipe/instruction parsed
Diffstat (limited to 'cpp')
-rw-r--r--cpp/002main.cc70
-rw-r--r--cpp/002main.test.cc18
2 files changed, 82 insertions, 6 deletions
diff --git a/cpp/002main.cc b/cpp/002main.cc
index 1476150c..a2bc0729 100644
--- a/cpp/002main.cc
+++ b/cpp/002main.cc
@@ -113,6 +113,11 @@ struct reagent {
   string name;
   vector<type_number> types;
   vector<pair<string, property> > properties;
+  reagent(string s) {
+    istringstream in(s);
+    name = slurp_until(in, ':');
+    types.push_back(Type_number[slurp_until(in, '/')]);
+  }
 };
 
 const int idle = 0;
@@ -124,6 +129,7 @@ struct instruction {
   vector<reagent> ingredients;  // only if !is_label
   vector<reagent> products;  // only if !is_label
   instruction() :is_label(false), operation(idle) {}
+  void clear() { is_label=false; label.clear(); operation=idle; ingredients.clear(); products.clear(); }
 };
 
 struct recipe {
@@ -173,14 +179,51 @@ void compile(string form) {
   skip_newlines(in);
 
   instruction curr;
-//?   while (next_instruction(in, &curr)) { //? 1
-//?     Recipe[r].step.push_back(curr); //? 1
-//?   } //? 1
+  while (next_instruction(in, &curr)) {
+    Recipe[r].step.push_back(curr);
+  }
 }
 
 bool next_instruction(istream& in, instruction* curr) {
-  skip_whitespace(in);
-  skip_newlines(in);
+  curr->clear();
+  if (in.eof()) return false;
+  skip_whitespace(in);  if (in.eof()) return false;
+  skip_newlines(in);  if (in.eof()) return false;
+
+//?   vector<string> ingredients, products; //? 1
+  vector<string> words;
+  while (in.peek() != '\n') {
+    skip_whitespace(in);  if (in.eof()) return false;
+    string word = next_word(in);  if (in.eof()) return false;
+    words.push_back(word);
+    skip_whitespace(in);  if (in.eof()) return false;
+  }
+  skip_newlines(in);  if (in.eof()) return false;
+//?   cout << "words: "; //? 1
+//?   for (vector<string>::iterator p = words.begin(); p != words.end(); ++p) { //? 1
+//?     cout << *p << "; "; //? 1
+//?   } //? 1
+//?   cout << '\n'; //? 1
+//?   return true; //? 1
+
+  vector<string>::iterator p = words.begin();
+  if (find(words.begin(), words.end(), "<-") != words.end()) {
+//?     cout << "instruction yields products\n"; //? 1
+    for (; *p != "<-"; ++p) {
+//?       cout << "product: " << *p << '\n'; //? 1
+//?       products.push_back(*p); //? 1
+      curr->products.push_back(reagent(*p));
+    }
+    ++p;  // skip <-
+  }
+//?   return true; //? 1
+
+  curr->operation = Recipe_number[*p];  ++p;
+
+  for (; p != words.end(); ++p) {
+//?     cout << "ingredient: " << *p << '\n'; //? 1
+    curr->ingredients.push_back(reagent(*p));
+  }
   return !in.eof();
 }
 
@@ -197,6 +240,11 @@ string next_word(istream& in) {
 
 void slurp_word(istream& in, ostream& out) {
   char c;
+  if (in.peek() == ',') {
+    in >> c;
+    out << c;
+    return;
+  }
   while (in >> c) {
 //?     cout << c << '\n'; //? 1
     if (isspace(c) || c == ',') {
@@ -226,6 +274,18 @@ void skip_comma(istream& in) {
   skip_whitespace(in);
 }
 
+string slurp_until(istream& in, char delim) {
+  ostringstream out;
+  char c;
+  while (in >> c) {
+    if (c == delim) {
+      break;
+    }
+    out << c;
+  }
+  return out.str();
+}
+
 
 
 //// test harness
diff --git a/cpp/002main.test.cc b/cpp/002main.test.cc
index 8608d724..77d0ee38 100644
--- a/cpp/002main.test.cc
+++ b/cpp/002main.test.cc
@@ -1,8 +1,24 @@
-void test_compile() {
+void test_parse() {
   compile("recipe main [\n"
           "  1:integer <- copy 23:literal\n"
+//?           "  1:integer, 2:integer <- copy 23:literal\n"
           "]\n");
   CHECK(Recipe_number.find("main") != Recipe_number.end());
+  recipe r = Recipe[Recipe_number["main"]];
+  vector<instruction>::iterator i = r.step.begin();
+  CHECK_EQ(i->is_label, false);
+  CHECK_EQ(i->label, "");
+  CHECK_EQ(i->operation, Recipe_number["copy"]);
+  CHECK_EQ(i->ingredients.size(), 1);
+  CHECK_EQ(i->ingredients[0].name, string("23"));
+  CHECK_EQ(i->ingredients[0].types.size(), 1);
+  CHECK_EQ(i->ingredients[0].types[0], Type_number["literal"]);
+  CHECK_EQ(i->ingredients[0].properties.size(), 0);
+  CHECK_EQ(i->products.size(), 1);
+  CHECK_EQ(i->products[0].name, string("1"));
+  CHECK_EQ(i->products[0].types.size(), 1);
+  CHECK_EQ(i->products[0].types[0], Type_number["integer"]);
+  CHECK_EQ(i->products[0].properties.size(), 0);
 }
 
 void test_literal() {