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
37namespace Hoa\Math\Bin;
38
39use Hoa\Compiler;
40use Hoa\Console;
41use Hoa\File;
42use 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 */
52class 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();
215A simple calculator.
216