1: <?php
2:
3: namespace BN\Compiler\Grammar;
4:
5: use BN\Compiler\Token\TokenType;
6: use BN\Compiler\Scanner\Scanner;
7: use BN\Compiler\Scanner\UnarySignsScanner;
8: use BN\Compiler\Scanner\LexemeToToken;
9: use BN\Compiler\Scanner\LexemeToTokens;
10: use BN\Compiler\Scanner\LexemeConverter;
11: use BN\Compiler\Scanner\Converter\LexemeToUnknown;
12: use BN\Compiler\Scanner\Converter\LexemeToKeyword;
13: use BN\Compiler\Scanner\Converter\LexemeToConstant;
14: use BN\Compiler\Scanner\Converter\LexemeToAssign;
15: use BN\Compiler\Scanner\Converter\LexemeToVariable;
16:
17: class GrammarBuilder
18: {
19: private $toNumber;
20: private $keywords;
21: private $constants;
22: private $operators;
23: private $unarySigns;
24: private $whiteSpace;
25: private $assignOperator;
26: private $statementsSeparator;
27:
28: public function __construct(LexemeConverter $lexemeToNumber)
29: {
30: $this->toNumber = $lexemeToNumber;
31: $this->keywords = array();
32: $this->whiteSpace = array();
33: $this->constants = array();
34: $this->operators = new Operators();
35: }
36:
37: public function statementsSeparator($statementsSeparator)
38: {
39: $this->statementsSeparator = $statementsSeparator;
40: return $this;
41: }
42:
43: public function whiteSpace()
44: {
45: $this->whiteSpace = func_get_args();
46: return $this;
47: }
48:
49: public function assign($assignOperator)
50: {
51: $operator = new OperatorBuilder();
52: $this->assignOperator = $assignOperator;
53: $this->operators->register(
54: $assignOperator,
55: $operator->precedence(0)->rightAssociative()
56: );
57: return $this;
58: }
59:
60: public function brackets($openingBracket, $closingBracket)
61: {
62: $this->keyword($openingBracket, TokenType::BRACKET_OPENING);
63: $this->keyword($closingBracket, TokenType::BRACKET_CLOSING);
64: return $this;
65: }
66:
67: public function unarySigns()
68: {
69: $this->unarySigns = func_get_args();
70: return $this;
71: }
72:
73: public function operators(array $operators)
74: {
75: foreach ($operators as $symbol => $operator) {
76: $this->operators->register($symbol, $operator);
77: $this->keyword($symbol, TokenType::OPERATOR);
78: }
79: return $this;
80: }
81:
82: public function keyword($symbol, $tokenType)
83: {
84: $this->keywords[$symbol] = $tokenType;
85: return $this;
86: }
87:
88: public function numberConstant($symbol, $value)
89: {
90: $this->constants[$symbol] = $value;
91: return $this;
92: }
93:
94: public function buildOperators()
95: {
96: return $this->operators;
97: }
98:
99: public function buildConstants()
100: {
101: return $this->constants;
102: }
103:
104: public function buildScanner()
105: {
106: $unknownLexeme = new LexemeToUnknown();
107: $toToken = new LexemeToToken($unknownLexeme);
108: $toToken->registerLexer(new LexemeToAssign($this->assignOperator));
109: $toToken->registerLexer(new LexemeToVariable());
110: $toToken->registerLexer($this->toNumber);
111: $toToken->registerLexer(new LexemeToKeyword($this->keywords));
112: $toToken->registerLexer(new LexemeToConstant(array_keys($this->constants)));
113: $toTokens = new LexemeToTokens($toToken);
114: $scanner = new Scanner($toTokens, $this->whiteSpace, $this->statementsSeparator);
115: if ($this->unarySigns) {
116: return new UnarySignsScanner($scanner, $this->unarySigns);
117: } else {
118: return $scanner;
119: }
120: }
121: }
122: