git.haldean.org tau / dbeaa5d
interactive help text haldean 4 years ago
5 changed file(s) with 186 addition(s) and 100 deletion(s). Raw diff Collapse all Expand all
55 xmlns:local="clr-namespace:Tau"
66 mc:Ignorable="d"
77 FocusManager.FocusedElement="{Binding ElementName=Input}"
8 Title="tau" Height="257.492" Width="160.859" WindowStyle="ToolWindow">
8 Title="tau" Height="249.621" Width="159.735" WindowStyle="ToolWindow">
99 <Grid>
10 <TextBlock TextWrapping="Wrap" Text="0" Margin="10,10,10,30" FontFamily="PragmataPro" Name="Result" FontSize="20"/>
11 <TextBox Margin="10,0,10,9" TextWrapping="Wrap" VerticalAlignment="Bottom" FontFamily="PragmataPro" Name="Input" FontSize="20" KeyUp="InputKey"/>
10 <Grid.RowDefinitions>
11 <RowDefinition Height="*"/>
12 <RowDefinition Height="Auto"/>
13 <RowDefinition Height="40"/>
14 </Grid.RowDefinitions>
15 <TextBlock Name="Result" TextWrapping="Wrap" Text="0" Margin="10,10,10,72" FontFamily="PragmataPro" FontSize="20"/>
16 <TextBlock Name="Help" FontFamily="PragmataPro" FontSize="9" VerticalAlignment="Bottom" Grid.Row="1" Margin="10,0" TextWrapping="Wrap"/>
17 <TextBox Name="Input" Margin="10,0,10,10" TextWrapping="Wrap" VerticalAlignment="Bottom" FontFamily="PragmataPro" FontSize="20" KeyUp="InputKey" Grid.Row="2"/>
1218 </Grid>
1319 </Window>
2020 public partial class MainWindow : Window
2121 {
2222 StackMachine sm;
23 OpParser parser;
2324 TextBlock result;
25 TextBlock help;
2426
2527 public MainWindow()
2628 {
2729 InitializeComponent();
28 sm = StackMachine.New();
29 result = (TextBlock) FindName("Result");
30 sm = new StackMachine();
31 parser = OpParser.New();
32 result = (TextBlock)FindName("Result");
33 help = (TextBlock)FindName("Help");
3034 }
3135
3236 private void InputKey(object sender, KeyEventArgs e)
3337 {
34 switch (e.Key)
38 TextBox t = (TextBox)sender;
39 var parsed = parser.Parse(t.Text);
40 help.Text = "";
41
42 if (e.Key == Key.Enter)
3543 {
36 case Key.Enter:
37 TextBox t = (TextBox)sender;
38 sm.Run(t.Text);
39 result.Text = sm.State();
40 t.Text = "";
41 break;
42 default:
43 break;
44 sm.Run(parsed);
45 result.Text = sm.State();
46 t.Text = "";
47 return;
48 }
49 if (parsed.Count() > 0)
50 {
51 help.Text = parsed.Last().Doc;
4452 }
4553 }
4654 }
0 ´╗┐using System;
1 using System.Collections.Generic;
2 using System.Linq;
3 using System.Text;
4 using System.Threading.Tasks;
5
6 namespace Tau
7 {
8 public class Op
9 {
10 public delegate void Visitor(Stack<Double> s);
11 public string Name;
12 public Visitor Func;
13 public string Doc;
14
15 public Op(string n, string d, Visitor f)
16 {
17 Name = n;
18 Func = f;
19 Doc = d;
20 }
21 }
22
23 class OpParser
24 {
25 private Dictionary<string, Op> ops;
26
27 protected OpParser()
28 {
29 ops = new Dictionary<string, Op>();
30 }
31
32 public static OpParser New()
33 {
34 OpParser parser = new OpParser();
35 parser.AddOp(new Op("+", "adds the top two values", BinOp((v1, v2) => { return v2 + v1; })));
36 parser.AddOp(new Op("*", "multiplies the top two values", BinOp((v1, v2) => { return v2 * v1; })));
37 parser.AddOp(new Op("-", "subtracts the top value from the value below it", BinOp((v1, v2) => { return v2 - v1; })));
38 parser.AddOp(new Op("/", "divides the top value into the value below it", BinOp((v1, v2) => { return v2 / v1; })));
39 parser.AddOp(new Op("dup", "duplicates the top value on the stack", (Stack<Double> values) => {
40 if (values.Count == 0)
41 return;
42 double v = values.Pop();
43 values.Push(v);
44 values.Push(v);
45 }));
46 parser.AddOp(new Op("swap", "swaps the top two values on the stack", (Stack<Double> values) => {
47 if (values.Count < 2)
48 return;
49 double v1 = values.Pop();
50 double v2 = values.Pop();
51 values.Push(v1);
52 values.Push(v2);
53 }));
54 return parser;
55 }
56
57 void AddOp(Op o)
58 {
59 ops.Add(o.Name, o);
60 }
61
62 private delegate double Binary(double v1, double v2);
63 private static Op.Visitor BinOp(Binary func)
64 {
65 return (Stack<Double> values) =>
66 {
67 if (values.Count == 0)
68 return;
69 double v1 = values.Pop();
70 double v2 = values.Count == 0 ? v1 : values.Pop();
71 values.Push(func(v1, v2));
72 };
73 }
74
75 private static Op PushOp(double v)
76 {
77 return new Op("constant", "", (Stack<Double> values) => { values.Push(v); });
78 }
79
80 public IEnumerable<Op> Parse(string input)
81 {
82 List<Op> res = new List<Op>();
83 StringBuilder sb = new StringBuilder();
84 bool inNumber = false;
85 bool waitSub = false;
86
87 for (int i = 0; i < input.Length; i++)
88 {
89 // Whitespace exists only to be a boundary between other things
90 if (input[i] == ' ')
91 {
92 if (waitSub)
93 {
94 // If we get here, the hyphen wasn't negation. Push the hypen and restart.
95 waitSub = false;
96 res.Add(ops["-"]);
97 // We drop the whitespace implicitly by not adding anything to this.
98 sb = new StringBuilder();
99 }
100 if (inNumber)
101 {
102 res.Add(PushOp(Double.Parse(sb.ToString())));
103 sb = new StringBuilder();
104 inNumber = false;
105 }
106 continue;
107 }
108 sb.Append(input[i]);
109
110 bool isNumber = Double.TryParse(sb.ToString(), out _);
111 if (inNumber && !isNumber)
112 {
113 sb.Remove(sb.Length - 1, 1);
114 res.Add(PushOp(Double.Parse(sb.ToString())));
115 sb = new StringBuilder(input.Substring(i, 1));
116 inNumber = false;
117 }
118 else if (isNumber)
119 {
120 inNumber = true;
121 }
122 else if (sb.Length == 1 && input[i] == '-')
123 {
124 // Special-case the hyphen because it could either be a negation or a subtraction;
125 // if it's not immediately followed by a number, we call it subtraction.
126 waitSub = true;
127 }
128 else if (waitSub)
129 {
130 // If we get here, the hyphen wasn't negation. Push the hypen and restart.
131 waitSub = false;
132 res.Add(ops["-"]);
133 sb = new StringBuilder(input.Substring(i, 1));
134 }
135 else if (ops.ContainsKey(sb.ToString()))
136 {
137 res.Add(ops[sb.ToString()]);
138 sb = new StringBuilder();
139 }
140 }
141
142 if (inNumber)
143 res.Add(PushOp(Double.Parse(sb.ToString())));
144 else if (ops.ContainsKey(sb.ToString()))
145 {
146 res.Add(ops[sb.ToString()]);
147 sb = new StringBuilder();
148 }
149 return res;
150 }
151 }
152 }
55
66 namespace Tau
77 {
8 class Op
9 {
10 public delegate void Visitor(Stack<Double> s);
11 public string Name;
12 public Visitor Func;
13 public string Doc;
14
15 public Op(string n, string d, Visitor f)
16 {
17 Name = n;
18 Func = f;
19 Doc = d;
20 }
21 }
22
238 public class StackMachine
249 {
2510 private Stack<Double> values;
26 private Dictionary<string, Op> ops;
2711
28 protected StackMachine()
12 public StackMachine()
2913 {
3014 values = new Stack<double>();
31 ops = new Dictionary<string, Op>();
32 }
33
34 void AddOp(Op o)
35 {
36 ops.Add(o.Name, o);
3715 }
3816
39 private delegate double Binary(double v1, double v2);
40 private static Op.Visitor BinOp(Binary func)
17 public void Run(IEnumerable<Op> stream)
4118 {
42 return (Stack<Double> values) =>
19 foreach (Op o in stream)
4320 {
44 if (values.Count == 0)
45 return;
46 double v1 = values.Pop();
47 double v2 = values.Count == 0 ? v1 : values.Pop();
48 values.Push(func(v1, v2));
49 };
50 }
51
52 public static StackMachine New()
53 {
54 StackMachine sm = new StackMachine();
55 sm.AddOp(new Op("+", "adds the top two values", BinOp((v1, v2) => { return v2 + v1; })));
56 sm.AddOp(new Op("*", "multiplies the top two values", BinOp((v1, v2) => { return v2 * v1; })));
57 sm.AddOp(new Op("-", "subtracts the top value from the value below it", BinOp((v1, v2) => { return v2 - v1; })));
58 sm.AddOp(new Op("/", "divides the top value into the value below it", BinOp((v1, v2) => { return v2 - v1; })));
59 sm.AddOp(new Op("dup", "duplicates the top value on the stack", (Stack<Double> values) => {
60 if (values.Count == 0)
61 return;
62 double v = values.Pop();
63 values.Push(v);
64 values.Push(v);
65 }));
66 sm.AddOp(new Op("swap", "swaps the top two values on the stack", (Stack<Double> values) => {
67 if (values.Count < 2)
68 return;
69 double v1 = values.Pop();
70 double v2 = values.Pop();
71 values.Push(v1);
72 values.Push(v2);
73 }));
74 return sm;
75 }
76
77 public void Run(string data)
78 {
79 string[] bits = data.Split();
80 foreach (string b in bits)
81 {
82 double res;
83 if (Double.TryParse(b, out res))
84 {
85 Push(res);
86 continue;
87 }
88 Push(b);
21 o.Func(values);
8922 }
90 }
91
92
93 public void Push(string opname)
94 {
95 Op op;
96 if (ops.TryGetValue(opname, out op))
97 {
98 op.Func(values);
99 }
100 }
101
102 public void Push(Double v)
103 {
104 values.Push(v);
10523 }
10624
10725 public string State()
5353 <Generator>MSBuild:Compile</Generator>
5454 <SubType>Designer</SubType>
5555 </ApplicationDefinition>
56 <Compile Include="OpParser.cs" />
5657 <Compile Include="StackMachine.cs" />
5758 <Page Include="MainWindow.xaml">
5859 <Generator>MSBuild:Compile</Generator>