1 <?php
2 
3 /**
4  * Hoa
5  *
6  *
7  * @license
8  *
9  * New BSD License
10  *
11  * Copyright © 2007-2017, Hoa community. All rights reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions are met:
15  *     * Redistributions of source code must retain the above copyright
16  *       notice, this list of conditions and the following disclaimer.
17  *     * Redistributions in binary form must reproduce the above copyright
18  *       notice, this list of conditions and the following disclaimer in the
19  *       documentation and/or other materials provided with the distribution.
20  *     * Neither the name of the Hoa nor the names of its contributors may be
21  *       used to endorse or promote products derived from this software without
22  *       specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
28  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 namespace Hoa\Math\Bin;
38 
39 use Hoa\Compiler;
40 use Hoa\Console;
41 use Hoa\File;
42 use Hoa\Math;
43 
44 /**
45  * Class \Hoa\Math\Bin\Calc.
46  *
47  * A simple calculator.
48  *
49  * @copyright  Copyright © 2007-2017 Hoa community
50  * @license    New BSD License
51  */
52 class Calc extends Console\Dispatcher\Kit
53 {
54     /**
55      * Options description.
56      *
57      * @var array
58      */
59     protected $options = [
60         ['help', Console\GetOption::NO_ARGUMENT, 'h'],
61         ['help', Console\GetOption::NO_ARGUMENT, '?']
62     ];
63 
64 
65 
66     /**
67      * The entry method.
68      *
69      * @return  int
70      */
71     public function main()
72     {
73         while (false !== $c = $this->getOption($v)) {
74             switch ($c) {
75                 case 'h':
76                 case '?':
77                     return $this->usage();
78 
79                 case '__ambiguous':
80                     $this->resolveOptionAmbiguity($v);
81 
82                     break;
83             }
84         }
85 
86         $this->parser->listInputs($expression);
87 
88         $compiler = Compiler\Llk::load(
89             new File\Read('hoa://Library/Math/Arithmetic.pp')
90         );
91         $visitor  = new Math\Visitor\Arithmetic();
92         $dump     = new Compiler\Visitor\Dump();
93 
94         if (null !== $expression) {
95             $ast = $compiler->parse($expression);
96             echo $expression . ' = ' . $visitor->visit($ast), "\n";
97 
98             return;
99         }
100 
101         $readline   = new Console\Readline();
102         $readline->setAutocompleter(
103             new Console\Readline\Autocompleter\Word(
104                 array_merge(
105                     array_keys($visitor->getConstants()->getArrayCopy()),
106                     array_keys($visitor->getFunctions()->getArrayCopy())
107                 )
108             )
109         );
110         $handle     = null;
111         $expression = 'h';
112 
113         do {
114             switch ($expression) {
115                 case 'h':
116                 case 'help':
117                     echo
118                         'Usage:', "\n",
119                         '    h[elp]       to print this help;', "\n",
120                         '    c[onstants]  to print available constants;', "\n",
121                         '    f[unctions]  to print available functions;', "\n",
122                         '    e[xpression] to print the current expression;', "\n",
123                         '    d[ump]       to dump the tree of the expression;', "\n",
124                         '    q[uit]       to quit.', "\n";
125 
126                     break;
127 
128                 case 'c':
129                 case 'constants':
130                     echo
131                         implode(
132                             ', ',
133                             array_keys(
134                                 $visitor->getConstants()->getArrayCopy()
135                             )
136                         ),
137                         "\n";
138 
139                     break;
140 
141                 case 'f':
142                 case 'functions':
143                     echo
144                         implode(
145                             ', ',
146                             array_keys(
147                                 $visitor->getFunctions()->getArrayCopy()
148                             )
149                         ),
150                         "\n";
151 
152                     break;
153 
154                 case 'e':
155                 case 'expression':
156                     echo $handle, "\n";
157 
158                     break;
159 
160                 case 'd':
161                 case 'dump':
162                     if (null === $handle) {
163                         echo 'Type a valid expression before (“> 39 + 3”).', "\n";
164                     } else {
165                         echo $dump->visit($compiler->parse($handle)), "\n";
166                     }
167 
168                     break;
169 
170                 case 'q':
171                 case 'quit':
172                     break 2;
173 
174                 default:
175                     if (null === $expression) {
176                         break;
177                     }
178 
179                     try {
180                         echo $visitor->visit($compiler->parse($expression)), "\n";
181                     } catch (Compiler\Exception $e) {
182                         echo $e->getMessage(), "\n";
183 
184                         break;
185                     }
186 
187                     $handle = $expression;
188 
189                     break;
190             }
191         } while (false !== $expression = $readline->readLine('> '));
192 
193         return;
194     }
195 
196     /**
197      * The command usage.
198      *
199      * @return  int
200      */
201     public function usage()
202     {
203         echo
204             'Usage   : math:calc <options> [expression]', "\n",
205             'Options :', "\n",
206             $this->makeUsageOptionsList([
207                 'help' => 'This help.'
208             ]), "\n";
209 
210         return;
211     }
212 }
213 
214 __halt_compiler();
215 A simple calculator.
216