Rule::syntax()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 1
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 0
nc 1
nop 0
dl 0
loc 1
rs 10
c 0
b 0
f 0
1
<?php
2
	
3
/**
4
	* Rule.php
5
	*/
6
	
7
namespace netfocusinc\argh;
8
9
/**
10
	* Representation of a Rule used to interpret command line arguments
11
	*
12
	* Rules are a combination of syntax and semantics used to interpret command line arguments.
13
	* When a command line string matches the syntax of a rule, and its character content matches the sematics of the rule
14
	* this command line string can be used to create an Argument.
15
	*
16
	* @author Benjamin Hough
17
	*
18
	* @since 1.0.0
19
	*/
20
class Rule
21
{
22
	//
23
	// CONSTANTS
24
	//
25
	
26
	// Syntax Contants
27
	
28
	const ARGH_SYNTAX_FLAG			= '[a-z]{1}';
29
	const ARGH_SYNTAX_FLAGS		= '[a-z]+';
30
	const ARGH_SYNTAX_NAME			= '[a-z0-9_]+';
31
	const ARGH_SYNTAX_VALUE		= '[a-z0-9_\.\/]*';
32
	const ARGH_SYNTAX_LIST			= '[a-z0-9_\-,\' ]+';
33
	const ARGH_SYNTAX_COMMAND	= '[a-z0-9_]{2,}';
34
	const ARGH_SYNTAX_QUOTED		= '[a-z0-9_\-\'\\/\. ]+';
35
	const ARGH_SYNTAX_VARIABLE	= '[a-z0-9_\.\/]*';
36
	
37
	// Semantic Contants
38
	const ARGH_SEMANTICS_FLAG			= 1;
39
	const ARGH_SEMANTICS_FLAGS			= 2;
40
	const ARGH_SEMANTICS_NAME			= 3;
41
	const ARGH_SEMANTICS_VALUE			= 4;
42
	const ARGH_SEMANTICS_LIST			= 5;
43
	const ARGH_SEMANTICS_COMMAND		= 6;
44
	const ARGH_SEMANTICS_VARIABLE	= 7;
45
	
46
	//
47
	// PUBLIC PROPERTIES
48
	//
49
	
50
	/** @var string The 'name' of this Rule */
51
	private $name = null;
52
	
53
	/** @var string An 'example' string that matches the syntax of this Rule */
54
	private $example = null;
55
	
56
	/** @var string A regular expression defining the acceptable syntax for this Rule */
57
	private $syntax = null;
58
	
59
	/** @var array Array of Rule's contants defining the semantical meaning for this Rule */
60
	private $semantics = null;
61
	
62
	//
63
	// STATIC FUNCTIONS
64
	//
65
	
66
	/**
67
		* Creates a new Rule with the specified $attributes
68
		*
69
		* Convenience method for creating new Rules with the specified $attributes
70
		*
71
		* @since 1.0.0
72
		*
73
		* @returns Rule
74
		*/
75
	public static function createWithAttributes(array $attributes): Rule
76
	{
77
		// Defaults
78
		$name = null;
79
		$example = null;
80
		$syntax = null;
81
		$semantics = null;
82
		
83
		if( array_key_exists('name', $attributes) ) $name = $attributes['name'];
84
		if( array_key_exists('example', $attributes) ) $example = $attributes['example'];
85
		if( array_key_exists('syntax', $attributes) ) $syntax = $attributes['syntax'];
86
		if( array_key_exists('semantics', $attributes) ) $semantics = $attributes['semantics'];
87
		
88
		return new self($name, $example, $syntax, $semantics);
89
90
	}
91
	
92
	/**
93
		* Returns a (human friendly) string representation of a semantic int
94
		*
95
		* @since 1.0.0
96
		*
97
		* @param int $semantics
98
		*
99
		* @returns string
100
		*/
101
	public static function semanticsToString(int $semantics)
102
	{
103
		switch($semantics)
104
		{
105
			case self::ARGH_SEMANTICS_FLAG:			return 'FLAG';
106
			case self::ARGH_SEMANTICS_FLAGS:		return 'FLAGS';
107
			case self::ARGH_SEMANTICS_NAME:			return 'NAME';
108
			case self::ARGH_SEMANTICS_VALUE:		return 'VALUE';
109
			case self::ARGH_SEMANTICS_LIST:			return 'LIST';
110
			case self::ARGH_SEMANTICS_COMMAND:	return 'COMMAND';
111
			case self::ARGH_SEMANTICS_VARIABLE:	return 'VARIABLE';
112
			default:														return '*invalid*';
113
		}
114
	}
115
	
116
	//
117
	// PUBLIC METHODS
118
	//
119
	
120
	/**
121
		* Rule contructor.
122
		*
123
		* Constructs a new Rule.
124
		*
125
		* @since 1.0.0
126
		*
127
		* @param string $name
128
		* @param string $example
129
		* @param string $syntax
130
		* @param array $semantics
131
		*
132
		* @throws ArghException
133
		*/
134
	public function __construct(string $name, string $example, string $syntax, array $semantics)
135
	{
136
		
137
		// Validate the syntax regular expression
138
		// Suppress error messages
139
		if( @preg_match($syntax, '') === FALSE )
140
		{
141
			throw new ArghException('Rule \'' . $name . '\' syntax \'' . $syntax .  '\' is not a valid regular expression');
142
		}
143
		
144
		// Confirm count(semantics) matches number of parenthesized subpatterns defined by the syntax regular expression
145
		if( substr_count($syntax, '(') != count($semantics) )
146
		{
147
			throw new ArghException('Rule \'' . $name . '\' syntax defines ' . substr_count($syntax, '(') . ' sub-patterns, but semantics defines ' . count($semantics));
148
		}
149
		
150
		// Set properties on this instance
151
		$this->name = $name;
152
		$this->syntax = $syntax;
153
		$this->semantics = $semantics;
154
		$this->example = $example;
155
	}
156
157
	/**
158
		* Gets the 'name' property of this Rule
159
		*
160
		* @since 1.0.0
161
		*
162
		* @return string
163
	*/
164
	public function name(): string { return $this->name; }
165
166
	/**
167
		* Gets the 'syntax' property of this Rule
168
		*
169
		* @since 1.0.0
170
		*
171
		* @return string
172
	*/
173
	public function syntax(): string { return $this->syntax; }
174
	
175
	/**
176
		* Gets the 'semantics' property of this Rule
177
		*
178
		* @since 1.0.0
179
		*
180
		* @return array
181
	*/
182
	public function semantics(): array { return $this->semantics; }
183
	
184
	/**
185
		* Gets the 'sample' of this Rule
186
		*
187
		* @since 1.0.0
188
		*
189
		* @return string
190
	*/
191
	public function example(): string { return $this->example; }
192
193
	/**
194
		* Does this Rule match a $string
195
		*
196
		* Note that matching a Rule does not guarantee the Rule will result
197
		* in a new Argument. Ultimately, the argument string may not meet all the 
198
		* requirements of the Rule, e.g. matching defined parameter name|flag|options
199
		*
200
		* @param $string string A string to check for match with this Rule
201
		* @param $tokens array Reference to an array, on match will contain matching elements
202
		*
203
		* @return bool
204
	  */	
205
	public function match($string, &$tokens=array()): bool
206
	{
207
		if( preg_match($this->syntax(), $string, $tokens) )
208
		{
209
			return TRUE;
210
		}
211
		else
212
		{
213
			return FALSE;
214
		}
215
	}
216
		
217
}
218
	
219
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...