Fleet  0.0.9
Inference in the LOT
SExpression.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include<utility>
4 #include<string>
5 #include<optional>
6 
7 #include "BaseNode.h"
8 
9 // Code for parsing and dealing with S-expressions
10 namespace SExpression {
11 
20  struct SExpNode : public BaseNode<SExpNode> {
21  std::optional<std::string> label;
22 
23  SExpNode() : label() { }
24  SExpNode(const std::string& s) : label(s) {}
25  SExpNode(const SExpNode& s) : BaseNode<SExpNode>(s), label(s.label) {}
26 
28  label = n.label;
29  children = n.children;
30  return *this;
31  }
32  SExpNode& operator=(const SExpNode&& n) {
33  label = std::move(n.label);
34  children = std::move(n.children);
35  return *this;
36  }
37 
38  virtual bool operator==(const SExpNode& n) const override {
39  return label == n.label and children == n.children;
40  }
41 
42  std::string get_label() {
43  if(label.has_value()) {
44  return label.value();
45  }
46  else {
47  return "<NA>";
48  }
49  }
50 
51  virtual std::string string() const {
52  if(label) {
53  assert(nchildren() == 0);
54  return label.value();
55  }
56  else {
57 
58  std::string out = "["; // we use square braces so we can see how it's different than paren inputs
59 
60  for(const auto& c : this->children) {
61  out += c.string() + " ";
62  }
63 
64  if(nchildren() > 0)
65  out.erase(out.length()-1);
66 
67  out += "]";
68  return out;
69  }
70  }
71  };
72 
73 
74  void assert_check_parens(const std::string& s) {
75  int nopen = 0;
76  for(char c : s) {
77  if (c == '(') nopen++;
78  else if(c == ')') nopen--;
79  assert(nopen >= 0);
80  }
81  if(nopen != 0) {
82  CERR "*** Bad parentheses in " << s ENDL;
83  assert(false);
84  }
85  }
86 
87  std::string trim(std::string x) {
88  // remove leading spaces
89  while(x[0] == ' ') {
90  x.erase(0, 1);
91  }
92 
93  // remove trailing spaces
94  while(x[x.size()-1] == ' ') {
95  x.erase(x.size()-1, 1);
96  }
97  return x;
98  }
99 
100 
101  std::vector<std::string> tokenize(std::string s) {
103  std::vector<std::string> out; // list of tokens
104 
105  std::string x; // build up the token
106  for(char c : s) {
107  if(c == '(' or c == ')' or c == ' ') {
108 
109  x = trim(x);
110 
111  if(x != "" and x != " ") {
112  out.push_back(x);
113  }
114  x = "";
115 
116  // and accumulate the paren if its parens
117  if(c != ' ') {
118  out.push_back(std::string(1,c));
119  }
120  }
121  else { // just accumulate here
122  x += c;
123  }
124  }
125 
126  if(x != "") {
127  out.push_back(trim(x));
128  }
129 
130  //PRINTN(str(out));
131  return out;
132  }
133 
134  std::string pop_front(std::vector<std::string>& q) {
135  // not great for vector, but this is just data pre-processing -- could switch to std::list
136  auto x = q.at(0);
137  q.erase(q.begin());
138  return x;
139  }
140 
141 
150  SExpNode __parse(std::vector<std::string>& tok) {
151 
152  assert(tok.size() > 0);
153 
154  SExpNode out;
155  while(not tok.empty()) {
156  auto x = pop_front(tok);
157  //print("x=",x);
158  if(x == "(") out.push_back(__parse(tok));
159  else if(x == ")") break; // when we get this, we must be a close (since lower-down stuff has been handled in the recursion)
160  else out.push_back(SExpNode(x)); // just a string
161  }
162 
163  return out;
164  }
165 
166 
172  SExpNode parse(std::vector<std::string>& tok) {
173 
174  if(tok.size() == 1) {
175  return SExpNode(pop_front(tok));
176  }
177 
178  if(tok.front() == "(") {
179  pop_front(tok);
180  }
181 
182  return __parse(tok);
183  }
184 
185  SExpNode parse(std::string s) {
186  auto tok = tokenize(s);
187  return parse(tok);
188  }
189 
190 
191 
192 }
void assert_check_parens(const std::string &s)
Definition: SExpression.h:74
SExpNode()
Definition: SExpression.h:23
std::vector< SExpNode > children
Definition: BaseNode.h:23
This is a general tree class, which we are adding because there are currently at least 3 different tr...
virtual std::string string() const
Definition: SExpression.h:51
Definition: SExpression.h:20
SExpNode __parse(std::vector< std::string > &tok)
Recursive parsing of S-expressions. Not high qualtiy. Basically, if we get ((A...) B...
Definition: SExpression.h:150
Definition: BaseNode.h:20
SExpNode(const std::string &s)
Definition: SExpression.h:24
std::string get_label()
Definition: SExpression.h:42
#define CERR
Definition: IO.h:23
SExpNode parse(std::vector< std::string > &tok)
Wrapper to parse to remove outer (...)
Definition: SExpression.h:172
std::vector< std::string > tokenize(std::string s)
Definition: SExpression.h:101
std::optional< std::string > label
Definition: SExpression.h:21
SExpNode(const SExpNode &s)
Definition: SExpression.h:25
#define ENDL
Definition: IO.h:21
virtual bool operator==(const SExpNode &n) const override
Definition: SExpression.h:38
Definition: SExpression.h:10
SExpNode & operator=(const SExpNode &n)
Definition: SExpression.h:27
std::string trim(std::string x)
Definition: SExpression.h:87
SExpNode & operator=(const SExpNode &&n)
Definition: SExpression.h:32
std::string pop_front(std::vector< std::string > &q)
Definition: SExpression.h:134
size_t nchildren() const
Definition: BaseNode.h:208