@Override
    public SyntaxNode parse() throws SyntaxException, IOException {
        scanner.nextToken();

        if (scanner.getCurrentToken().isType(TokenType.LITERAL)) {
            ast.setAttribute(SyntaxNode.Attributes.TITLE, scanner.getCurrentToken().getValue(true));
            scanner.nextToken();
        }

        if (!assertToken(scanner.getCurrentToken(), TokenType.L_BRACE, "{")) {
            raiseError("Syntax must start with '{'");
        }

        scanner.nextToken();

        while (scanner.hasNextToken()) {
            if (scanner.getCurrentToken().isType(TokenType.IDENTIFIER)) {
                final Node rules = parseRule();
                ast.addChild(rules);
                scanner.nextToken();
            } else if (scanner.getCurrentToken().isType(TokenType.COMMENT)) {
                final CommentNode comment = CommentNode.newInstance(ast,
                                                            scanner.getCurrentToken().getValue());
                ast.addChild(comment);
                scanner.nextToken();
            } else {
                break;
            }
        }

        if (!assertToken(scanner.getCurrentToken(), TokenType.R_BRACE, "}")) {
            raiseError(String.format("Syntax must end with '}' but saw '%s'",
                                     scanner.getCurrentToken()));
        }

        scanner.nextToken();

        if (scanner.hasNextToken()) {
            if (scanner.getCurrentToken().isType(TokenType.LITERAL)) {
                ast.setAttribute(SyntaxNode.Attributes.META, scanner.getCurrentToken().getValue(true));
            } else {
                raiseError("Literal expected as syntax comment");
            }
        }

        return ast;
    }