Completed
Push — master ( df4975...ed8c21 )
by Shane
02:51
created

ValueParser::canStillParseValue()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 12
rs 9.4286
cc 3
eloc 6
nc 3
nop 1
1
<?php
2
3
namespace PhpHocon\Token\Parser;
4
5
use PhpHocon\Token\Tokens;
6
use PhpHocon\Token\Value;
7
use PhpHocon\Token\Value\BooleanValue;
8
use PhpHocon\Token\Value\NullValue;
9
use PhpHocon\Token\Value\NumberValue;
10
use PhpHocon\Token\Value\StringValue;
11
12
class ValueParser implements Parser
13
{
14
    /**
15
     * @var array
16
     */
17
    private $illegalCharacters = [
18
        Tokens::EQUALS,
19
        Tokens::COLON,
20
        Tokens::SPACE,
21
        Tokens::NEW_LINE
22
    ];
23
24
    /**
25
     * @var bool
26
     */
27
    private $isQuotedString;
28
29
    /**
30
     * @var string
31
     */
32
    private $quoteCharacter;
33
34
    /**
35
     * @param ParserState $state
36
     * @return boolean
37
     */
38
    public function canParse(ParserState $state)
39
    {
40
        return !$state->isParsingKey() && $this->canStartGatheringValue($state);
41
    }
42
43
    /**
44
     * @param ParserState $state
45
     * @return ParseResult
46
     */
47
    public function parse(ParserState $state)
48
    {
49
        $characters = $state->getCharacters();
50
        $value = '';
51
52
        if (true === $this->isQuotedString = $this->isQuotedString($state->getHeadCharacter())) {
53
            $this->quoteCharacter = array_shift($characters);
54
        }
55
56
        while ($this->canStillParseValue($characters)) {
57
            $value .= array_shift($characters);
58
        }
59
60
        if (count($characters) && $characters[0] === $this->quoteCharacter) {
61
            array_shift($characters);
62
        }
63
64
        return new ParseResult(
65
            new ParserState($characters, $state->getBraceCount()),
66
            $this->getObjectForValue($value)
67
        );
68
    }
69
70
    /**
71
     * @param ParserState $state
72
     * @return bool
73
     */
74
    private function canStartGatheringValue(ParserState $state)
75
    {
76
        return !in_array($state->getHeadCharacter(), $this->illegalCharacters);
77
    }
78
79
    /**
80
     * @param string $character
81
     * @return bool
82
     */
83
    private function isQuotedString($character)
84
    {
85
        return in_array($character, [Tokens::APOSTROPHE, Tokens::SPEECH_MARK]);
86
    }
87
88
    /**
89
     * @param string[] $characters
90
     * @return bool
91
     */
92
    private function canStillParseValue(array $characters)
93
    {
94
        if (!count($characters)) {
95
            return false;
96
        }
97
98
        if ($this->isQuotedString) {
99
            return !$this->isStringTerminator($characters[0]);
100
        }
101
102
        return !in_array($characters[0], $this->illegalCharacters);
103
    }
104
105
    /**
106
     * @param string $value
107
     * @return Value
108
     */
109
    private function getObjectForValue($value)
110
    {
111
        if (is_numeric($value)) {
112
            return new NumberValue($this->convertStringToNumber($value));
113
        } elseif ($this->valueIsBoolean($value)) {
114
            return new BooleanValue($value === 'true');
115
        } elseif ($this->valueIsNull($value)) {
116
            return new NullValue();
117
        }
118
119
        return new StringValue($value);
120
    }
121
122
    /**
123
     * @param string $value
124
     * @return float|int
125
     */
126
    private function convertStringToNumber($value)
127
    {
128
        return strpos($value, '.') === false ? (int)$value : (float)$value;
129
    }
130
131
    /**
132
     * @param string $value
133
     * @return bool
134
     */
135
    private function valueIsBoolean($value)
136
    {
137
        return $value === 'true' || $value === 'false';
138
    }
139
140
    /**
141
     * @param string $value
142
     * @return bool
143
     */
144
    private function valueIsNull($value)
145
    {
146
        return $value === 'null';
147
    }
148
149
    /**
150
     * @param string $character
151
     * @return bool
152
     */
153
    private function isStringTerminator($character)
154
    {
155
        return $character === $this->quoteCharacter;
156
    }
157
}
158