about summary refs log tree commit diff stats
path: root/html/017parse_tree.cc.html
blob: 0ff64fb15499b1c23eb45b0d90143e27d7a70ebc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Mu - 017parse_tree.cc</title>
<meta name="Generator" content="Vim/7.4">
<meta name="plugin-version" content="vim7.4_v2">
<meta name="syntax" content="cpp">
<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
<meta name="colorscheme" content="minimal">
<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; }
* { font-size: 12pt; font-size: 1em; }
.Constant { color: #00a0a0; }
.muRecipe { color: #ff8700; }
.Comment { color: #9090ff; }
.Delimiter { color: #800080; }
.Special { color: #c00000; }
.traceContains { color: #008000; }
.Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; }
.muData { color: #ffff00; }
.Identifier { color: #fcb165; }
-->
</style>

<script type='text/javascript'>
<!--

-->
</script>
</head>
<body>
<pre id='vimCodeElement'>
<span class="Comment">// So far instructions can only contain linear lists of properties. Now we add</span>
<span class="Comment">// support for more complex trees of properties in dilated reagents. This will</span>
<span class="Comment">// come in handy later for expressing complex types, like &quot;a dictionary from</span>
<span class="Comment">// (address to array of charaters) to (list of numbers)&quot;.</span>
<span class="Comment">//</span>
<span class="Comment">// Type trees aren't as general as s-expressions even if they look like them:</span>
<span class="Comment">// the first element of a type tree is always an atom, and left and right</span>
<span class="Comment">// pointers of non-atoms are never NULL. All type trees are 'dotted' in lisp</span>
<span class="Comment">// parlance.</span>
<span class="Comment">//</span>
<span class="Comment">// For now you can't use the simpler 'colon-based' representation inside type</span>
<span class="Comment">// trees. Once you start typing parens, keep on typing parens.</span>

<span class="Delimiter">:(scenarios load)</span>
<span class="Delimiter">:(scenario dilated_reagent_with_nested_brackets)</span>
<span class="muRecipe">def</span> main [
  <span class="Delimiter">{</span><span class="Constant">1</span>: number<span class="Delimiter">,</span> foo: <span class="Delimiter">(</span>bar <span class="Delimiter">(</span>baz quux<span class="Delimiter">))}</span><span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
]
<span class="traceContains">+parse:   product: {1: &quot;number&quot;, &quot;foo&quot;: (&quot;bar&quot; (&quot;baz&quot; &quot;quux&quot;))}</span>

<span class="Delimiter">:(before &quot;End Parsing Dilated Reagent Property(value)&quot;)</span>
value = parse_string_tree<span class="Delimiter">(</span>value<span class="Delimiter">);</span>
<span class="Delimiter">:(before &quot;End Parsing Dilated Reagent Type Property(type_names)&quot;)</span>
type_names = parse_string_tree<span class="Delimiter">(</span>type_names<span class="Delimiter">);</span>

<span class="Delimiter">:(code)</span>
string_tree* parse_string_tree<span class="Delimiter">(</span>string_tree* s<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  assert<span class="Delimiter">(</span>s<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!starts_with<span class="Delimiter">(</span>s<span class="Delimiter">-&gt;</span>value<span class="Delimiter">,</span> <span class="Constant">&quot;(&quot;</span><span class="Delimiter">))</span> <span class="Identifier">return</span> s<span class="Delimiter">;</span>
  string_tree* result = parse_string_tree<span class="Delimiter">(</span>s<span class="Delimiter">-&gt;</span>value<span class="Delimiter">);</span>
  <span class="Normal">delete</span> s<span class="Delimiter">;</span>
  <span class="Identifier">return</span> result<span class="Delimiter">;</span>
<span class="Delimiter">}</span>

string_tree* parse_string_tree<span class="Delimiter">(</span><span class="Normal">const</span> string&amp; s<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  istringstream in<span class="Delimiter">(</span>s<span class="Delimiter">);</span>
  in &gt;&gt; std::noskipws<span class="Delimiter">;</span>
  <span class="Identifier">return</span> parse_string_tree<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
<span class="Delimiter">}</span>

string_tree* parse_string_tree<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  skip_whitespace_but_not_newline<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">NULL</span><span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">')'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
    in<span class="Delimiter">.</span>get<span class="Delimiter">();</span>
    <span class="Identifier">return</span> <span class="Constant">NULL</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="Constant">'('</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
    string_tree* result = <span class="Normal">new</span> string_tree<span class="Delimiter">(</span>next_word<span class="Delimiter">(</span>in<span class="Delimiter">));</span>
    <span class="Identifier">return</span> result<span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  in<span class="Delimiter">.</span>get<span class="Delimiter">();</span>  <span class="Comment">// skip '('</span>
  string_tree* result = <span class="Constant">NULL</span><span class="Delimiter">;</span>
  string_tree** curr = &amp;result<span class="Delimiter">;</span>
  <span class="Normal">while</span> <span class="Delimiter">(</span><span class="Constant">true</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
    skip_whitespace_but_not_newline<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
    assert<span class="Delimiter">(</span>has_data<span class="Delimiter">(</span>in<span class="Delimiter">));</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">')'</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span>
    *curr = <span class="Normal">new</span> string_tree<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">);</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">'('</span><span class="Delimiter">)</span>
      <span class="Delimiter">(</span>*curr<span class="Delimiter">)-&gt;</span>left = parse_string_tree<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
    <span class="Normal">else</span>
      <span class="Delimiter">(</span>*curr<span class="Delimiter">)-&gt;</span>left = <span class="Normal">new</span> string_tree<span class="Delimiter">(</span>next_word<span class="Delimiter">(</span>in<span class="Delimiter">));</span>
    curr = &amp;<span class="Delimiter">(</span>*curr<span class="Delimiter">)-&gt;</span>right<span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  in<span class="Delimiter">.</span>get<span class="Delimiter">();</span>  <span class="Comment">// skip ')'</span>
  assert<span class="Delimiter">(</span>*curr == <span class="Constant">NULL</span><span class="Delimiter">);</span>
  <span class="Comment">// standardize the final element to always be on the right if it's an atom</span>
  <span class="Comment">// (a b c) =&gt; (a b . c) in s-expression parlance</span>
  string_tree* tmp = result<span class="Delimiter">;</span>
  <span class="Normal">while</span> <span class="Delimiter">(</span>tmp<span class="Delimiter">-&gt;</span>right &amp;&amp; tmp<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> tmp = tmp<span class="Delimiter">-&gt;</span>right<span class="Delimiter">;</span>
  assert<span class="Delimiter">(</span>!tmp<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!tmp<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>left<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">)</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span>
  string_tree* tmp2 = tmp<span class="Delimiter">-&gt;</span>right<span class="Delimiter">;</span>
  tmp<span class="Delimiter">-&gt;</span>right = tmp2<span class="Delimiter">-&gt;</span>left<span class="Delimiter">;</span>
  tmp2<span class="Delimiter">-&gt;</span>left = <span class="Constant">NULL</span><span class="Delimiter">;</span>
  assert<span class="Delimiter">(</span>tmp2<span class="Delimiter">-&gt;</span>right == <span class="Constant">NULL</span><span class="Delimiter">);</span>
  <span class="Normal">delete</span> tmp2<span class="Delimiter">;</span>
  <span class="Identifier">return</span> result<span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(scenario dilated_reagent_with_type_tree)</span>
<span class="Special">% Hide_errors = true;  // 'map' isn't defined yet</span>
<span class="muRecipe">def</span> main [
  <span class="Delimiter">{</span><span class="Constant">1</span>: <span class="Delimiter">(</span>foo <span class="Delimiter">(</span>address array character<span class="Delimiter">)</span> <span class="Delimiter">(</span>bar number<span class="Delimiter">))}</span><span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
]
<span class="Comment"># just to avoid errors</span>
<span class="muData">container</span> foo [
]
<span class="muData">container</span> bar [
]
<span class="traceContains">+parse:   product: {1: (&quot;foo&quot; (&quot;address&quot; &quot;array&quot; &quot;character&quot;) (&quot;bar&quot; &quot;number&quot;))}</span>
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->