Skip to content

Commit eb3b2e2

Browse files
committed
Merge pull request #31 from phpcr/cnd-parser
CND parser
2 parents 221482e + f666c36 commit eb3b2e2

28 files changed

+2608
-0
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace PHPCR\Util\CND\Exception;
4+
5+
use PHPCR\Util\CND\Scanner\TokenQueue,
6+
PHPCR\Util\CND\Scanner\GenericToken;
7+
8+
/**
9+
* @author Daniel Barsotti <daniel.barsotti@liip.ch>
10+
*/
11+
class ParserException extends \Exception
12+
{
13+
public function __construct(TokenQueue $queue, $msg)
14+
{
15+
$token = $queue->peek();
16+
$msg = sprintf("PARSER ERROR: %s. Current token is [%s, '%s'] at line %s, column %s", $msg, GenericToken::getTypeName($token->getType()), $token->getData(), $token->getLine(), $token->getRow());
17+
18+
// construct a lookup of the next tokens
19+
$lookup = '';
20+
for($i = 1; $i <= 5; $i++) {
21+
if ($queue->isEof()) {
22+
break;
23+
}
24+
$token = $queue->get();
25+
$lookup .= $token->getData() . ' ';
26+
}
27+
$msg .= "\nBuffer lookup: \"$lookup\"";
28+
29+
parent::__construct($msg);
30+
}
31+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace PHPCR\Util\CND\Exception;
4+
5+
use PHPCR\Util\CND\Reader\ReaderInterface;
6+
7+
/**
8+
* @author Daniel Barsotti <daniel.barsotti@liip.ch>
9+
*/
10+
class ScannerException extends \Exception
11+
{
12+
public function __construct(ReaderInterface $reader, $msg)
13+
{
14+
$msg = sprintf(
15+
"SCANNER ERROR: %s at line %s, column %s.\nCurrent buffer \"%s\"",
16+
$msg,
17+
$reader->getCurrentLine(),
18+
$reader->getCurrentColumn(),
19+
$reader->consume()
20+
);
21+
22+
parent::__construct($msg);
23+
}
24+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<?php
2+
3+
namespace PHPCR\Util\CND\Parser;
4+
5+
use PHPCR\Util\CND\Scanner\GenericToken as Token;
6+
use PHPCR\Util\CND\Scanner\TokenQueue;
7+
use PHPCR\Util\CND\Exception\ParserException;
8+
9+
/**
10+
* Abstract base class for parsers
11+
*
12+
* It implements helper functions for parsers:
13+
*
14+
* - checkToken - check if the next token matches
15+
* - expectToken - expect the next token to match
16+
* - checkAndExpectToken - check and then expect the next token to match
17+
*
18+
* @author Daniel Barsotti <daniel.barsotti@liip.ch>
19+
*/
20+
abstract class AbstractParser
21+
{
22+
/**
23+
* The token queue
24+
* @var TokenQueue
25+
*/
26+
protected $tokenQueue;
27+
28+
/**
29+
* Check the next token without consuming it and return true if it matches the given type and data.
30+
* If the data is not provided (equal to null) then only the token type is checked.
31+
* Return false otherwise.
32+
*
33+
* @param int $type The expected token type
34+
* @param null|string $data The expected data or null
35+
*
36+
* @return bool
37+
*/
38+
protected function checkToken($type, $data = null)
39+
{
40+
if ($this->tokenQueue->isEof()) {
41+
return false;
42+
}
43+
44+
$token = $this->tokenQueue->peek();
45+
46+
if ($token->getType() !== $type) {
47+
return false;
48+
}
49+
50+
if ($data && $token->getData() !== $data) {
51+
return false;
52+
}
53+
54+
return true;
55+
}
56+
57+
/**
58+
* Check if the token data is one of the elements of the data array.
59+
*
60+
* @param int $type
61+
* @param array $data
62+
*
63+
* @return bool
64+
*/
65+
protected function checkTokenIn($type, array $data)
66+
{
67+
foreach ($data as $d) {
68+
if ($this->checkToken($type, $d)) {
69+
return true;
70+
}
71+
}
72+
73+
return false;
74+
}
75+
76+
/**
77+
* Check if the next token matches the expected type and data. If it does, then consume and return it,
78+
* otherwise throw an exception.
79+
*
80+
* @param int $type The expected token type
81+
* @param null|string $data The expected token data or null
82+
*
83+
* @return Token
84+
*
85+
* @throws ParserException
86+
*/
87+
protected function expectToken($type, $data = null)
88+
{
89+
$token = $this->tokenQueue->peek();
90+
91+
if (!$this->checkToken($type, $data)) {
92+
throw new ParserException($this->tokenQueue, sprintf("Expected token [%s, '%s']", Token::getTypeName($type), $data));
93+
}
94+
95+
$this->tokenQueue->next();
96+
97+
return $token;
98+
}
99+
100+
/**
101+
* Check if the next token matches the expected type and data. If it does, then consume it, otherwise
102+
* return false.
103+
*
104+
* @param int $type The expected token type
105+
* @param null|string $data The expected token data or null
106+
* @return bool|Token
107+
*/
108+
protected function checkAndExpectToken($type, $data = null)
109+
{
110+
if ($this->checkToken($type, $data)) {
111+
$token = $this->tokenQueue->peek();
112+
$this->tokenQueue->next();
113+
return $token;
114+
}
115+
116+
return false;
117+
}
118+
}

0 commit comments

Comments
 (0)