Skip to content
This repository has been archived by the owner on Apr 24, 2018. It is now read-only.

Commit

Permalink
Merge pull request #1 from hansott/feature-schema-parser
Browse files Browse the repository at this point in the history
✨  Add schema declaration parser
  • Loading branch information
hansott authored Sep 23, 2017
2 parents b0b79e9 + 43c72e3 commit 9ac4d86
Show file tree
Hide file tree
Showing 71 changed files with 1,941 additions and 191 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
/composer.lock
/vendor/*
/.idea/*
/.php_cs.cache
/test.php
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Changelog

All Notable changes to `hansott/graphql-language` will be documented in this file.
See [releases](https://github.com/hansott/graphql-language/releases).
67 changes: 67 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,73 @@ $traverser->traverse($document);
var_dump($finder->getQueries());
```

### Parsing a schema declaration to a [HansOtt\GraphQL\Schema\Schema](src/Schema/Schema.php)

```php
use HansOtt\GraphQL\Schema\ParseError;
use HansOtt\GraphQL\Schema\SyntaxError;
use HansOtt\GraphQL\Schema\ParserFactory;

$factory = new ParserFactory;
$parser = $factory->create();

$schema = <<<'SCHEMA'
enum DogCommand { SIT, DOWN, HEEL }

type Dog implements Pet {
name: String!
nickname: String
barkVolume: Int
doesKnowCommand(dogCommand: DogCommand!): Boolean!
isHousetrained(atOtherHomes: Boolean): Boolean!
owner: Human
}

interface Sentient {
name: String!
}

interface Pet {
name: String!
}

type Alien implements Sentient {
name: String!
homePlanet: String
}

type Human implements Sentient {
name: String!
}

enum CatCommand { JUMP }

type Cat implements Pet {
name: String!
nickname: String
doesKnowCommand(catCommand: CatCommand!): Boolean!
meowVolume: Int
}

union CatOrDog = Cat | Dog
union DogOrHuman = Dog | Human
union HumanOrAlien = Human | Alien

type QueryRoot {
dog: Dog
}
SCHEMA;

try {
$schema = $parser->parse($schema);
var_dump($schema); // Instance of HansOtt\GraphQL\Schema\Schema
} catch (SyntaxError $e) {
echo "Syntax error in query: {$e->getMessage()}" . PHP_EOL;
} catch (ParseError $e) {
echo "Failed to parse query: {$e->getMessage()}" . PHP_EOL;
}
```

## Change log

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
Expand Down
6 changes: 5 additions & 1 deletion src/Query/Lexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

namespace HansOtt\GraphQL\Query;

final class Lexer
use HansOtt\GraphQL\Shared\ScannerGeneric;
use HansOtt\GraphQL\Shared\ScannerWithLocation;
use HansOtt\GraphQL\Shared\Lexer as LexerShared;

final class Lexer implements LexerShared
{
/**
* @var ScannerWithLocation
Expand Down
12 changes: 3 additions & 9 deletions src/Query/Location.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,8 @@

namespace HansOtt\GraphQL\Query;

final class Location
{
public $line;
public $column;
use HansOtt\GraphQL\Shared\Location as LocationShared;

public function __construct($line, $column)
{
$this->line = (int) $line;
$this->column = (int) $column;
}
final class Location extends LocationShared
{
}
13 changes: 3 additions & 10 deletions src/Query/Node.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,8 @@

namespace HansOtt\GraphQL\Query;

interface Node
{
/**
* @return Node[]
*/
public function getChildren();
use HansOtt\GraphQL\Shared\Node as NodeShared;

/**
* @return Location
*/
public function getLocation();
interface Node extends NodeShared
{
}
15 changes: 3 additions & 12 deletions src/Query/NodeBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,8 @@

namespace HansOtt\GraphQL\Query;

abstract class NodeBase implements Node
{
public $location;

public function __construct(Location $location = null)
{
$this->location = $location;
}
use HansOtt\GraphQL\Shared\NodeBase as NodeBaseShared;

public function getLocation()
{
return $this->location;
}
abstract class NodeBase extends NodeBaseShared implements Node
{
}
4 changes: 2 additions & 2 deletions src/Query/ParseError.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

namespace HansOtt\GraphQL\Query;

use Exception;
use HansOtt\GraphQL\Shared\ParseError as ParseErrorShared;

final class ParseError extends Exception
final class ParseError extends ParseErrorShared
{
}
65 changes: 12 additions & 53 deletions src/Query/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,15 @@

namespace HansOtt\GraphQL\Query;

final class Parser
{
/**
* @var ScannerTokens
*/
private $scanner;
private $lexer;

public function __construct(Lexer $lexer)
{
$this->lexer = $lexer;
}

private function getParseError($message)
{
$token = $this->scanner->getLastToken();
if ($this->scanner->eof() === false) {
$token = $this->scanner->peek();
}

return new ParseError($message . " (line {$token->location->line}, column {$token->location->column})");
}

private function expect($tokenType)
{
$token = $this->scanner->next();

if ($token->type !== $tokenType) {
$expectedToken = Token::getNameFor($tokenType);
throw $this->getParseError("Expected \"{$expectedToken}\" but instead found \"{$token->getName()}\" with value \"{$token->value}\"");
}

return $token;
}

private function accept($tokenType)
{
$token = $this->scanner->peek();

if ($token->type !== $tokenType) {
return false;
}

return $this->scanner->next();
}
use HansOtt\GraphQL\Shared\ScannerTokens;
use HansOtt\GraphQL\Shared\ScannerGeneric;
use HansOtt\GraphQL\Shared\Parser as ParserShared;

private function is($tokenType)
final class Parser extends ParserShared
{
protected function getNameFor($tokenType)
{
if ($this->scanner->eof()) {
return false;
}

$token = $this->scanner->peek();

return $token->type === $tokenType;
return Token::getNameFor($tokenType);
}

private function parseObject()
Expand Down Expand Up @@ -475,6 +429,11 @@ private function parseDocument()
return new Document($definitions);
}

/**
* @param string $query
*
* @return Document
*/
public function parse($query)
{
$tokens = $this->lexer->lex($query);
Expand Down
9 changes: 0 additions & 9 deletions src/Query/ScannerReachedEnd.php

This file was deleted.

4 changes: 2 additions & 2 deletions src/Query/SyntaxError.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

namespace HansOtt\GraphQL\Query;

use Exception;
use HansOtt\GraphQL\Shared\SyntaxError as SyntaxErrorShared;

final class SyntaxError extends Exception
final class SyntaxError extends SyntaxErrorShared
{
}
45 changes: 3 additions & 42 deletions src/Query/Token.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

namespace HansOtt\GraphQL\Query;

use ReflectionClass;
use HansOtt\GraphQL\Shared\Token as TokenShared;

final class Token
final class Token extends TokenShared
{
const T_NAME = 0;
const T_STRING = 1;
Expand All @@ -29,44 +29,5 @@ final class Token
const T_BRACKET_RIGHT = 20;
const T_BRACE_LEFT = 21;
const T_BRACE_RIGHT = 22;
const T_PIPE = 23;
const T_COMMA = 24;

public $type;
public $value;
public $location;

public function __construct($type, $value, Location $location)
{
$this->type = (int) $type;
$this->value = (string) $value;
$this->location = $location;
}

private static function getNames()
{
static $typeToName;

if (is_array($typeToName)) {
return $typeToName;
}

$reflection = new ReflectionClass('HansOtt\\GraphQL\\Query\\Token');
$constants = $reflection->getConstants();
$typeToName = array_flip($constants);

return $typeToName;
}

public static function getNameFor($type)
{
$typeToName = static::getNames();

return $typeToName[$type];
}

public function getName()
{
return static::getNameFor($this->type);
}
const T_COMMA = 23;
}
4 changes: 4 additions & 0 deletions src/Query/TypeNamed.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ final class TypeNamed extends NodeBase implements Type
{
public $name;

/**
* @param string $name
* @param Location|null $location
*/
public function __construct($name, Location $location = null)
{
parent::__construct($location);
Expand Down
7 changes: 1 addition & 6 deletions src/Query/ValueBoolean.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace HansOtt\GraphQL\Query;

final class ValueBoolean extends NodeBase implements Value
final class ValueBoolean extends NodeBase implements ValueScalar
{
private $isTrue;

Expand All @@ -11,9 +11,4 @@ public function __construct($isTrue, Location $location = null)
parent::__construct($location);
$this->isTrue = (bool) $isTrue;
}

public function getChildren()
{
return array();
}
}
9 changes: 4 additions & 5 deletions src/Query/ValueEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ final class ValueEnum extends NodeBase implements Value
{
public $value;

/**
* @param string $value
* @param Location|null $location
*/
public function __construct($value, Location $location = null)
{
parent::__construct($location);
$this->value = (string) $value;
}

public function getChildren()
{
return array();
}
}
11 changes: 5 additions & 6 deletions src/Query/ValueFloat.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,17 @@

namespace HansOtt\GraphQL\Query;

final class ValueFloat extends NodeBase implements Value
final class ValueFloat extends NodeBase implements ValueScalar
{
public $value;

/**
* @param string $value
* @param Location|null $location
*/
public function __construct($value, Location $location = null)
{
parent::__construct($location);
$this->value = (float) $value;
}

public function getChildren()
{
return array();
}
}
Loading

0 comments on commit 9ac4d86

Please sign in to comment.