import std.stdio;
import std.conv : to;
import std.array;
import ctpg;
class TreeBase {
public:
this() { }
TreeBase clone() {
return null;
}
string toString() const {
return "";
}
}
class TreeInteger : TreeBase {
public:
long m_value;
this() { }
this(long value) {
m_value = value;
}
TreeInteger clone() {
return new TreeInteger(m_value);
}
string toString() const {
return to!string(m_value);
}
}
class TreeReal : TreeBase {
public:
real m_value;
this() { }
this(double value) {
m_value = value;
}
TreeReal clone() {
return new TreeReal(m_value);
}
string toString() const {
return to!string(m_value);
}
}
class TreeString : TreeBase {
public:
string m_value;
this() { }
this(string value) {
m_value = value;
}
TreeString clone() {
return new TreeString(m_value);
}
string toString() const {
return m_value;
}
}
class TreeBranch : TreeBase {
public:
string m_head;
TreeBase[] m_subtree;
this() { }
this(string head, TreeBase[] subtree ...) {
m_head = head;
m_subtree = subtree;
}
ref TreeBase opIndex(size_t i) {
return m_subtree[i];
}
TreeBranch opSlice(size_t i, size_t j) {
size_t n = j - i;
TreeBase[] subtree = new TreeBase[n];
for(size_t k = i; k < j; k++) {
subtree[k - i] = m_subtree[k].clone();
}
return new TreeBranch(m_head, subtree);
}
ref long integerAt(size_t i) {
assert(cast(TreeInteger)m_subtree[i] !is null);
return (cast(TreeInteger)m_subtree[i]).m_value;
}
ref real realAt(size_t i) {
assert(cast(TreeReal)m_subtree[i] !is null);
return (cast(TreeReal)m_subtree[i]).m_value;
}
ref string stringAt(size_t i) {
assert(cast(TreeString)m_subtree[i] !is null);
return (cast(TreeString)m_subtree[i]).m_value;
}
TreeBranch branchAt(size_t i) {
assert(cast(TreeBranch)m_subtree[i] !is null);
return (cast(TreeBranch)m_subtree[i]);
}
TreeBranch clone() {
TreeBranch tree = new TreeBranch(m_head);
tree.m_subtree = new TreeBase[m_subtree.length];
for(size_t i = 0; i < m_subtree.length; i++) {
tree.m_subtree[i] = m_subtree[i].clone();
}
return tree;
}
string toString() const {
string s;
s ~= "[";
s ~= m_head;
for(size_t i = 0; i < m_subtree.length; i++) {
s ~= ", ";
s ~= m_subtree[i].toString();
}
s ~= "]";
return s;
}
}
mixin(generateParsers(q{
TreeBase IDENT =
[A-Za-z][A-Za-z0-9]* >>(value, values)
{ return cast(TreeBase)new TreeString(value ~ values.join()); }
;
@default_skip(defaultSkip)
TreeBase exp = formula $;
TreeBase formula = IDENT
/ !"(" formula !")" >>(data)
{ return data; }
/ !"/lnot" formula >>(data)
{ return cast(TreeBase)new TreeBranch("/lnot", data); }
/ formula !"/land" formula >>(lhs, rhs)
{ return cast(TreeBase)new TreeBranch("/land", lhs, rhs); }
/ formula !"/lor" formula >>(lhs, rhs)
{ return cast(TreeBase)new TreeBranch("/lor", lhs, rhs); }
/ formula !"/rightarrow" formula >>(lhs, rhs)
{ return cast(TreeBase)new TreeBranch("/rightarrow", lhs, rhs); }
/ formula !"/leftrightarrow" formula >>(lhs, rhs)
{ return cast(TreeBase)new TreeBranch("/leftrightarrow", lhs, rhs); }
;
}));
void main() {
string buf;
stdin.readln(buf);
auto parsed = parse!exp(buf);
writeln(parsed.match);
writeln(parsed.value);
}