Parser::cleanup()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 8
cts 8
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 8
nc 1
nop 1
crap 1
1
<?php
2
3
namespace LisPhp;
4
5
use RuntimeException;
6
7
class Parser
8
{
9
    /**
10
     * @param string $input
11
     *
12
     * @return array
13
     */
14 45
    public static function parse(string $input) : array
15
    {
16 45
        $input = static::cleanup($input);
17
18 45
        $tokens = static::tokenize($input);
19
20 45
        return static::readFromTokens($tokens);
21
    }
22
23
    /**
24
     * @param array $tokens
25
     *
26
     * @return array
27
     */
28 45
    protected static function readFromTokens(array &$tokens)
29
    {
30 45
        if (count($tokens) === 0) {
31 3
            throw new RuntimeException('Unexpected EOF while reading');
32
        }
33
34 42
        $token = array_shift($tokens);
35
36 42
        if ($token === '(') {
37 39
            $list = [];
38
39 39
            while (count($tokens) && $tokens[0] !== ')') {
40 39
                $list[] = static::readFromTokens($tokens);
41
            }
42
43 39
            if (count($tokens) && $tokens[0] === ')') {
44 33
                array_shift($tokens);
45
            } else {
46 9
                throw new RuntimeException('Invalid syntax');
47
            }
48
49 33
            return $list;
50 39
        } elseif ($token === ')') {
51 3
            throw new RuntimeException('Invalid syntax');
52
        } else {
53 36
            return static::atom($token);
54
        }
55
    }
56
57
    /**
58
     * Splits a program into tokens.
59
     *
60
     * @param string $input
61
     *
62
     * @return array $tokens
63
     */
64 45
    protected static function tokenize(string $input) : array
65
    {
66 45
        $tokens = array_filter(
67
            explode(
68 45
                ' ',
69 45
                str_replace(['(', ')'], [' ( ', ' ) '], $input)
70
            ),
71 45
            function($value) {
72 45
                return $value !== '';
73 45
            }
74
        );
75
76 45
        return $tokens;
77
    }
78
79
    /**
80
     * Converts a token into an atom.
81
     *
82
     * @param mixed $value
83
     *
84
     * @return mixed
85
     */
86 36
    protected static function atom($value)
87
    {
88 36
        if (is_numeric($value)) {
89 33
            return is_float($value) ? (float) $value : (int) $value;
90
        } else {
91 36
            return $value;
92
        }
93
    }
94
95
    /**
96
     * Cleanups extra spaces.
97
     *
98
     * @param string $input
99
     *
100
     * @return string $input
101
     */
102 45
    protected static function cleanup($input)
103
    {
104 45
        $input = preg_replace('/\s+/', ' ', $input);
105 45
        $input = preg_replace('/\(\s+/', ' (', $input);
106 45
        $input = preg_replace('/\s+\(/', ' (', $input);
107 45
        $input = preg_replace('/\s+\)/', ') ', $input);
108 45
        $input = preg_replace('/\)\s+/', ') ', $input);
109 45
        $input = trim($input);
110
111 45
        return $input;
112
    }
113
}
114