# EBNF Notation3 Grammar based pm Antlr4.
# From https://github.com/w3c/N3/blob/master/grammar/n3.g4
[1] n3Doc ::= (n3Statement '.' | sparqlDirective)*
[2] n3Statement ::= n3Directive | triples
[3] n3Directive ::= prefixID | base
[4] sparqlDirective ::= sparqlBase | sparqlPrefix
[5] sparqlBase ::= BASE IRIREF
[6] sparqlPrefix ::= PREFIX PNAME_NS IRIREF
[7] prefixID ::= '@prefix' PNAME_NS IRIREF
[8] base ::= '@base' IRIREF
[9] triples ::= subject predicateObjectList?
[10] predicateObjectList ::= verb objectList (';' (verb objectList)?)*
[11] objectList ::= object (',' object)*
[12] verb ::= predicate
| 'a'
| 'has' expression
| 'is' expression 'of'
| '='
| '<='
| '=>'
[13] subject ::= expression
[14] predicate ::= (expression | '<-' expression)
/* allow inverting first predicate in a path */
[15] object ::= expression
[16] expression ::= path
[17] path ::= pathItem ('!' path | '^' path)?
[18] pathItem ::= iri
| blankNode
| quickVar
| collection
| blankNodePropertyList
| iriPropertyList
| literal
| formula
[19] literal ::= rdfLiteral
| numericLiteral
| BOOLEAN_LITERAL
[20] blankNodePropertyList ::= '[' predicateObjectList ']'
[21] iriPropertyList ::= IPLSTART iri predicateObjectList ']'
[22] collection ::= '(' object* ')'
[23] formula ::= '{' formulaContent? '}'
[24] formulaContent ::= n3Statement ('.' formulaContent?)?
| sparqlDirective formulaContent?
[25] numericLiteral ::= DOUBLE | DECIMAL | INTEGER
[26] rdfLiteral ::= STRING (LANGTAG | '^^' iri)?
[27] iri ::= IRIREF | prefixedName
[28] prefixedName ::= PNAME_LN | PNAME_NS
# PNAME_NS will be matched for ':' (i.e., "empty") prefixedNames
# hence this cannot be a lexer rule; for s/p/o of only ':', PNAME_NS will be returned
# instead of PrefixedName token
[29] blankNode ::= BLANK_NODE_LABEL | ANON
[30] quickVar ::= QUICK_VAR_NAME
# only made this a parser rule for consistency
# (all other path-items are also parser rules)
@terminals
[31] BOOLEAN_LITERAL ::= 'true' | 'false'
[32] STRING ::= STRING_LITERAL_LONG_SINGLE_QUOTE
| STRING_LITERAL_LONG_QUOTE
| STRING_LITERAL_QUOTE
| STRING_LITERAL_SINGLE_QUOTE
/* Note, this must be matched before '[' */
[33] IPLSTART ::= '[' WS* 'id'
/* borrowed from SPARQL spec, which excludes newlines and other nastiness */
[139s] IRIREF ::= '<' ([^<>"{}|^`\]-[#x00-#x20] | UCHAR)* '>'
[140s] PNAME_NS ::= PN_PREFIX? ':'
[141s] PNAME_LN ::= PNAME_NS PN_LOCAL
[142s] BLANK_NODE_LABEL ::= '_:' ( PN_CHARS_U | [0-9] ) ((PN_CHARS|'.')* PN_CHARS)?
[145s] LANGTAG ::= "@" ([a-zA-Z]+ ( "-" [a-zA-Z0-9]+ )*)
[146s] INTEGER ::= [0-9]+
[147s] DECIMAL ::= [0-9]* '.' [0-9]+
[148s] DOUBLE ::= [0-9]+ '.' [0-9]* EXPONENT
| '.' ([0-9])+ EXPONENT | ([0-9])+ EXPONENT
[155s] EXPONENT ::= [eE] [+-]? [0-9]+
[156s] STRING_LITERAL_QUOTE ::= '"' ( [^#x22#x5C#xA#xD] | ECHAR | UCHAR )* '"'
[157s] STRING_LITERAL_SINGLE_QUOTE ::= "'" ( [^#x27#x5C#xA#xD] | ECHAR | UCHAR )* "'"
[158s] STRING_LITERAL_LONG_SINGLE_QUOTE ::= "'''" ( ( "'" | "''" )? ( [^'\] | ECHAR | UCHAR ) )* "'''"
[159s] STRING_LITERAL_LONG_QUOTE ::= '"""' ( ( '"' | '""' )? ( [^"\] | ECHAR | UCHAR ) )* '"""'
[35] UCHAR ::= ( "\u" HEX HEX HEX HEX ) | ( "\U" HEX HEX HEX HEX HEX HEX HEX HEX )
[160s] ECHAR ::= "\" [tbnrf\"']
[162s] WS ::= #x20 | #x9 | #xD | #xA
[163s] ANON ::= '[' WS* ']'
[36] QUICK_VAR_NAME ::= "?" PN_LOCAL
/* Allows fuller character set */
[164s] PN_CHARS_BASE ::= [A-Z] | [a-z] | [#x00C0-#x00D6]
| [#x00D8-#x00F6] | [#x00F8-#x02FF] | [#x0370-#x037D]
| [#x037F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F]
| [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF]
| [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
[165s] PN_CHARS_U ::= PN_CHARS_BASE | '_'
[167s] PN_CHARS ::= PN_CHARS_U | "-" | [0-9] | #x00B7 | [#x0300-#x036F] | [#x203F-#x2040]
/* BASE and PREFIX must be case-insensitive, hence these monstrosities */
[37] BASE ::= ('B'|'b') ('A'|'a') ('S'|'s') ('E'|'e')
[38] PREFIX ::= ('P'|'p') ('R'|'r') ('E'|'e') ('F'|'f') ('I'|'i') ('X'|'x')
[168s] PN_PREFIX ::= PN_CHARS_BASE ( ( PN_CHARS | "." )* PN_CHARS )?
[169s] PN_LOCAL ::= ( PN_CHARS_U | ':' | [0-9] | PLX ) ( ( PN_CHARS | '.' | ':' | PLX )* ( PN_CHARS | ':' | PLX ) ) ?
[170s] PLX ::= PERCENT | PN_LOCAL_ESC
[171s] PERCENT ::= '%' HEX HEX
[172s] HEX ::= [0-9] | [A-F] | [a-f]
[173s] PN_LOCAL_ESC ::= '\' ( '_' | '~' | '.' | '-' | '!' | '$' | '&' | "'" | '(' | ')' | '*' | '+' | ',' | ';' | '='
| '/' | '?' | '#' | '@' | '%' )
[39] COMMENT ::= ('#' - '#x') [^#xA#xC#xD]*
# Ignore all whitespace and comments between non-terminals
@pass ( WS | COMMENT )*