"""yapps input grammar for SPARQL.

:organization: Logilab
:copyright: 2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""

# flake8: noqa

from fyzz.ast import *


class FyzzParserError(Exception):
    """Base Fyzz parser Error"""


class FyzzParserSyntaxError(FyzzParserError):
    """Error when trying to parse the Sparql expression

    title: title used to present the exception
    text: sparql expression that was parsed
    err: SyntaxError raised by yapps
    """

    def __init__(self, text, err):
        self.text = text
        self.err = err

    def __str__(self):
        lines = self.text.splitlines()
        lineno, carno = self.err.pos[1], self.err.pos[2]
        out = "\n".join(lines[:lineno])
        out += "\n%s^\n" % ((carno - 1) * " ")
        out += "\n".join(lines[lineno:])
        return "\n%s\n%s" % (out, self.err)


class FyzzParserPrefixError(FyzzParserError):
    """Error raised when invalid prefix is used"""

    def __init__(self, ns, valid_prefixes):
        self.ns = ns
        self.valid_prefixes = valid_prefixes

    def __str__(self):
        return "Invalid prefix %r should be in %s" % (self.ns, self.valid_prefixes)


def check_prefixed_name(R, ns, name):
    if ns not in R.prefixes:
        raise FyzzParserPrefixError(ns, list(R.prefixes))
    return (R.prefixes[ns], name)


def simplify_expr(expr):
    if len(expr) == 2 and expr[0] in ("or", "and"):
        return expr[1]
    else:
        return expr


# Begin -- grammar generated by Yapps
import re
from yapps import runtime


class FyzzScanner(runtime.Scanner):
    patterns = [
        ("\\s+", re.compile("\\s+")),
        ("#.*", re.compile("#.*")),
        ("IRI_REF", re.compile('<[^<>"{}|^\\`]*>')),
        ("PNAME_NS", re.compile("([A-Za-z]([A-Za-z0-9_.-]*[A-Za-z0-9_-])?)?:")),
        (
            "BLANK_NODE_LABEL",
            re.compile("_:[A-Za-z_0-9]([A-Za-z0-9_.-]*[A-Za-z0-9_-])?"),
        ),
        ("VAR1", re.compile("\\?[A-Za-z_0-9]+")),
        ("VAR2", re.compile("\\$[A-Za-z_0-9]+")),
        ("LANGTAG", re.compile("@[a-zA-Z]+(-[a-zA-Z0-9]+)*")),
        ("INTEGER", re.compile("\\d+")),
        ("DECIMAL", re.compile("(\\d+\\.\\d*)|(\\.\\d+)")),
        (
            "DOUBLE",
            re.compile(
                "(\\d+\\.\\d*[eE][+-]?\\d+)|(\\.\\d+[eE][+-]?\\d+)|(\\d+[eE][+-]?\\d+)"
            ),
        ),
        ("INTEGER_POSITIVE", re.compile("\\+\\d+")),
        ("DECIMAL_POSITIVE", re.compile("\\+(\\d+\\.\\d*)|(\\.\\d+)")),
        (
            "DOUBLE_POSITIVE",
            re.compile(
                "\\+(\\d+\\.\\d*[eE][+-]?\\d+)|(\\.\\d+[eE][+-]?\\d+)|(\\d+[eE][+-]?\\d+)"
            ),
        ),
        ("INTEGER_NEGATIVE", re.compile("-\\d+")),
        ("DECIMAL_NEGATIVE", re.compile("-(\\d+\\.\\d*)|(\\.\\d+)")),
        (
            "DOUBLE_NEGATIVE",
            re.compile(
                "-(\\d+\\.\\d*[eE][+-]?\\d+)|(\\.\\d+[eE][+-]?\\d+)|(\\d+[eE][+-]?\\d+)"
            ),
        ),
        ("STRING_LITERAL1", re.compile("'([\\w\\s\\\\_-]|(\\\")|(\\'))*'")),
        ("STRING_LITERAL2", re.compile('"([\\w\\s\\\\_-]|(\\")|(\\\'))*"')),
        ("STRING_LITERAL_LONG1", re.compile("'''[\\w\\s\\\\_\\\"'-]*'''")),
        ("STRING_LITERAL_LONG2", re.compile('"""[\\w\\s\\\\_"\\\'-]*"""')),
        ("NIL", re.compile("\\(\\s*\\)")),
        ("ANON", re.compile("\\[\\s*\\]")),
        ("PN_PREFIX", re.compile("[A-Za-z]([A-Za-z0-9_.-]*[A-Za-z0-9_-])?")),
        ("PN_LOCAL", re.compile("[A-Za-z_0-9]([A-Za-z0-9_.-]*[A-Za-z0-9_-])?")),
        ("PREFIX", re.compile("PREFIX")),
        ("SELECT", re.compile("SELECT")),
        ("CONSTRUCT", re.compile("CONSTRUCT")),
        ("DESCRIBE", re.compile("DESCRIBE")),
        ("ASK", re.compile("ASK")),
        ("WHERE", re.compile("WHERE")),
        ("OPTIONAL", re.compile("OPTIONAL")),
        ("UNION", re.compile("UNION")),
        ("GRAPH", re.compile("GRAPH")),
        ("BASE", re.compile("BASE")),
        ("ORDER", re.compile("ORDER")),
        ("BY", re.compile("BY")),
        ("ASC", re.compile("ASC")),
        ("DESC", re.compile("DESC")),
        ("LIMIT", re.compile("LIMIT")),
        ("OFFSET", re.compile("OFFSET")),
        ("FILTER", re.compile("FILTER")),
        ("DISTINCT", re.compile("DISTINCT")),
        ("REDUCED", re.compile("REDUCED")),
        ("FROM", re.compile("FROM")),
        ("NAMED", re.compile("NAMED")),
        ("A", re.compile("a")),
        ("TRUE", re.compile("true")),
        ("FALSE", re.compile("false")),
        ("STAR", re.compile("\\*")),
        ("LBRACK", re.compile("{")),
        ("RBRACK", re.compile("}")),
        ("LSBRA", re.compile("\\[")),
        ("RSBRA", re.compile("\\]")),
        ("LPAREN", re.compile("\\(")),
        ("RPAREN", re.compile("\\)")),
        ("DOT", re.compile("\\.")),
        ("COLON", re.compile(":")),
        ("SEMICOLON", re.compile(";")),
        ("COMMA", re.compile(",")),
        ("OR", re.compile("||")),
        ("AND", re.compile("AND")),
        ("LANG", re.compile("LANG")),
        ("LANGMATCHES", re.compile("LANGMATCHES")),
        ("DATATYPE", re.compile("DATATYPE")),
        ("BOUND", re.compile("BOUND")),
        ("SAMETERM", re.compile("sameTerm")),
        ("ISIRI", re.compile("isIRI")),
        ("ISURI", re.compile("isURI")),
        ("ISBLANK", re.compile("isBLANK")),
        ("ISLITERAL", re.compile("isLITERAL")),
        ("REGEX", re.compile("REGEX")),
        ("STR", re.compile("(?i)STR")),
        ("EQUAL", re.compile("=")),
        ("NOTEQUAL", re.compile("!=")),
        ("LESSER", re.compile("<")),
        ("GREATER", re.compile(">")),
        ("LESSEREQ", re.compile("<=")),
        ("GREATEREQ", re.compile(">=")),
        ("PLUS", re.compile("\\+")),
        ("MINUS", re.compile("-")),
        ("DIVIDE", re.compile("/")),
        ("NOT", re.compile("!")),
    ]

    def __init__(self, str, *args, **kw):
        runtime.Scanner.__init__(
            self,
            None,
            {
                "#.*": None,
                "\\s+": None,
            },
            str,
            *args,
            **kw
        )


class Fyzz(runtime.Parser):
    Context = runtime.Context

    def Query(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "Query", [R])
        Prologue = self.Prologue(R, _context)
        _token = self._peek("SELECT", "CONSTRUCT", "DESCRIBE", "ASK", context=_context)
        if _token == "SELECT":
            SelectQuery = self.SelectQuery(R, _context)
        elif _token == "CONSTRUCT":
            ConstructQuery = self.ConstructQuery(R, _context)
        elif _token == "DESCRIBE":
            DescribeQuery = self.DescribeQuery(R, _context)
        else:  # == 'ASK'
            AskQuery = self.AskQuery(R, _context)

    def Prologue(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "Prologue", [R])
        if (
            self._peek(
                "BASE",
                "PREFIX",
                "SELECT",
                "CONSTRUCT",
                "DESCRIBE",
                "ASK",
                context=_context,
            )
            == "BASE"
        ):
            BaseDecl = self.BaseDecl(R, _context)
        while (
            self._peek(
                "PREFIX", "SELECT", "CONSTRUCT", "DESCRIBE", "ASK", context=_context
            )
            == "PREFIX"
        ):
            PrefixDecl = self.PrefixDecl(R, _context)

    def BaseDecl(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "BaseDecl", [R])
        BASE = self._scan("BASE", context=_context)
        IRI_REF = self._scan("IRI_REF", context=_context)
        R.prefixes[None] = IRI_REF[1:-1]

    def PrefixDecl(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "PrefixDecl", [R])
        PREFIX = self._scan("PREFIX", context=_context)
        PNAME_NS = self._scan("PNAME_NS", context=_context)
        IRI_REF = self._scan("IRI_REF", context=_context)
        R.prefixes[PNAME_NS[:-1]] = IRI_REF[1:-1]

    def SelectQuery(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "SelectQuery", [R])
        SELECT = self._scan("SELECT", context=_context)
        R.type = "select"
        if self._peek(
            "DISTINCT", "REDUCED", "STAR", "VAR1", "VAR2", context=_context
        ) in ["DISTINCT", "REDUCED"]:
            _token = self._peek("DISTINCT", "REDUCED", context=_context)
            if _token == "DISTINCT":
                DISTINCT = self._scan("DISTINCT", context=_context)
                R.distinct = True
            else:  # == 'REDUCED'
                REDUCED = self._scan("REDUCED", context=_context)
                R.reduced = True
        _token = self._peek("STAR", "VAR1", "VAR2", context=_context)
        if _token != "STAR":
            Var = self.Var(R, _context)
            R.selected.append(Var)
            while (
                self._peek(
                    "VAR1",
                    "VAR2",
                    "FROM",
                    "WHERE",
                    "LBRACK",
                    "ORDER",
                    "LIMIT",
                    "OFFSET",
                    "ASC",
                    "DESC",
                    "LPAREN",
                    "STR",
                    "LANG",
                    "LANGMATCHES",
                    "DATATYPE",
                    "BOUND",
                    "SAMETERM",
                    "ISIRI",
                    "ISURI",
                    "ISBLANK",
                    "ISLITERAL",
                    "REGEX",
                    "IRI_REF",
                    "DOT",
                    "PNAME_NS",
                    "UNION",
                    "STAR",
                    "DIVIDE",
                    "RBRACK",
                    "FILTER",
                    "LSBRA",
                    "OPTIONAL",
                    "GRAPH",
                    "TRUE",
                    "FALSE",
                    "BLANK_NODE_LABEL",
                    "ANON",
                    "STRING_LITERAL1",
                    "STRING_LITERAL2",
                    "STRING_LITERAL_LONG1",
                    "STRING_LITERAL_LONG2",
                    "INTEGER",
                    "DECIMAL",
                    "DOUBLE",
                    "INTEGER_POSITIVE",
                    "DECIMAL_POSITIVE",
                    "DOUBLE_POSITIVE",
                    "INTEGER_NEGATIVE",
                    "DECIMAL_NEGATIVE",
                    "DOUBLE_NEGATIVE",
                    "PLUS",
                    "MINUS",
                    "EQUAL",
                    "NOTEQUAL",
                    "LESSER",
                    "GREATER",
                    "LESSEREQ",
                    "GREATEREQ",
                    "AND",
                    "OR",
                    "COMMA",
                    "RPAREN",
                    context=_context,
                )
                in ["VAR1", "VAR2"]
            ):
                Var = self.Var(R, _context)
                R.selected.append(Var)
        else:  # == 'STAR'
            STAR = self._scan("STAR", context=_context)
            R.selected.append("*")
        while (
            self._peek(
                "WHERE",
                "FROM",
                "LBRACK",
                "ORDER",
                "LIMIT",
                "OFFSET",
                "ASC",
                "DESC",
                "VAR1",
                "VAR2",
                "LPAREN",
                "STR",
                "LANG",
                "LANGMATCHES",
                "DATATYPE",
                "BOUND",
                "SAMETERM",
                "ISIRI",
                "ISURI",
                "ISBLANK",
                "ISLITERAL",
                "REGEX",
                "IRI_REF",
                "DOT",
                "PNAME_NS",
                "UNION",
                "STAR",
                "DIVIDE",
                "RBRACK",
                "FILTER",
                "LSBRA",
                "OPTIONAL",
                "GRAPH",
                "TRUE",
                "FALSE",
                "BLANK_NODE_LABEL",
                "ANON",
                "STRING_LITERAL1",
                "STRING_LITERAL2",
                "STRING_LITERAL_LONG1",
                "STRING_LITERAL_LONG2",
                "INTEGER",
                "DECIMAL",
                "DOUBLE",
                "INTEGER_POSITIVE",
                "DECIMAL_POSITIVE",
                "DOUBLE_POSITIVE",
                "INTEGER_NEGATIVE",
                "DECIMAL_NEGATIVE",
                "DOUBLE_NEGATIVE",
                "PLUS",
                "MINUS",
                "EQUAL",
                "NOTEQUAL",
                "LESSER",
                "GREATER",
                "LESSEREQ",
                "GREATEREQ",
                "AND",
                "OR",
                "COMMA",
                "RPAREN",
                context=_context,
            )
            == "FROM"
        ):
            DatasetClause = self.DatasetClause(R, _context)
        WhereClause = self.WhereClause(R, _context)
        SolutionModifier = self.SolutionModifier(R, _context)

    def ConstructQuery(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "ConstructQuery", [R])
        CONSTRUCT = self._scan("CONSTRUCT", context=_context)
        R.type = "construct"
        ConstructTemplate = self.ConstructTemplate(R, _context)
        while (
            self._peek(
                "WHERE",
                "FROM",
                "LBRACK",
                "ORDER",
                "LIMIT",
                "OFFSET",
                "ASC",
                "DESC",
                "VAR1",
                "VAR2",
                "LPAREN",
                "STR",
                "LANG",
                "LANGMATCHES",
                "DATATYPE",
                "BOUND",
                "SAMETERM",
                "ISIRI",
                "ISURI",
                "ISBLANK",
                "ISLITERAL",
                "REGEX",
                "IRI_REF",
                "DOT",
                "PNAME_NS",
                "UNION",
                "STAR",
                "DIVIDE",
                "RBRACK",
                "FILTER",
                "LSBRA",
                "OPTIONAL",
                "GRAPH",
                "TRUE",
                "FALSE",
                "BLANK_NODE_LABEL",
                "ANON",
                "STRING_LITERAL1",
                "STRING_LITERAL2",
                "STRING_LITERAL_LONG1",
                "STRING_LITERAL_LONG2",
                "INTEGER",
                "DECIMAL",
                "DOUBLE",
                "INTEGER_POSITIVE",
                "DECIMAL_POSITIVE",
                "DOUBLE_POSITIVE",
                "INTEGER_NEGATIVE",
                "DECIMAL_NEGATIVE",
                "DOUBLE_NEGATIVE",
                "PLUS",
                "MINUS",
                "EQUAL",
                "NOTEQUAL",
                "LESSER",
                "GREATER",
                "LESSEREQ",
                "GREATEREQ",
                "AND",
                "OR",
                "COMMA",
                "RPAREN",
                context=_context,
            )
            == "FROM"
        ):
            DatasetClause = self.DatasetClause(R, _context)
        WhereClause = self.WhereClause(R, _context)
        SolutionModifier = self.SolutionModifier(R, _context)

    def DescribeQuery(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "DescribeQuery", [R])
        DESCRIBE = self._scan("DESCRIBE", context=_context)
        _token = self._peek(
            "STAR", "VAR1", "VAR2", "IRI_REF", "PNAME_NS", context=_context
        )
        if _token != "STAR":
            while 1:
                VarOrIRIref = self.VarOrIRIref(R, _context)
                if (
                    self._peek(
                        "VAR1",
                        "VAR2",
                        "IRI_REF",
                        "PNAME_NS",
                        "LBRACK",
                        "FROM",
                        "WHERE",
                        "ORDER",
                        "LIMIT",
                        "OFFSET",
                        "ASC",
                        "DESC",
                        "LPAREN",
                        "LSBRA",
                        "STR",
                        "LANG",
                        "LANGMATCHES",
                        "DATATYPE",
                        "BOUND",
                        "SAMETERM",
                        "ISIRI",
                        "ISURI",
                        "ISBLANK",
                        "ISLITERAL",
                        "TRUE",
                        "FALSE",
                        "BLANK_NODE_LABEL",
                        "ANON",
                        "REGEX",
                        "DOT",
                        "STRING_LITERAL1",
                        "STRING_LITERAL2",
                        "STRING_LITERAL_LONG1",
                        "STRING_LITERAL_LONG2",
                        "INTEGER",
                        "DECIMAL",
                        "DOUBLE",
                        "INTEGER_POSITIVE",
                        "DECIMAL_POSITIVE",
                        "DOUBLE_POSITIVE",
                        "INTEGER_NEGATIVE",
                        "DECIMAL_NEGATIVE",
                        "DOUBLE_NEGATIVE",
                        "UNION",
                        "STAR",
                        "DIVIDE",
                        "RBRACK",
                        "FILTER",
                        "OPTIONAL",
                        "GRAPH",
                        "PLUS",
                        "MINUS",
                        "EQUAL",
                        "NOTEQUAL",
                        "LESSER",
                        "GREATER",
                        "LESSEREQ",
                        "GREATEREQ",
                        "AND",
                        "OR",
                        "COMMA",
                        "RPAREN",
                        context=_context,
                    )
                    not in ["VAR1", "VAR2", "IRI_REF", "PNAME_NS"]
                ):
                    break
        else:  # == 'STAR'
            STAR = self._scan("STAR", context=_context)
            R.selected.append("*")
        while (
            self._peek(
                "WHERE",
                "FROM",
                "LBRACK",
                "ORDER",
                "LIMIT",
                "OFFSET",
                "ASC",
                "DESC",
                "VAR1",
                "VAR2",
                "LPAREN",
                "STR",
                "LANG",
                "LANGMATCHES",
                "DATATYPE",
                "BOUND",
                "SAMETERM",
                "ISIRI",
                "ISURI",
                "ISBLANK",
                "ISLITERAL",
                "REGEX",
                "IRI_REF",
                "DOT",
                "PNAME_NS",
                "UNION",
                "STAR",
                "DIVIDE",
                "RBRACK",
                "FILTER",
                "LSBRA",
                "OPTIONAL",
                "GRAPH",
                "TRUE",
                "FALSE",
                "BLANK_NODE_LABEL",
                "ANON",
                "STRING_LITERAL1",
                "STRING_LITERAL2",
                "STRING_LITERAL_LONG1",
                "STRING_LITERAL_LONG2",
                "INTEGER",
                "DECIMAL",
                "DOUBLE",
                "INTEGER_POSITIVE",
                "DECIMAL_POSITIVE",
                "DOUBLE_POSITIVE",
                "INTEGER_NEGATIVE",
                "DECIMAL_NEGATIVE",
                "DOUBLE_NEGATIVE",
                "PLUS",
                "MINUS",
                "EQUAL",
                "NOTEQUAL",
                "LESSER",
                "GREATER",
                "LESSEREQ",
                "GREATEREQ",
                "AND",
                "OR",
                "COMMA",
                "RPAREN",
                context=_context,
            )
            == "FROM"
        ):
            DatasetClause = self.DatasetClause(R, _context)
        if (
            self._peek(
                "WHERE",
                "LBRACK",
                "ORDER",
                "LIMIT",
                "OFFSET",
                "ASC",
                "DESC",
                "VAR1",
                "VAR2",
                "LPAREN",
                "STR",
                "LANG",
                "LANGMATCHES",
                "DATATYPE",
                "BOUND",
                "SAMETERM",
                "ISIRI",
                "ISURI",
                "ISBLANK",
                "ISLITERAL",
                "REGEX",
                "IRI_REF",
                "DOT",
                "PNAME_NS",
                "UNION",
                "STAR",
                "DIVIDE",
                "RBRACK",
                "FILTER",
                "LSBRA",
                "OPTIONAL",
                "GRAPH",
                "TRUE",
                "FALSE",
                "BLANK_NODE_LABEL",
                "ANON",
                "STRING_LITERAL1",
                "STRING_LITERAL2",
                "STRING_LITERAL_LONG1",
                "STRING_LITERAL_LONG2",
                "INTEGER",
                "DECIMAL",
                "DOUBLE",
                "INTEGER_POSITIVE",
                "DECIMAL_POSITIVE",
                "DOUBLE_POSITIVE",
                "INTEGER_NEGATIVE",
                "DECIMAL_NEGATIVE",
                "DOUBLE_NEGATIVE",
                "PLUS",
                "MINUS",
                "EQUAL",
                "NOTEQUAL",
                "LESSER",
                "GREATER",
                "LESSEREQ",
                "GREATEREQ",
                "AND",
                "OR",
                "COMMA",
                "RPAREN",
                context=_context,
            )
            in ["WHERE", "LBRACK"]
        ):
            WhereClause = self.WhereClause(R, _context)
        SolutionModifier = self.SolutionModifier(R, _context)

    def AskQuery(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "AskQuery", [R])
        ASK = self._scan("ASK", context=_context)
        R.type = "ask"
        while (
            self._peek(
                "WHERE",
                "FROM",
                "LBRACK",
                "ORDER",
                "LIMIT",
                "OFFSET",
                "ASC",
                "DESC",
                "VAR1",
                "VAR2",
                "LPAREN",
                "STR",
                "LANG",
                "LANGMATCHES",
                "DATATYPE",
                "BOUND",
                "SAMETERM",
                "ISIRI",
                "ISURI",
                "ISBLANK",
                "ISLITERAL",
                "REGEX",
                "IRI_REF",
                "DOT",
                "PNAME_NS",
                "UNION",
                "STAR",
                "DIVIDE",
                "RBRACK",
                "FILTER",
                "LSBRA",
                "OPTIONAL",
                "GRAPH",
                "TRUE",
                "FALSE",
                "BLANK_NODE_LABEL",
                "ANON",
                "STRING_LITERAL1",
                "STRING_LITERAL2",
                "STRING_LITERAL_LONG1",
                "STRING_LITERAL_LONG2",
                "INTEGER",
                "DECIMAL",
                "DOUBLE",
                "INTEGER_POSITIVE",
                "DECIMAL_POSITIVE",
                "DOUBLE_POSITIVE",
                "INTEGER_NEGATIVE",
                "DECIMAL_NEGATIVE",
                "DOUBLE_NEGATIVE",
                "PLUS",
                "MINUS",
                "EQUAL",
                "NOTEQUAL",
                "LESSER",
                "GREATER",
                "LESSEREQ",
                "GREATEREQ",
                "AND",
                "OR",
                "COMMA",
                "RPAREN",
                context=_context,
            )
            == "FROM"
        ):
            DatasetClause = self.DatasetClause(R, _context)
        WhereClause = self.WhereClause(R, _context)

    def DatasetClause(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "DatasetClause", [R])
        FROM = self._scan("FROM", context=_context)
        _token = self._peek("NAMED", "IRI_REF", "PNAME_NS", context=_context)
        if _token != "NAMED":
            DefaultGraphClause = self.DefaultGraphClause(R, _context)
        else:  # == 'NAMED'
            NamedGraphClause = self.NamedGraphClause(R, _context)

    def DefaultGraphClause(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "DefaultGraphClause", [R])
        SourceSelector = self.SourceSelector(R, _context)
        return SourceSelector

    def NamedGraphClause(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "NamedGraphClause", [R])
        NAMED = self._scan("NAMED", context=_context)
        SourceSelector = self.SourceSelector(R, _context)
        return SourceSelector

    def SourceSelector(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "SourceSelector", [R])
        IRIref = self.IRIref(R, _context)
        return IRIref

    def WhereClause(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "WhereClause", [R])
        if self._peek("WHERE", "LBRACK", context=_context) == "WHERE":
            WHERE = self._scan("WHERE", context=_context)
        GroupGraphPattern = self.GroupGraphPattern(R, _context)
        R.where = GroupGraphPattern

    def SolutionModifier(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "SolutionModifier", [R])
        if (
            self._peek(
                "ORDER",
                "LIMIT",
                "OFFSET",
                "ASC",
                "DESC",
                "VAR1",
                "VAR2",
                "LPAREN",
                "STR",
                "LANG",
                "LANGMATCHES",
                "DATATYPE",
                "BOUND",
                "SAMETERM",
                "ISIRI",
                "ISURI",
                "ISBLANK",
                "ISLITERAL",
                "REGEX",
                "IRI_REF",
                "DOT",
                "PNAME_NS",
                "UNION",
                "STAR",
                "DIVIDE",
                "RBRACK",
                "FILTER",
                "LSBRA",
                "OPTIONAL",
                "LBRACK",
                "GRAPH",
                "TRUE",
                "FALSE",
                "BLANK_NODE_LABEL",
                "ANON",
                "STRING_LITERAL1",
                "STRING_LITERAL2",
                "STRING_LITERAL_LONG1",
                "STRING_LITERAL_LONG2",
                "INTEGER",
                "DECIMAL",
                "DOUBLE",
                "INTEGER_POSITIVE",
                "DECIMAL_POSITIVE",
                "DOUBLE_POSITIVE",
                "INTEGER_NEGATIVE",
                "DECIMAL_NEGATIVE",
                "DOUBLE_NEGATIVE",
                "PLUS",
                "MINUS",
                "EQUAL",
                "NOTEQUAL",
                "LESSER",
                "GREATER",
                "LESSEREQ",
                "GREATEREQ",
                "AND",
                "OR",
                "COMMA",
                "RPAREN",
                context=_context,
            )
            == "ORDER"
        ):
            OrderClause = self.OrderClause(R, _context)
        if (
            self._peek(
                "LIMIT",
                "OFFSET",
                "ORDER",
                "ASC",
                "DESC",
                "VAR1",
                "VAR2",
                "LPAREN",
                "STR",
                "LANG",
                "LANGMATCHES",
                "DATATYPE",
                "BOUND",
                "SAMETERM",
                "ISIRI",
                "ISURI",
                "ISBLANK",
                "ISLITERAL",
                "REGEX",
                "IRI_REF",
                "DOT",
                "PNAME_NS",
                "UNION",
                "STAR",
                "DIVIDE",
                "RBRACK",
                "FILTER",
                "LSBRA",
                "OPTIONAL",
                "LBRACK",
                "GRAPH",
                "TRUE",
                "FALSE",
                "BLANK_NODE_LABEL",
                "ANON",
                "STRING_LITERAL1",
                "STRING_LITERAL2",
                "STRING_LITERAL_LONG1",
                "STRING_LITERAL_LONG2",
                "INTEGER",
                "DECIMAL",
                "DOUBLE",
                "INTEGER_POSITIVE",
                "DECIMAL_POSITIVE",
                "DOUBLE_POSITIVE",
                "INTEGER_NEGATIVE",
                "DECIMAL_NEGATIVE",
                "DOUBLE_NEGATIVE",
                "PLUS",
                "MINUS",
                "EQUAL",
                "NOTEQUAL",
                "LESSER",
                "GREATER",
                "LESSEREQ",
                "GREATEREQ",
                "AND",
                "OR",
                "COMMA",
                "RPAREN",
                context=_context,
            )
            in ["LIMIT", "OFFSET"]
        ):
            LimitOffsetClauses = self.LimitOffsetClauses(R, _context)

    def LimitOffsetClauses(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "LimitOffsetClauses", [R])
        _token = self._peek("LIMIT", "OFFSET", context=_context)
        if _token == "LIMIT":
            LimitClause = self.LimitClause(R, _context)
            if (
                self._peek(
                    "OFFSET",
                    "LIMIT",
                    "ORDER",
                    "ASC",
                    "DESC",
                    "VAR1",
                    "VAR2",
                    "LPAREN",
                    "STR",
                    "LANG",
                    "LANGMATCHES",
                    "DATATYPE",
                    "BOUND",
                    "SAMETERM",
                    "ISIRI",
                    "ISURI",
                    "ISBLANK",
                    "ISLITERAL",
                    "REGEX",
                    "IRI_REF",
                    "DOT",
                    "PNAME_NS",
                    "UNION",
                    "STAR",
                    "DIVIDE",
                    "RBRACK",
                    "FILTER",
                    "LSBRA",
                    "OPTIONAL",
                    "LBRACK",
                    "GRAPH",
                    "TRUE",
                    "FALSE",
                    "BLANK_NODE_LABEL",
                    "ANON",
                    "STRING_LITERAL1",
                    "STRING_LITERAL2",
                    "STRING_LITERAL_LONG1",
                    "STRING_LITERAL_LONG2",
                    "INTEGER",
                    "DECIMAL",
                    "DOUBLE",
                    "INTEGER_POSITIVE",
                    "DECIMAL_POSITIVE",
                    "DOUBLE_POSITIVE",
                    "INTEGER_NEGATIVE",
                    "DECIMAL_NEGATIVE",
                    "DOUBLE_NEGATIVE",
                    "PLUS",
                    "MINUS",
                    "EQUAL",
                    "NOTEQUAL",
                    "LESSER",
                    "GREATER",
                    "LESSEREQ",
                    "GREATEREQ",
                    "AND",
                    "OR",
                    "COMMA",
                    "RPAREN",
                    context=_context,
                )
                == "OFFSET"
            ):
                OffsetClause = self.OffsetClause(R, _context)
        else:  # == 'OFFSET'
            OffsetClause = self.OffsetClause(R, _context)
            if (
                self._peek(
                    "LIMIT",
                    "OFFSET",
                    "ORDER",
                    "ASC",
                    "DESC",
                    "VAR1",
                    "VAR2",
                    "LPAREN",
                    "STR",
                    "LANG",
                    "LANGMATCHES",
                    "DATATYPE",
                    "BOUND",
                    "SAMETERM",
                    "ISIRI",
                    "ISURI",
                    "ISBLANK",
                    "ISLITERAL",
                    "REGEX",
                    "IRI_REF",
                    "DOT",
                    "PNAME_NS",
                    "UNION",
                    "STAR",
                    "DIVIDE",
                    "RBRACK",
                    "FILTER",
                    "LSBRA",
                    "OPTIONAL",
                    "LBRACK",
                    "GRAPH",
                    "TRUE",
                    "FALSE",
                    "BLANK_NODE_LABEL",
                    "ANON",
                    "STRING_LITERAL1",
                    "STRING_LITERAL2",
                    "STRING_LITERAL_LONG1",
                    "STRING_LITERAL_LONG2",
                    "INTEGER",
                    "DECIMAL",
                    "DOUBLE",
                    "INTEGER_POSITIVE",
                    "DECIMAL_POSITIVE",
                    "DOUBLE_POSITIVE",
                    "INTEGER_NEGATIVE",
                    "DECIMAL_NEGATIVE",
                    "DOUBLE_NEGATIVE",
                    "PLUS",
                    "MINUS",
                    "EQUAL",
                    "NOTEQUAL",
                    "LESSER",
                    "GREATER",
                    "LESSEREQ",
                    "GREATEREQ",
                    "AND",
                    "OR",
                    "COMMA",
                    "RPAREN",
                    context=_context,
                )
                == "LIMIT"
            ):
                LimitClause = self.LimitClause(R, _context)

    def OrderClause(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "OrderClause", [R])
        ORDER = self._scan("ORDER", context=_context)
        BY = self._scan("BY", context=_context)
        while 1:
            OrderCondition = self.OrderCondition(R, _context)
            if self._peek(
                "ASC",
                "DESC",
                "VAR1",
                "VAR2",
                "LPAREN",
                "STR",
                "LANG",
                "LANGMATCHES",
                "DATATYPE",
                "BOUND",
                "SAMETERM",
                "ISIRI",
                "ISURI",
                "ISBLANK",
                "ISLITERAL",
                "REGEX",
                "IRI_REF",
                "PNAME_NS",
                "LIMIT",
                "OFFSET",
                "DOT",
                "UNION",
                "STAR",
                "DIVIDE",
                "ORDER",
                "RBRACK",
                "FILTER",
                "LSBRA",
                "OPTIONAL",
                "LBRACK",
                "GRAPH",
                "TRUE",
                "FALSE",
                "BLANK_NODE_LABEL",
                "ANON",
                "STRING_LITERAL1",
                "STRING_LITERAL2",
                "STRING_LITERAL_LONG1",
                "STRING_LITERAL_LONG2",
                "INTEGER",
                "DECIMAL",
                "DOUBLE",
                "INTEGER_POSITIVE",
                "DECIMAL_POSITIVE",
                "DOUBLE_POSITIVE",
                "INTEGER_NEGATIVE",
                "DECIMAL_NEGATIVE",
                "DOUBLE_NEGATIVE",
                "PLUS",
                "MINUS",
                "EQUAL",
                "NOTEQUAL",
                "LESSER",
                "GREATER",
                "LESSEREQ",
                "GREATEREQ",
                "AND",
                "OR",
                "COMMA",
                "RPAREN",
                context=_context,
            ) not in [
                "ASC",
                "DESC",
                "VAR1",
                "VAR2",
                "LPAREN",
                "STR",
                "LANG",
                "LANGMATCHES",
                "DATATYPE",
                "BOUND",
                "SAMETERM",
                "ISIRI",
                "ISURI",
                "ISBLANK",
                "ISLITERAL",
                "REGEX",
                "IRI_REF",
                "PNAME_NS",
            ]:
                break

    def OrderCondition(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "OrderCondition", [R])
        _token = self._peek(
            "ASC",
            "DESC",
            "VAR1",
            "VAR2",
            "LPAREN",
            "STR",
            "LANG",
            "LANGMATCHES",
            "DATATYPE",
            "BOUND",
            "SAMETERM",
            "ISIRI",
            "ISURI",
            "ISBLANK",
            "ISLITERAL",
            "REGEX",
            "IRI_REF",
            "PNAME_NS",
            context=_context,
        )
        if _token in ["ASC", "DESC"]:
            _token = self._peek("ASC", "DESC", context=_context)
            if _token == "ASC":
                ASC = self._scan("ASC", context=_context)
                asc_or_desc = "asc"
            else:  # == 'DESC'
                DESC = self._scan("DESC", context=_context)
                asc_or_desc = "desc"
            BrackettedExpression = self.BrackettedExpression(R, _context)
            R.orderby.append((BrackettedExpression, asc_or_desc))
        else:
            _token = self._peek(
                "VAR1",
                "VAR2",
                "LPAREN",
                "STR",
                "LANG",
                "LANGMATCHES",
                "DATATYPE",
                "BOUND",
                "SAMETERM",
                "ISIRI",
                "ISURI",
                "ISBLANK",
                "ISLITERAL",
                "REGEX",
                "IRI_REF",
                "PNAME_NS",
                context=_context,
            )
            if _token not in ["VAR1", "VAR2"]:
                Constraint = self.Constraint(R, _context)
            else:  # in ['VAR1', 'VAR2']
                Var = self.Var(R, _context)
                R.orderby.append((Var, "asc"))

    def LimitClause(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "LimitClause", [R])
        LIMIT = self._scan("LIMIT", context=_context)
        INTEGER = self._scan("INTEGER", context=_context)
        R.limit = int(INTEGER)

    def OffsetClause(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "OffsetClause", [R])
        OFFSET = self._scan("OFFSET", context=_context)
        INTEGER = self._scan("INTEGER", context=_context)
        R.offset = int(INTEGER)

    def GroupGraphPattern(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "GroupGraphPattern", [R])
        LBRACK = self._scan("LBRACK", context=_context)
        triples = []
        if (
            self._peek(
                "RBRACK",
                "FILTER",
                "OPTIONAL",
                "LBRACK",
                "GRAPH",
                "VAR1",
                "VAR2",
                "LPAREN",
                "LSBRA",
                "IRI_REF",
                "TRUE",
                "FALSE",
                "BLANK_NODE_LABEL",
                "ANON",
                "PNAME_NS",
                "STRING_LITERAL1",
                "STRING_LITERAL2",
                "STRING_LITERAL_LONG1",
                "STRING_LITERAL_LONG2",
                "INTEGER",
                "DECIMAL",
                "DOUBLE",
                "INTEGER_POSITIVE",
                "DECIMAL_POSITIVE",
                "DOUBLE_POSITIVE",
                "INTEGER_NEGATIVE",
                "DECIMAL_NEGATIVE",
                "DOUBLE_NEGATIVE",
                context=_context,
            )
            not in ["RBRACK", "FILTER", "OPTIONAL", "LBRACK", "GRAPH"]
        ):
            TriplesBlock = self.TriplesBlock(R, _context)
        triples.extend(locals().get("TriplesBlock", []))
        while (
            self._peek(
                "RBRACK", "FILTER", "OPTIONAL", "LBRACK", "GRAPH", context=_context
            )
            != "RBRACK"
        ):
            _token = self._peek(
                "FILTER", "OPTIONAL", "LBRACK", "GRAPH", context=_context
            )
            if _token != "FILTER":
                GraphPatternNotTriples = self.GraphPatternNotTriples(R, _context)
            else:  # == 'FILTER'
                Filter = self.Filter(R, _context)
            if (
                self._peek(
                    "DOT",
                    "RBRACK",
                    "FILTER",
                    "VAR1",
                    "VAR2",
                    "LPAREN",
                    "LSBRA",
                    "OPTIONAL",
                    "LBRACK",
                    "GRAPH",
                    "IRI_REF",
                    "TRUE",
                    "FALSE",
                    "BLANK_NODE_LABEL",
                    "ANON",
                    "PNAME_NS",
                    "STRING_LITERAL1",
                    "STRING_LITERAL2",
                    "STRING_LITERAL_LONG1",
                    "STRING_LITERAL_LONG2",
                    "INTEGER",
                    "DECIMAL",
                    "DOUBLE",
                    "INTEGER_POSITIVE",
                    "DECIMAL_POSITIVE",
                    "DOUBLE_POSITIVE",
                    "INTEGER_NEGATIVE",
                    "DECIMAL_NEGATIVE",
                    "DOUBLE_NEGATIVE",
                    context=_context,
                )
                == "DOT"
            ):
                DOT = self._scan("DOT", context=_context)
            if (
                self._peek(
                    "RBRACK",
                    "FILTER",
                    "VAR1",
                    "VAR2",
                    "LPAREN",
                    "LSBRA",
                    "OPTIONAL",
                    "LBRACK",
                    "GRAPH",
                    "IRI_REF",
                    "TRUE",
                    "FALSE",
                    "BLANK_NODE_LABEL",
                    "ANON",
                    "PNAME_NS",
                    "STRING_LITERAL1",
                    "STRING_LITERAL2",
                    "STRING_LITERAL_LONG1",
                    "STRING_LITERAL_LONG2",
                    "INTEGER",
                    "DECIMAL",
                    "DOUBLE",
                    "INTEGER_POSITIVE",
                    "DECIMAL_POSITIVE",
                    "DOUBLE_POSITIVE",
                    "INTEGER_NEGATIVE",
                    "DECIMAL_NEGATIVE",
                    "DOUBLE_NEGATIVE",
                    context=_context,
                )
                not in ["RBRACK", "FILTER", "OPTIONAL", "LBRACK", "GRAPH"]
            ):
                TriplesBlock = self.TriplesBlock(R, _context)
            triples.extend(locals().get("TriplesBlock", []))
        RBRACK = self._scan("RBRACK", context=_context)
        return triples

    def TriplesBlock(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "TriplesBlock", [R])
        TriplesSameSubject = self.TriplesSameSubject(R, _context)
        triples = TriplesSameSubject
        if (
            self._peek(
                "DOT",
                "RBRACK",
                "FILTER",
                "OPTIONAL",
                "LBRACK",
                "GRAPH",
                context=_context,
            )
            == "DOT"
        ):
            DOT = self._scan("DOT", context=_context)
            if (
                self._peek(
                    "VAR1",
                    "VAR2",
                    "LPAREN",
                    "LSBRA",
                    "RBRACK",
                    "FILTER",
                    "IRI_REF",
                    "TRUE",
                    "FALSE",
                    "BLANK_NODE_LABEL",
                    "ANON",
                    "OPTIONAL",
                    "LBRACK",
                    "GRAPH",
                    "PNAME_NS",
                    "STRING_LITERAL1",
                    "STRING_LITERAL2",
                    "STRING_LITERAL_LONG1",
                    "STRING_LITERAL_LONG2",
                    "INTEGER",
                    "DECIMAL",
                    "DOUBLE",
                    "INTEGER_POSITIVE",
                    "DECIMAL_POSITIVE",
                    "DOUBLE_POSITIVE",
                    "INTEGER_NEGATIVE",
                    "DECIMAL_NEGATIVE",
                    "DOUBLE_NEGATIVE",
                    context=_context,
                )
                not in ["RBRACK", "FILTER", "OPTIONAL", "LBRACK", "GRAPH"]
            ):
                TriplesBlock = self.TriplesBlock(R, _context)
            triples.extend(locals().get("TriplesBlock", []))
        return triples

    def GraphPatternNotTriples(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "GraphPatternNotTriples", [R])
        _token = self._peek("OPTIONAL", "LBRACK", "GRAPH", context=_context)
        if _token == "OPTIONAL":
            OptionalGraphPattern = self.OptionalGraphPattern(R, _context)
        elif _token == "LBRACK":
            GroupOrUnionGraphPattern = self.GroupOrUnionGraphPattern(R, _context)
        else:  # == 'GRAPH'
            GraphGraphPattern = self.GraphGraphPattern(R, _context)

    def OptionalGraphPattern(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "OptionalGraphPattern", [R])
        OPTIONAL = self._scan("OPTIONAL", context=_context)
        GroupGraphPattern = self.GroupGraphPattern(R, _context)

    def GraphGraphPattern(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "GraphGraphPattern", [R])
        GRAPH = self._scan("GRAPH", context=_context)
        VarOrIRIref = self.VarOrIRIref(R, _context)
        GroupGraphPattern = self.GroupGraphPattern(R, _context)

    def GroupOrUnionGraphPattern(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "GroupOrUnionGraphPattern", [R])
        GroupGraphPattern = self.GroupGraphPattern(R, _context)
        while (
            self._peek(
                "UNION",
                "DOT",
                "ORDER",
                "LIMIT",
                "OFFSET",
                "ASC",
                "DESC",
                "RBRACK",
                "FILTER",
                "VAR1",
                "VAR2",
                "LPAREN",
                "LSBRA",
                "OPTIONAL",
                "LBRACK",
                "GRAPH",
                "IRI_REF",
                "TRUE",
                "FALSE",
                "BLANK_NODE_LABEL",
                "ANON",
                "STR",
                "LANG",
                "LANGMATCHES",
                "DATATYPE",
                "BOUND",
                "SAMETERM",
                "ISIRI",
                "ISURI",
                "ISBLANK",
                "ISLITERAL",
                "PNAME_NS",
                "STRING_LITERAL1",
                "STRING_LITERAL2",
                "STRING_LITERAL_LONG1",
                "STRING_LITERAL_LONG2",
                "INTEGER",
                "DECIMAL",
                "DOUBLE",
                "INTEGER_POSITIVE",
                "DECIMAL_POSITIVE",
                "DOUBLE_POSITIVE",
                "INTEGER_NEGATIVE",
                "DECIMAL_NEGATIVE",
                "DOUBLE_NEGATIVE",
                "REGEX",
                "STAR",
                "DIVIDE",
                "PLUS",
                "MINUS",
                "EQUAL",
                "NOTEQUAL",
                "LESSER",
                "GREATER",
                "LESSEREQ",
                "GREATEREQ",
                "AND",
                "OR",
                "COMMA",
                "RPAREN",
                context=_context,
            )
            == "UNION"
        ):
            UNION = self._scan("UNION", context=_context)
            GroupGraphPattern = self.GroupGraphPattern(R, _context)

    def Filter(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "Filter", [R])
        FILTER = self._scan("FILTER", context=_context)
        Constraint = self.Constraint(R, _context)

    def Constraint(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "Constraint", [R])
        _token = self._peek(
            "LPAREN",
            "STR",
            "LANG",
            "LANGMATCHES",
            "DATATYPE",
            "BOUND",
            "SAMETERM",
            "ISIRI",
            "ISURI",
            "ISBLANK",
            "ISLITERAL",
            "REGEX",
            "IRI_REF",
            "PNAME_NS",
            context=_context,
        )
        if _token == "LPAREN":
            BrackettedExpression = self.BrackettedExpression(R, _context)
        elif _token not in ["IRI_REF", "PNAME_NS"]:
            BuiltInCall = self.BuiltInCall(R, _context)
        else:  # in ['IRI_REF', 'PNAME_NS']
            FunctionCall = self.FunctionCall(R, _context)

    def FunctionCall(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "FunctionCall", [R])
        IRIref = self.IRIref(R, _context)
        ArgList = self.ArgList(R, _context)

    def ArgList(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "ArgList", [R])
        _token = self._peek("NIL", "LPAREN", context=_context)
        if _token == "NIL":
            NIL = self._scan("NIL", context=_context)
        else:  # == 'LPAREN'
            LPAREN = self._scan("LPAREN", context=_context)
            Expression = self.Expression(R, _context)
            while self._peek("RPAREN", "COMMA", context=_context) == "COMMA":
                COMMA = self._scan("COMMA", context=_context)
                Expression = self.Expression(R, _context)
            RPAREN = self._scan("RPAREN", context=_context)

    def ConstructTemplate(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "ConstructTemplate", [R])
        LBRACK = self._scan("LBRACK", context=_context)
        if (
            self._peek(
                "RBRACK",
                "VAR1",
                "VAR2",
                "LPAREN",
                "LSBRA",
                "IRI_REF",
                "TRUE",
                "FALSE",
                "BLANK_NODE_LABEL",
                "ANON",
                "PNAME_NS",
                "STRING_LITERAL1",
                "STRING_LITERAL2",
                "STRING_LITERAL_LONG1",
                "STRING_LITERAL_LONG2",
                "INTEGER",
                "DECIMAL",
                "DOUBLE",
                "INTEGER_POSITIVE",
                "DECIMAL_POSITIVE",
                "DOUBLE_POSITIVE",
                "INTEGER_NEGATIVE",
                "DECIMAL_NEGATIVE",
                "DOUBLE_NEGATIVE",
                context=_context,
            )
            != "RBRACK"
        ):
            ConstructTriples = self.ConstructTriples(R, _context)
        RBRACK = self._scan("RBRACK", context=_context)

    def ConstructTriples(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "ConstructTriples", [R])
        TriplesSameSubject = self.TriplesSameSubject(R, _context)
        if self._peek("DOT", "RBRACK", context=_context) == "DOT":
            DOT = self._scan("DOT", context=_context)
            if (
                self._peek(
                    "RBRACK",
                    "VAR1",
                    "VAR2",
                    "LPAREN",
                    "LSBRA",
                    "IRI_REF",
                    "TRUE",
                    "FALSE",
                    "BLANK_NODE_LABEL",
                    "ANON",
                    "PNAME_NS",
                    "STRING_LITERAL1",
                    "STRING_LITERAL2",
                    "STRING_LITERAL_LONG1",
                    "STRING_LITERAL_LONG2",
                    "INTEGER",
                    "DECIMAL",
                    "DOUBLE",
                    "INTEGER_POSITIVE",
                    "DECIMAL_POSITIVE",
                    "DOUBLE_POSITIVE",
                    "INTEGER_NEGATIVE",
                    "DECIMAL_NEGATIVE",
                    "DOUBLE_NEGATIVE",
                    context=_context,
                )
                != "RBRACK"
            ):
                ConstructTriples = self.ConstructTriples(R, _context)

    def TriplesSameSubject(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "TriplesSameSubject", [R])
        _token = self._peek(
            "VAR1",
            "VAR2",
            "LPAREN",
            "LSBRA",
            "IRI_REF",
            "TRUE",
            "FALSE",
            "BLANK_NODE_LABEL",
            "ANON",
            "PNAME_NS",
            "STRING_LITERAL1",
            "STRING_LITERAL2",
            "STRING_LITERAL_LONG1",
            "STRING_LITERAL_LONG2",
            "INTEGER",
            "DECIMAL",
            "DOUBLE",
            "INTEGER_POSITIVE",
            "DECIMAL_POSITIVE",
            "DOUBLE_POSITIVE",
            "INTEGER_NEGATIVE",
            "DECIMAL_NEGATIVE",
            "DOUBLE_NEGATIVE",
            context=_context,
        )
        if _token not in ["LPAREN", "LSBRA"]:
            VarOrTerm = self.VarOrTerm(R, _context)
            PropertyListNotEmpty = self.PropertyListNotEmpty(R, _context)
            return [(VarOrTerm, p, o) for p, o in PropertyListNotEmpty]
        else:  # in ['LPAREN', 'LSBRA']
            TriplesNode = self.TriplesNode(R, _context)
            PropertyList = self.PropertyList(R, _context)
            return []

    def PropertyListNotEmpty(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "PropertyListNotEmpty", [R])
        propertylist = []
        Verb = self.Verb(R, _context)
        ObjectList = self.ObjectList(R, _context)
        propertylist.extend((Verb, obj) for obj in ObjectList)
        while (
            self._peek(
                "SEMICOLON",
                "RSBRA",
                "DOT",
                "RBRACK",
                "FILTER",
                "OPTIONAL",
                "LBRACK",
                "GRAPH",
                context=_context,
            )
            == "SEMICOLON"
        ):
            SEMICOLON = self._scan("SEMICOLON", context=_context)
            if (
                self._peek(
                    "A",
                    "SEMICOLON",
                    "VAR1",
                    "VAR2",
                    "IRI_REF",
                    "PNAME_NS",
                    "RSBRA",
                    "DOT",
                    "RBRACK",
                    "FILTER",
                    "OPTIONAL",
                    "LBRACK",
                    "GRAPH",
                    context=_context,
                )
                in ["A", "VAR1", "VAR2", "IRI_REF", "PNAME_NS"]
            ):
                Verb = self.Verb(R, _context)
                ObjectList = self.ObjectList(R, _context)
                propertylist.extend((Verb, obj) for obj in ObjectList)
        return propertylist

    def PropertyList(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "PropertyList", [R])
        if (
            self._peek(
                "A",
                "RSBRA",
                "VAR1",
                "VAR2",
                "IRI_REF",
                "PNAME_NS",
                "DOT",
                "RBRACK",
                "FILTER",
                "OPTIONAL",
                "LBRACK",
                "GRAPH",
                context=_context,
            )
            in ["A", "VAR1", "VAR2", "IRI_REF", "PNAME_NS"]
        ):
            PropertyListNotEmpty = self.PropertyListNotEmpty(R, _context)
        return locals().get("PropertyListNotEmpty", [])

    def ObjectList(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "ObjectList", [R])
        objectlist = []
        Object = self.Object(R, _context)
        objectlist.append(Object)
        while (
            self._peek(
                "COMMA",
                "SEMICOLON",
                "RSBRA",
                "DOT",
                "RBRACK",
                "FILTER",
                "OPTIONAL",
                "LBRACK",
                "GRAPH",
                context=_context,
            )
            == "COMMA"
        ):
            COMMA = self._scan("COMMA", context=_context)
            Object = self.Object(R, _context)
            objectlist.append(Object)
        return objectlist

    def Object(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "Object", [R])
        GraphNode = self.GraphNode(R, _context)
        return GraphNode

    def Verb(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "Verb", [R])
        _token = self._peek(
            "A", "VAR1", "VAR2", "IRI_REF", "PNAME_NS", context=_context
        )
        if _token != "A":
            VarOrIRIref = self.VarOrIRIref(R, _context)
            return VarOrIRIref
        else:  # == 'A'
            A = self._scan("A", context=_context)
            return ("", "a")

    def TriplesNode(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "TriplesNode", [R])
        _token = self._peek("LPAREN", "LSBRA", context=_context)
        if _token == "LPAREN":
            Collection = self.Collection(R, _context)
            return Collection
        else:  # == 'LSBRA'
            BlankNodePropertyList = self.BlankNodePropertyList(R, _context)
            return BlankNodePropertyList

    def BlankNodePropertyList(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "BlankNodePropertyList", [R])
        LSBRA = self._scan("LSBRA", context=_context)
        PropertyListNotEmpty = self.PropertyListNotEmpty(R, _context)
        RSBRA = self._scan("RSBRA", context=_context)
        return PropertyListNotEmpty

    def Collection(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "Collection", [R])
        LPAREN = self._scan("LPAREN", context=_context)
        col = []
        while 1:
            GraphNode = self.GraphNode(R, _context)
            col.append(GraphNode)
            if self._peek(
                "LPAREN",
                "LSBRA",
                "VAR1",
                "VAR2",
                "IRI_REF",
                "TRUE",
                "FALSE",
                "BLANK_NODE_LABEL",
                "ANON",
                "PNAME_NS",
                "STRING_LITERAL1",
                "STRING_LITERAL2",
                "STRING_LITERAL_LONG1",
                "STRING_LITERAL_LONG2",
                "INTEGER",
                "DECIMAL",
                "DOUBLE",
                "INTEGER_POSITIVE",
                "DECIMAL_POSITIVE",
                "DOUBLE_POSITIVE",
                "INTEGER_NEGATIVE",
                "DECIMAL_NEGATIVE",
                "DOUBLE_NEGATIVE",
                "RPAREN",
                context=_context,
            ) not in [
                "LPAREN",
                "LSBRA",
                "VAR1",
                "VAR2",
                "IRI_REF",
                "TRUE",
                "FALSE",
                "BLANK_NODE_LABEL",
                "ANON",
                "PNAME_NS",
                "STRING_LITERAL1",
                "STRING_LITERAL2",
                "STRING_LITERAL_LONG1",
                "STRING_LITERAL_LONG2",
                "INTEGER",
                "DECIMAL",
                "DOUBLE",
                "INTEGER_POSITIVE",
                "DECIMAL_POSITIVE",
                "DOUBLE_POSITIVE",
                "INTEGER_NEGATIVE",
                "DECIMAL_NEGATIVE",
                "DOUBLE_NEGATIVE",
            ]:
                break
        RPAREN = self._scan("RPAREN", context=_context)
        return col

    def GraphNode(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "GraphNode", [R])
        _token = self._peek(
            "LPAREN",
            "LSBRA",
            "VAR1",
            "VAR2",
            "IRI_REF",
            "TRUE",
            "FALSE",
            "BLANK_NODE_LABEL",
            "ANON",
            "PNAME_NS",
            "STRING_LITERAL1",
            "STRING_LITERAL2",
            "STRING_LITERAL_LONG1",
            "STRING_LITERAL_LONG2",
            "INTEGER",
            "DECIMAL",
            "DOUBLE",
            "INTEGER_POSITIVE",
            "DECIMAL_POSITIVE",
            "DOUBLE_POSITIVE",
            "INTEGER_NEGATIVE",
            "DECIMAL_NEGATIVE",
            "DOUBLE_NEGATIVE",
            context=_context,
        )
        if _token not in ["LPAREN", "LSBRA"]:
            VarOrTerm = self.VarOrTerm(R, _context)
            return VarOrTerm
        else:  # in ['LPAREN', 'LSBRA']
            TriplesNode = self.TriplesNode(R, _context)
            return TriplesNode

    def VarOrTerm(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "VarOrTerm", [R])
        _token = self._peek(
            "VAR1",
            "VAR2",
            "IRI_REF",
            "TRUE",
            "FALSE",
            "BLANK_NODE_LABEL",
            "ANON",
            "PNAME_NS",
            "STRING_LITERAL1",
            "STRING_LITERAL2",
            "STRING_LITERAL_LONG1",
            "STRING_LITERAL_LONG2",
            "INTEGER",
            "DECIMAL",
            "DOUBLE",
            "INTEGER_POSITIVE",
            "DECIMAL_POSITIVE",
            "DOUBLE_POSITIVE",
            "INTEGER_NEGATIVE",
            "DECIMAL_NEGATIVE",
            "DOUBLE_NEGATIVE",
            context=_context,
        )
        if _token in ["VAR1", "VAR2"]:
            Var = self.Var(R, _context)
            return Var
        else:
            GraphTerm = self.GraphTerm(R, _context)
            return GraphTerm

    def VarOrIRIref(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "VarOrIRIref", [R])
        _token = self._peek("VAR1", "VAR2", "IRI_REF", "PNAME_NS", context=_context)
        if _token not in ["IRI_REF", "PNAME_NS"]:
            Var = self.Var(R, _context)
            return Var
        else:  # in ['IRI_REF', 'PNAME_NS']
            IRIref = self.IRIref(R, _context)
            return IRIref

    def Var(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "Var", [R])
        _token = self._peek("VAR1", "VAR2", context=_context)
        if _token == "VAR1":
            VAR1 = self._scan("VAR1", context=_context)
            return R.add_variable(VAR1[1:])
        else:  # == 'VAR2'
            VAR2 = self._scan("VAR2", context=_context)
            return R.add_variable(VAR2[1:])

    def GraphTerm(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "GraphTerm", [R])
        _token = self._peek(
            "IRI_REF",
            "TRUE",
            "FALSE",
            "BLANK_NODE_LABEL",
            "ANON",
            "PNAME_NS",
            "STRING_LITERAL1",
            "STRING_LITERAL2",
            "STRING_LITERAL_LONG1",
            "STRING_LITERAL_LONG2",
            "INTEGER",
            "DECIMAL",
            "DOUBLE",
            "INTEGER_POSITIVE",
            "DECIMAL_POSITIVE",
            "DOUBLE_POSITIVE",
            "INTEGER_NEGATIVE",
            "DECIMAL_NEGATIVE",
            "DOUBLE_NEGATIVE",
            context=_context,
        )
        if _token in ["IRI_REF", "PNAME_NS"]:
            IRIref = self.IRIref(R, _context)
            return IRIref
        elif _token in [
            "STRING_LITERAL1",
            "STRING_LITERAL2",
            "STRING_LITERAL_LONG1",
            "STRING_LITERAL_LONG2",
        ]:
            RDFLiteral = self.RDFLiteral(R, _context)
            return RDFLiteral
        elif _token not in ["TRUE", "FALSE", "BLANK_NODE_LABEL", "ANON"]:
            NumericLiteral = self.NumericLiteral(R, _context)
            return NumericLiteral
        elif _token not in ["BLANK_NODE_LABEL", "ANON"]:
            BooleanLiteral = self.BooleanLiteral(R, _context)
            return BooleanLiteral
        else:  # in ['BLANK_NODE_LABEL', 'ANON']
            BlankNode = self.BlankNode(R, _context)

    def Expression(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "Expression", [R])
        ConditionalOrExpression = self.ConditionalOrExpression(R, _context)
        return ConditionalOrExpression

    def ConditionalOrExpression(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "ConditionalOrExpression", [R])
        ConditionalAndExpression = self.ConditionalAndExpression(R, _context)
        ored_expr = ["or", ConditionalAndExpression]
        while self._peek("OR", "COMMA", "RPAREN", context=_context) == "OR":
            OR = self._scan("OR", context=_context)
            ConditionalAndExpression = self.ConditionalAndExpression(R, _context)
            ored_expr.append(ConditionalAndExpression)
        return simplify_expr(ored_expr)

    def ConditionalAndExpression(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "ConditionalAndExpression", [R])
        ValueLogical = self.ValueLogical(R, _context)
        values = ["and", ValueLogical]
        while self._peek("AND", "OR", "COMMA", "RPAREN", context=_context) == "AND":
            AND = self._scan("AND", context=_context)
            ValueLogical = self.ValueLogical(R, _context)
            values.append(ValueLogical)
        return simplify_expr(values)

    def ValueLogical(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "ValueLogical", [R])
        RelationalExpression = self.RelationalExpression(R, _context)
        return RelationalExpression

    def RelationalExpression(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "RelationalExpression", [R])
        NumericExpression = self.NumericExpression(R, _context)
        expr = NumericExpression
        if (
            self._peek(
                "EQUAL",
                "NOTEQUAL",
                "LESSER",
                "GREATER",
                "LESSEREQ",
                "GREATEREQ",
                "AND",
                "OR",
                "COMMA",
                "RPAREN",
                context=_context,
            )
            not in ["AND", "OR", "COMMA", "RPAREN"]
        ):
            _token = self._peek(
                "EQUAL",
                "NOTEQUAL",
                "LESSER",
                "GREATER",
                "LESSEREQ",
                "GREATEREQ",
                context=_context,
            )
            if _token == "EQUAL":
                EQUAL = self._scan("EQUAL", context=_context)
                NumericExpression = self.NumericExpression(R, _context)
                expr = ("=", expr, NumericExpression)
            elif _token == "NOTEQUAL":
                NOTEQUAL = self._scan("NOTEQUAL", context=_context)
                NumericExpression = self.NumericExpression(R, _context)
                expr = ("!=", expr, NumericExpression)
            elif _token == "LESSER":
                LESSER = self._scan("LESSER", context=_context)
                NumericExpression = self.NumericExpression(R, _context)
                expr = ("<", expr, NumericExpression)
            elif _token == "GREATER":
                GREATER = self._scan("GREATER", context=_context)
                NumericExpression = self.NumericExpression(R, _context)
                expr = (">", expr, NumericExpression)
            elif _token == "LESSEREQ":
                LESSEREQ = self._scan("LESSEREQ", context=_context)
                NumericExpression = self.NumericExpression(R, _context)
                expr = ("<=", expr, NumericExpression)
            else:  # == 'GREATEREQ'
                GREATEREQ = self._scan("GREATEREQ", context=_context)
                NumericExpression = self.NumericExpression(R, _context)
                expr = (">=", expr, NumericExpression)
        return expr

    def NumericExpression(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "NumericExpression", [R])
        AdditiveExpression = self.AdditiveExpression(R, _context)
        return AdditiveExpression

    def AdditiveExpression(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "AdditiveExpression", [R])
        MultiplicativeExpression = self.MultiplicativeExpression(R, _context)
        expr = MultiplicativeExpression
        while self._peek(
            "PLUS",
            "MINUS",
            "INTEGER_POSITIVE",
            "DECIMAL_POSITIVE",
            "DOUBLE_POSITIVE",
            "INTEGER_NEGATIVE",
            "DECIMAL_NEGATIVE",
            "DOUBLE_NEGATIVE",
            "EQUAL",
            "NOTEQUAL",
            "LESSER",
            "GREATER",
            "LESSEREQ",
            "GREATEREQ",
            "AND",
            "OR",
            "COMMA",
            "RPAREN",
            context=_context,
        ) in [
            "PLUS",
            "MINUS",
            "INTEGER_POSITIVE",
            "DECIMAL_POSITIVE",
            "DOUBLE_POSITIVE",
            "INTEGER_NEGATIVE",
            "DECIMAL_NEGATIVE",
            "DOUBLE_NEGATIVE",
        ]:
            _token = self._peek(
                "PLUS",
                "MINUS",
                "INTEGER_POSITIVE",
                "DECIMAL_POSITIVE",
                "DOUBLE_POSITIVE",
                "INTEGER_NEGATIVE",
                "DECIMAL_NEGATIVE",
                "DOUBLE_NEGATIVE",
                context=_context,
            )
            if _token == "PLUS":
                PLUS = self._scan("PLUS", context=_context)
                MultiplicativeExpression = self.MultiplicativeExpression(R, _context)
                expr = ("+", expr, MultiplicativeExpression)
            elif _token == "MINUS":
                MINUS = self._scan("MINUS", context=_context)
                MultiplicativeExpression = self.MultiplicativeExpression(R, _context)
                expr = ("-", expr, MultiplicativeExpression)
            elif _token not in [
                "INTEGER_NEGATIVE",
                "DECIMAL_NEGATIVE",
                "DOUBLE_NEGATIVE",
            ]:
                NumericLiteralPositive = self.NumericLiteralPositive(_context)
                expr = (None, expr, NumericLiteralPositive)
            else:
                NumericLiteralNegative = self.NumericLiteralNegative(_context)
                expr = (None, expr, NumericLiteralPositive)
        return expr

    def MultiplicativeExpression(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "MultiplicativeExpression", [R])
        UnaryExpression = self.UnaryExpression(R, _context)
        expr = UnaryExpression
        while (
            self._peek(
                "STAR",
                "DIVIDE",
                "PLUS",
                "MINUS",
                "INTEGER_POSITIVE",
                "DECIMAL_POSITIVE",
                "DOUBLE_POSITIVE",
                "INTEGER_NEGATIVE",
                "DECIMAL_NEGATIVE",
                "DOUBLE_NEGATIVE",
                "EQUAL",
                "NOTEQUAL",
                "LESSER",
                "GREATER",
                "LESSEREQ",
                "GREATEREQ",
                "AND",
                "OR",
                "COMMA",
                "RPAREN",
                context=_context,
            )
            in ["STAR", "DIVIDE"]
        ):
            _token = self._peek("STAR", "DIVIDE", context=_context)
            if _token == "STAR":
                STAR = self._scan("STAR", context=_context)
                UnaryExpression = self.UnaryExpression(R, _context)
                expr = ("*", expr, UnaryExpression)
            else:  # == 'DIVIDE'
                DIVIDE = self._scan("DIVIDE", context=_context)
                UnaryExpression = self.UnaryExpression(R, _context)
                expr = ("/", expr, UnaryExpression)
        return expr

    def UnaryExpression(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "UnaryExpression", [R])
        _token = self._peek(
            "NOT",
            "PLUS",
            "MINUS",
            "VAR1",
            "VAR2",
            "LPAREN",
            "STR",
            "LANG",
            "LANGMATCHES",
            "DATATYPE",
            "BOUND",
            "SAMETERM",
            "ISIRI",
            "ISURI",
            "ISBLANK",
            "ISLITERAL",
            "TRUE",
            "FALSE",
            "REGEX",
            "IRI_REF",
            "STRING_LITERAL1",
            "STRING_LITERAL2",
            "STRING_LITERAL_LONG1",
            "STRING_LITERAL_LONG2",
            "INTEGER",
            "DECIMAL",
            "DOUBLE",
            "INTEGER_POSITIVE",
            "DECIMAL_POSITIVE",
            "DOUBLE_POSITIVE",
            "INTEGER_NEGATIVE",
            "DECIMAL_NEGATIVE",
            "DOUBLE_NEGATIVE",
            "PNAME_NS",
            context=_context,
        )
        if _token == "NOT":
            NOT = self._scan("NOT", context=_context)
            PrimaryExpression = self.PrimaryExpression(R, _context)
            return ("!", PrimaryExpression)
        elif _token == "PLUS":
            PLUS = self._scan("PLUS", context=_context)
            PrimaryExpression = self.PrimaryExpression(R, _context)
            return ("+", PrimaryExpression)
        elif _token == "MINUS":
            MINUS = self._scan("MINUS", context=_context)
            PrimaryExpression = self.PrimaryExpression(R, _context)
            return ("-", PrimaryExpression)
        else:
            PrimaryExpression = self.PrimaryExpression(R, _context)
            return PrimaryExpression

    def PrimaryExpression(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "PrimaryExpression", [R])
        _token = self._peek(
            "VAR1",
            "VAR2",
            "LPAREN",
            "STR",
            "LANG",
            "LANGMATCHES",
            "DATATYPE",
            "BOUND",
            "SAMETERM",
            "ISIRI",
            "ISURI",
            "ISBLANK",
            "ISLITERAL",
            "TRUE",
            "FALSE",
            "REGEX",
            "IRI_REF",
            "STRING_LITERAL1",
            "STRING_LITERAL2",
            "STRING_LITERAL_LONG1",
            "STRING_LITERAL_LONG2",
            "INTEGER",
            "DECIMAL",
            "DOUBLE",
            "INTEGER_POSITIVE",
            "DECIMAL_POSITIVE",
            "DOUBLE_POSITIVE",
            "INTEGER_NEGATIVE",
            "DECIMAL_NEGATIVE",
            "DOUBLE_NEGATIVE",
            "PNAME_NS",
            context=_context,
        )
        if _token == "LPAREN":
            BrackettedExpression = self.BrackettedExpression(R, _context)
            return BrackettedExpression
        elif _token not in [
            "VAR1",
            "VAR2",
            "TRUE",
            "FALSE",
            "IRI_REF",
            "STRING_LITERAL1",
            "STRING_LITERAL2",
            "STRING_LITERAL_LONG1",
            "STRING_LITERAL_LONG2",
            "INTEGER",
            "DECIMAL",
            "DOUBLE",
            "INTEGER_POSITIVE",
            "DECIMAL_POSITIVE",
            "DOUBLE_POSITIVE",
            "INTEGER_NEGATIVE",
            "DECIMAL_NEGATIVE",
            "DOUBLE_NEGATIVE",
            "PNAME_NS",
        ]:
            BuiltInCall = self.BuiltInCall(R, _context)
        elif _token in ["IRI_REF", "PNAME_NS"]:
            IRIrefOrFunction = self.IRIrefOrFunction(R, _context)
        elif _token in [
            "STRING_LITERAL1",
            "STRING_LITERAL2",
            "STRING_LITERAL_LONG1",
            "STRING_LITERAL_LONG2",
        ]:
            RDFLiteral = self.RDFLiteral(R, _context)
            return RDFLiteral
        elif _token not in ["VAR1", "VAR2", "TRUE", "FALSE"]:
            NumericLiteral = self.NumericLiteral(R, _context)
            return NumericLiteral
        elif _token not in ["VAR1", "VAR2"]:
            BooleanLiteral = self.BooleanLiteral(R, _context)
            return BooleanLiteral
        else:  # in ['VAR1', 'VAR2']
            Var = self.Var(R, _context)
            return Var

    def BrackettedExpression(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "BrackettedExpression", [R])
        LPAREN = self._scan("LPAREN", context=_context)
        Expression = self.Expression(R, _context)
        RPAREN = self._scan("RPAREN", context=_context)
        return Expression

    def BuiltInCall(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "BuiltInCall", [R])
        _token = self._peek(
            "STR",
            "LANG",
            "LANGMATCHES",
            "DATATYPE",
            "BOUND",
            "SAMETERM",
            "ISIRI",
            "ISURI",
            "ISBLANK",
            "ISLITERAL",
            "REGEX",
            context=_context,
        )
        if _token == "STR":
            STR = self._scan("STR", context=_context)
            LPAREN = self._scan("LPAREN", context=_context)
            Expression = self.Expression(R, _context)
            RPAREN = self._scan("RPAREN", context=_context)
        elif _token == "LANG":
            LANG = self._scan("LANG", context=_context)
            LPAREN = self._scan("LPAREN", context=_context)
            Expression = self.Expression(R, _context)
            RPAREN = self._scan("RPAREN", context=_context)
        elif _token == "LANGMATCHES":
            LANGMATCHES = self._scan("LANGMATCHES", context=_context)
            LPAREN = self._scan("LPAREN", context=_context)
            Expression = self.Expression(R, _context)
            COMMA = self._scan("COMMA", context=_context)
            Expression = self.Expression(R, _context)
            RPAREN = self._scan("RPAREN", context=_context)
        elif _token == "DATATYPE":
            DATATYPE = self._scan("DATATYPE", context=_context)
            LPAREN = self._scan("LPAREN", context=_context)
            Expression = self.Expression(R, _context)
            RPAREN = self._scan("RPAREN", context=_context)
        elif _token == "BOUND":
            BOUND = self._scan("BOUND", context=_context)
            LPAREN = self._scan("LPAREN", context=_context)
            Var = self.Var(_context)
            RPAREN = self._scan("RPAREN", context=_context)
        elif _token == "SAMETERM":
            SAMETERM = self._scan("SAMETERM", context=_context)
            LPAREN = self._scan("LPAREN", context=_context)
            Expression = self.Expression(R, _context)
            COMMA = self._scan("COMMA", context=_context)
            Expression = self.Expression(R, _context)
            RPAREN = self._scan("RPAREN", context=_context)
        elif _token == "ISIRI":
            ISIRI = self._scan("ISIRI", context=_context)
            LPAREN = self._scan("LPAREN", context=_context)
            Expression = self.Expression(R, _context)
            RPAREN = self._scan("RPAREN", context=_context)
        elif _token == "ISURI":
            ISURI = self._scan("ISURI", context=_context)
            LPAREN = self._scan("LPAREN", context=_context)
            Expression = self.Expression(R, _context)
            RPAREN = self._scan("RPAREN", context=_context)
        elif _token == "ISBLANK":
            ISBLANK = self._scan("ISBLANK", context=_context)
            LPAREN = self._scan("LPAREN", context=_context)
            Expression = self.Expression(R, _context)
            RPAREN = self._scan("RPAREN", context=_context)
        elif _token == "ISLITERAL":
            ISLITERAL = self._scan("ISLITERAL", context=_context)
            LPAREN = self._scan("LPAREN", context=_context)
            Expression = self.Expression(R, _context)
            RPAREN = self._scan("RPAREN", context=_context)
        else:  # == 'REGEX'
            RegexExpression = self.RegexExpression(R, _context)

    def RegexExpression(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "RegexExpression", [R])
        REGEX = self._scan("REGEX", context=_context)
        LPAREN = self._scan("LPAREN", context=_context)
        Expression = self.Expression(R, _context)
        COMMA = self._scan("COMMA", context=_context)
        Expression = self.Expression(R, _context)
        if self._peek("COMMA", "RPAREN", context=_context) == "COMMA":
            COMMA = self._scan("COMMA", context=_context)
            Expression = self.Expression(R, _context)
        RPAREN = self._scan("RPAREN", context=_context)

    def IRIrefOrFunction(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "IRIrefOrFunction", [R])
        IRIref = self.IRIref(R, _context)
        if (
            self._peek(
                "NIL",
                "LPAREN",
                "DOT",
                "ASC",
                "DESC",
                "STAR",
                "DIVIDE",
                "VAR1",
                "VAR2",
                "UNION",
                "STR",
                "LANG",
                "LANGMATCHES",
                "DATATYPE",
                "BOUND",
                "SAMETERM",
                "ISIRI",
                "ISURI",
                "ISBLANK",
                "ISLITERAL",
                "REGEX",
                "IRI_REF",
                "LIMIT",
                "OFFSET",
                "PNAME_NS",
                "RBRACK",
                "FILTER",
                "LSBRA",
                "PLUS",
                "MINUS",
                "OPTIONAL",
                "LBRACK",
                "GRAPH",
                "TRUE",
                "FALSE",
                "BLANK_NODE_LABEL",
                "ANON",
                "ORDER",
                "INTEGER_POSITIVE",
                "DECIMAL_POSITIVE",
                "DOUBLE_POSITIVE",
                "INTEGER_NEGATIVE",
                "DECIMAL_NEGATIVE",
                "DOUBLE_NEGATIVE",
                "STRING_LITERAL1",
                "STRING_LITERAL2",
                "STRING_LITERAL_LONG1",
                "STRING_LITERAL_LONG2",
                "INTEGER",
                "DECIMAL",
                "DOUBLE",
                "EQUAL",
                "NOTEQUAL",
                "LESSER",
                "GREATER",
                "LESSEREQ",
                "GREATEREQ",
                "AND",
                "OR",
                "COMMA",
                "RPAREN",
                context=_context,
            )
            in ["NIL", "LPAREN"]
        ):
            ArgList = self.ArgList(R, _context)

    def RDFLiteral(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "RDFLiteral", [R])
        String = self.String(_context)
        return String

    def NumericLiteral(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "NumericLiteral", [R])
        _token = self._peek(
            "INTEGER",
            "DECIMAL",
            "DOUBLE",
            "INTEGER_POSITIVE",
            "DECIMAL_POSITIVE",
            "DOUBLE_POSITIVE",
            "INTEGER_NEGATIVE",
            "DECIMAL_NEGATIVE",
            "DOUBLE_NEGATIVE",
            context=_context,
        )
        if _token in ["INTEGER", "DECIMAL", "DOUBLE"]:
            NumericLiteralUnsigned = self.NumericLiteralUnsigned(_context)
            return NumericLiteralUnsigned
        elif _token not in ["INTEGER_NEGATIVE", "DECIMAL_NEGATIVE", "DOUBLE_NEGATIVE"]:
            NumericLiteralPositive = self.NumericLiteralPositive(_context)
            return NumericLiteralPositive
        else:
            NumericLiteralNegative = self.NumericLiteralNegative(_context)
            return NumericLiteralNegative

    def NumericLiteralUnsigned(self, _parent=None):
        _context = self.Context(_parent, self._scanner, "NumericLiteralUnsigned", [])
        _token = self._peek("INTEGER", "DECIMAL", "DOUBLE", context=_context)
        if _token == "INTEGER":
            INTEGER = self._scan("INTEGER", context=_context)
            return INTEGER
        elif _token == "DECIMAL":
            DECIMAL = self._scan("DECIMAL", context=_context)
            return DECIMAL
        else:  # == 'DOUBLE'
            DOUBLE = self._scan("DOUBLE", context=_context)
            return DOUBLE

    def NumericLiteralPositive(self, _parent=None):
        _context = self.Context(_parent, self._scanner, "NumericLiteralPositive", [])
        _token = self._peek(
            "INTEGER_POSITIVE", "DECIMAL_POSITIVE", "DOUBLE_POSITIVE", context=_context
        )
        if _token == "INTEGER_POSITIVE":
            INTEGER_POSITIVE = self._scan("INTEGER_POSITIVE", context=_context)
            return INTEGER_POSITIVE
        elif _token == "DECIMAL_POSITIVE":
            DECIMAL_POSITIVE = self._scan("DECIMAL_POSITIVE", context=_context)
            return DECIMAL_POSITIVE
        else:  # == 'DOUBLE_POSITIVE'
            DOUBLE_POSITIVE = self._scan("DOUBLE_POSITIVE", context=_context)
            return DOUBLE_POSITIVE

    def NumericLiteralNegative(self, _parent=None):
        _context = self.Context(_parent, self._scanner, "NumericLiteralNegative", [])
        _token = self._peek(
            "INTEGER_NEGATIVE", "DECIMAL_NEGATIVE", "DOUBLE_NEGATIVE", context=_context
        )
        if _token == "INTEGER_NEGATIVE":
            INTEGER_NEGATIVE = self._scan("INTEGER_NEGATIVE", context=_context)
            return INTEGER_NEGATIVE
        elif _token == "DECIMAL_NEGATIVE":
            DECIMAL_NEGATIVE = self._scan("DECIMAL_NEGATIVE", context=_context)
            return DECIMAL_NEGATIVE
        else:  # == 'DOUBLE_NEGATIVE'
            DOUBLE_NEGATIVE = self._scan("DOUBLE_NEGATIVE", context=_context)
            return DOUBLE_NEGATIVE

    def BooleanLiteral(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "BooleanLiteral", [R])
        _token = self._peek("TRUE", "FALSE", context=_context)
        if _token == "TRUE":
            TRUE = self._scan("TRUE", context=_context)
            return SparqlLiteral(True)
        else:  # == 'FALSE'
            FALSE = self._scan("FALSE", context=_context)
            return SparqlLiteral(False)

    def String(self, _parent=None):
        _context = self.Context(_parent, self._scanner, "String", [])
        _token = self._peek(
            "STRING_LITERAL1",
            "STRING_LITERAL2",
            "STRING_LITERAL_LONG1",
            "STRING_LITERAL_LONG2",
            context=_context,
        )
        if _token == "STRING_LITERAL1":
            STRING_LITERAL1 = self._scan("STRING_LITERAL1", context=_context)
            return SparqlLiteral(STRING_LITERAL1[1:-1])
        elif _token == "STRING_LITERAL2":
            STRING_LITERAL2 = self._scan("STRING_LITERAL2", context=_context)
            return SparqlLiteral(STRING_LITERAL2[1:-1])
        elif _token == "STRING_LITERAL_LONG1":
            STRING_LITERAL_LONG1 = self._scan("STRING_LITERAL_LONG1", context=_context)
            return SparqlLiteral(STRING_LITERAL_LONG1[3:-3])
        else:  # == 'STRING_LITERAL_LONG2'
            STRING_LITERAL_LONG2 = self._scan("STRING_LITERAL_LONG2", context=_context)
            return SparqlLiteral(STRING_LITERAL_LONG2[3:-3])

    def IRIref(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "IRIref", [R])
        _token = self._peek("IRI_REF", "PNAME_NS", context=_context)
        if _token == "IRI_REF":
            IRI_REF = self._scan("IRI_REF", context=_context)
            return IRI_REF
        else:  # == 'PNAME_NS'
            PrefixedName = self.PrefixedName(R, _context)
            return PrefixedName

    def PrefixedName(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "PrefixedName", [R])
        PNAME_NS = self._scan("PNAME_NS", context=_context)
        if (
            self._peek(
                "PN_LOCAL",
                "NIL",
                "LPAREN",
                "LBRACK",
                "VAR1",
                "VAR2",
                "IRI_REF",
                "FROM",
                "PNAME_NS",
                "DOT",
                "WHERE",
                "ASC",
                "DESC",
                "STAR",
                "DIVIDE",
                "A",
                "UNION",
                "ORDER",
                "STR",
                "LANG",
                "LANGMATCHES",
                "DATATYPE",
                "BOUND",
                "SAMETERM",
                "ISIRI",
                "ISURI",
                "ISBLANK",
                "ISLITERAL",
                "LIMIT",
                "OFFSET",
                "LSBRA",
                "REGEX",
                "RBRACK",
                "FILTER",
                "PLUS",
                "MINUS",
                "TRUE",
                "FALSE",
                "BLANK_NODE_LABEL",
                "ANON",
                "COMMA",
                "RPAREN",
                "OPTIONAL",
                "GRAPH",
                "INTEGER_POSITIVE",
                "DECIMAL_POSITIVE",
                "DOUBLE_POSITIVE",
                "INTEGER_NEGATIVE",
                "DECIMAL_NEGATIVE",
                "DOUBLE_NEGATIVE",
                "STRING_LITERAL1",
                "STRING_LITERAL2",
                "STRING_LITERAL_LONG1",
                "STRING_LITERAL_LONG2",
                "INTEGER",
                "DECIMAL",
                "DOUBLE",
                "SEMICOLON",
                "EQUAL",
                "NOTEQUAL",
                "LESSER",
                "GREATER",
                "LESSEREQ",
                "GREATEREQ",
                "RSBRA",
                "AND",
                "OR",
                context=_context,
            )
            == "PN_LOCAL"
        ):
            PN_LOCAL = self._scan("PN_LOCAL", context=_context)
        return check_prefixed_name(R, PNAME_NS[:-1], locals().get("PN_LOCAL"))

    def BlankNode(self, R, _parent=None):
        _context = self.Context(_parent, self._scanner, "BlankNode", [R])
        _token = self._peek("BLANK_NODE_LABEL", "ANON", context=_context)
        if _token == "BLANK_NODE_LABEL":
            BLANK_NODE_LABEL = self._scan("BLANK_NODE_LABEL", context=_context)
        else:  # == 'ANON'
            ANON = self._scan("ANON", context=_context)


def parse(rule, text):
    P = Fyzz(FyzzScanner(text))
    return runtime.wrap_error_reporter(P, rule)


# End -- grammar generated by Yapps


def parse(text):
    """parses a query

    :param text: the SPARQL query
    :type text: str

    :return: the abstract syntax tree
    :rtype: `fyzz.ast.SparqlTree`

    >>> from fyzz.yappsparser import parse
    >>> ast = parse('''PREFIX doap: <http://usefulinc.com/ns/doap#>
    ... SELECT ?project ?name WHERE {
    ...    ?project a doap:Project;
    ...         doap:name ?name.
    ... }
    ... ORDER BY ?name LIMIT 5 OFFSET 10
    ... ''')
    >>> print ast.selected
    [SparqlVar('project'), SparqlVar('name')]
    >>> print ast.prefixes
    {'doap': 'http://usefulinc.com/ns/doap#'}
    >>> print ast.orderby
    [(SparqlVar('name'), 'asc')]
    >>> print ast.limit, ast.offset
    5 10
    >>> print ast.where
    [(SparqlVar('project'), ('', 'a'), ('http://usefulinc.com/ns/doap#', 'Project')),
     (SparqlVar('project'), ('http://usefulinc.com/ns/doap#', 'name'), SparqlVar('name'))]
    """
    from yapps import runtime

    try:
        parser = Fyzz(FyzzScanner(text))
        root = SparqlTree()
        parser.Query(root)
        return root
    except runtime.SyntaxError as err:
        raise FyzzParserSyntaxError(text, err)
