Skip to content

Commit

Permalink
Add EBNF in the documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
adoy committed Apr 27, 2017
1 parent 3b85168 commit ff0a258
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 5 deletions.
16 changes: 16 additions & 0 deletions EBNF.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# NACL EBNF

```ebnf
Nacl ::= Array | Object
Object ::= "{" InnerObject "}" | InnerObject
InnerObject ::= [ KeyValueList [ "," | ";" ] ]
KeyValueList ::= KeyValue [ [ "," | ";" ] KeyValueList ]
KeyValue ::= ( ( T_END_STR | T_NAME | T_VAR ) [ ":" | "=" ] Value ) | MacroCall
Array ::= "[" [ ValueList ] "]"
ValueList ::= Value [ "," ValueList ]
Value ::= String | Scalar | Variable | "{" InnerObject "}" | Array | MacroCall
Scalar ::= T_END_STR | T_NAME | T_BOOL | T_NUM | T_NULL
String ::= { T_ENCAPSED_VAR | T_STRING }* T_END_STR
Variable ::= T_VAR
MacroCall ::= "." T_NAME [ "(" [ Object ] ")" ] Value
```
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ NACL is a configuration language both human and machine friendly.
It's a JSON superset which means that JSON can be used as valid input to the NACL parser.
NACL is heavily inspired by libucl.

For the detailed grammar refer to the [EBNF](EBNF.md).

## Example

```nacl
Expand Down
37 changes: 32 additions & 5 deletions src/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ public function setVariable($name, $value)
$this->variables[$name] = $value;
}

/**
* Nacl ::= Array | Object
*/
public function parse($str, $filename = 'nacl string')
{
$this->lexer->push($str, $filename);
Expand Down Expand Up @@ -51,6 +54,12 @@ public function parseFile($file)
return $this->parse(file_get_contents($file), $filename);
}

/**
* Object ::= "{" InnerObject "}" | InnerObject
* InnerObject ::= [ KeyValueList [ "," | ";" ] ]
* KeyValueList ::= KeyValue [ [ "," | ";" ] KeyValueList ]
* KeyValue ::= ( ( T_END_STR | T_NAME | T_VAR ) [ ":" | "=" ] Value ) | MacroCall
*/
private function parseObject()
{
$object = [];
Expand Down Expand Up @@ -86,7 +95,6 @@ private function parseObject()
$continue = $this->consumeOptional(',') || $this->consumeOptional(';');
break;
case '.':
$this->nextToken();
$val = $this->parseMacro($object);
$continue = $this->consumeOptional(';');
break;
Expand All @@ -100,6 +108,10 @@ private function parseObject()
return $object;
}

/**
* Array ::= "[" [ ValueList ] "]"
* ValueList ::= Value [ "," ValueList ]
*/
private function parseArray()
{
$array = [];
Expand All @@ -116,6 +128,9 @@ private function parseArray()
return $array;
}

/**
* Value ::= String | Scalar | Variable | "{" InnerObject "}" | Array | MacroCall
*/
private function parseValue()
{
switch ($this->token->type) {
Expand All @@ -141,7 +156,6 @@ private function parseValue()
$value = $this->parseArray();
break;
case '.':
$this->nextToken();
$value = $this->parseMacro();
break;
default:
Expand All @@ -151,6 +165,9 @@ private function parseValue()
return $value;
}

/**
* Scalar ::= T_END_STR | T_NAME | T_BOOL | T_NUM | T_NULL
*/
private function parseScalar()
{
$value = $this->token->value;
Expand All @@ -159,6 +176,9 @@ private function parseScalar()
return $value;
}

/**
* String ::= { T_ENCAPSED_VAR | T_STRING }* T_END_STR
*/
private function parseString()
{
$value = '';
Expand All @@ -175,14 +195,17 @@ private function parseString()
case Token::T_STRING:
$value .= $this->token->value;
break;
}
}

$this->nextToken();
} while ($continue);

return $value;
}

/**
* Variable ::= T_VAR
*/
private function getVariable($name)
{
if (!isset($this->variables[$name])) {
Expand All @@ -194,8 +217,12 @@ private function getVariable($name)
return $this->variables[$name];
}

private function parseMacro(&$context = null)
/**
* MacroCall ::= "." T_NAME [ "(" [ Object ] ")" ] Value
*/
private function parseMacro(array &$context = null)
{
$this->consume('.');
$result = null;

if ($this->token->type != Token::T_NAME) {
Expand Down Expand Up @@ -252,7 +279,7 @@ private function deepMerge(array $a1, array $a2)
return $a1;
}

private function doInclude($file, $options, &$context)
private function doInclude($file, $options, array &$context = null)
{
$options = array_merge([
'required' => true,
Expand Down

0 comments on commit ff0a258

Please sign in to comment.