
/*

SPARQL 1.1 grammar rules based on the Last Call Working Draft of 24/07/2012:
  http://www.w3.org/TR/2012/WD-sparql11-query-20120724/#sparqlGrammar

Be careful with grammar notation - it is EBNF in prolog syntax!

[...] lists always represent sequence.
or can be used as binary operator or n-ary prefix term - do not put [...] 
inside unless you want sequence as a single disjunct.

*, +, ? - generally used as 1-ary terms 

stephen.cresswell@tso.co.uk
*/

% We need to be careful with end-of-input marker $
% Since we never actually receive this from Codemirror, 
% we can't have it appear on RHS of deployed rules.
% However, we do need it to check whether rules *could* precede 
% end-of-input, so use it with top-level

:-dynamic '==>'/2.

queryUnit ==> [query,$].
updateUnit ==> [update,$].

query ==> 
	[prologue,or(selectQuery,constructQuery,describeQuery,askQuery),valuesClause].

prologue ==> 
	[?(baseDecl),*(prefixDecl)].

baseDecl ==> 
	['BASE','IRI_REF'].

prefixDecl ==> 
	['PREFIX','PNAME_NS','IRI_REF'].

% [7]
selectQuery ==>
	[selectClause,*(datasetClause),whereClause,solutionModifier].

subSelect ==>
        [selectClause,whereClause,solutionModifier,valuesClause].

% [9]
selectClause ==> 
	['SELECT',
	?('DISTINCT' or 'REDUCED'),
	(+(var or ['(',expression,'AS',var,')']) or '*')].

%selectQuery ==> 
%	['SELECT',
%	?('DISTINCT' or 'REDUCED'),
%	(+(var) or '*'),
%	*(datasetClause),whereClause,solutionModifier].

%[10]
constructQuery ==> 
	['CONSTRUCT',
 	 [constructTemplate,*(datasetClause),whereClause,solutionModifier] 
         or
	 [*(datasetClause),'WHERE','{',?(triplesTemplate),'}',solutionModifier]].

describeQuery ==> 
	['DESCRIBE',+(varOrIRIref) or '*',
	*(describeDatasetClause),?(whereClause),solutionModifier].

askQuery ==>
	['ASK',*(datasetClause),whereClause,solutionModifier].

describeDatasetClause ==> % Not in spec - artificial distinction
	['FROM',defaultGraphClause or namedGraphClause]. 
datasetClause ==> 
	['FROM',defaultGraphClause or namedGraphClause]. 

defaultGraphClause ==> 
	[sourceSelector].

namedGraphClause ==> 
	['NAMED',sourceSelector].

sourceSelector ==> 
	[iriRef].

whereClause ==> 
	[?('WHERE'),groupGraphPattern].

%[18]
solutionModifier ==> 
	[?(groupClause),?(havingClause),?(orderClause),?(limitOffsetClauses)].

%[19]
groupClause ==> 
	['GROUP','BY',+(groupCondition)].

%[20]
groupCondition ==>
	[builtInCall].
groupCondition ==>
	[functionCall].
groupCondition ==>
	['(',expression,?(['AS',var]),')'].
groupCondition ==>
	[var].

%[21]
havingClause ==>
	['HAVING',+(havingCondition)].
%[22]
havingCondition ==>
	[constraint].

orderClause ==> 
	['ORDER','BY',+(orderCondition)].

orderCondition ==> 
	['ASC' or 'DESC',brackettedExpression].
orderCondition ==> 
	[constraint].
orderCondition ==> 
	[var].

%[25]
limitOffsetClauses ==> 
	[limitClause, ?(offsetClause)].
limitOffsetClauses ==> 
	[offsetClause, ?(limitClause)].

%[26]
limitClause ==> 
	['LIMIT','INTEGER'].

%[27]
offsetClause ==> 
	['OFFSET','INTEGER'].

%[28]
%bindingsClause ==>
%	['BINDINGS',*(var),'{',
%	   *(['(',*(bindingValue),')'] or 'NIL'),
%	   '}'].
%bindingsClause ==> [].

%[28]
valuesClause ==> ['VALUES',dataBlock].
valuesClause ==> [].

%[29]
update ==> [prologue,?([update1,?([';',update])])].

%[30]
update1 ==> [load].
update1 ==> [clear].
update1 ==> [drop].
update1 ==> [add].
update1 ==> [move].
update1 ==> [copy].
update1 ==> [create].
update1 ==> ['INSERT',insert1].
update1 ==> ['DELETE',delete1].
update1 ==> [modify].

%[31]
load ==> ['LOAD','?SILENT_1',iriRef,?(['INTO',graphRef])].
clear ==> ['CLEAR','?SILENT_2',graphRefAll].
drop ==> ['DROP','?SILENT_2',graphRefAll].
create ==> ['CREATE','?SILENT_3',graphRef].
add ==> ['ADD','?SILENT_4',graphOrDefault,'TO',graphOrDefault].
move ==> ['MOVE','?SILENT_4',graphOrDefault,'TO',graphOrDefault].
copy ==> ['COPY','?SILENT_4',graphOrDefault,'TO',graphOrDefault].

% Distinguish uses of ?('SILENT') to keep table clean.
% This is only needed because Flint uses the LL1 table to provide suggestions.
'?SILENT_1'==>[].
'?SILENT_1'==>['SILENT'].
'?SILENT_2'==>[].
'?SILENT_2'==>['SILENT'].
'?SILENT_3'==>[].
'?SILENT_3'==>['SILENT'].
'?SILENT_4'==>[].
'?SILENT_4'==>['SILENT'].

%[38]-[41] Deviate from spec because we separated symbols e.g. was 'INSERT DATA'.
% By separating symbols, we lose LL1 property, so have to re-jiggle grammar
% to avoid multiple rules that begin with DELETE.
insert1 ==> ['DATA',quadData].
insert1 ==> [quadPattern,
	    *(usingClause),
	    'WHERE',
	    groupGraphPattern].

delete1 ==> ['DATA',quadDataNoBnodes].     % Originally nt deleteData
delete1 ==> ['WHERE',quadPatternNoBnodes]. % Originally nt deleteWhere
delete1 ==> [quadPatternNoBnodes,?(insertClause), % Originally part of nt modify
	    *(usingClause),
	    'WHERE',
	    groupGraphPattern].

%[41]
% In the spec, WITH is optional, but we have refactored
% and handled cases beginning 'DELETE' or 'INSERT'.
modify ==> 
	['WITH',iriRef,
	  [deleteClause,?(insertClause)] or insertClause,
	  *(usingClause),
	  'WHERE',
	  groupGraphPattern].

%[42]
deleteClause ==> 
	['DELETE',quadPattern].
%[43]
insertClause ==>
	['INSERT',quadPattern].
%[44]
usingClause ==>
	['USING',iriRef or ['NAMED',iriRef]].
%[45]
graphOrDefault ==> ['DEFAULT'].
graphOrDefault ==> [?('GRAPH'),iriRef].
%[46]
graphRef ==> ['GRAPH',iriRef].
%[47]
graphRefAll ==> [graphRef].
graphRefAll ==> ['DEFAULT'].
graphRefAll ==> ['NAMED'].
graphRefAll ==> ['ALL'].
%[48]
quadPattern ==> ['{',quads,'}'].
quadPatternNoBnodes ==> ['{',disallowBnodes,quads,allowBnodes,'}'].
%[49]
quadData ==> ['{',disallowVars,quads,allowVars,'}'].
quadDataNoBnodes ==> ['{',disallowBnodes,disallowVars,quads,allowVars,allowBnodes,'}'].
% Special NTs that have a hard-wired side-effect in parser code
%  - conditions appear in notes 8 and 9 in grammar section of SPARQL1.1 spec.
disallowVars==>[].
allowVars==>[].
disallowBnodes==>[].
allowBnodes==>[].
%[50]
quads ==> 
	[?(triplesTemplate),*([quadsNotTriples,?('.'),?(triplesTemplate)])].
%[51]
quadsNotTriples ==>
	['GRAPH',varOrIRIref,'{',?(triplesTemplate),'}'].
%[52]
triplesTemplate ==>
	[triplesSameSubject,?(['.',?(triplesTemplate)])].
%[53]
groupGraphPattern ==> 
	['{',subSelect or groupGraphPatternSub,'}'].
%groupGraphPattern ==> [
%        '{',
%        ?(triplesBlock),
%	*([graphPatternNotTriples or filter, ?('.'), ?(triplesBlock)]),
%	'}'].
%[54]
groupGraphPatternSub ==>
	[?(triplesBlock),*([graphPatternNotTriples,?('.'),?(triplesBlock)])].
%[55]
triplesBlock ==>
	[triplesSameSubjectPath,?(['.',?(triplesBlock)])].
%[56]
graphPatternNotTriples ==> [groupOrUnionGraphPattern].
graphPatternNotTriples ==> [optionalGraphPattern].
graphPatternNotTriples ==> [minusGraphPattern].
graphPatternNotTriples ==> [graphGraphPattern].
graphPatternNotTriples ==> [serviceGraphPattern].
graphPatternNotTriples ==> [filter].
graphPatternNotTriples ==> [bind].
graphPatternNotTriples ==> [inlineData].
%[57]
optionalGraphPattern ==> ['OPTIONAL',groupGraphPattern].
%[58]
graphGraphPattern ==> 
	['GRAPH',varOrIRIref,groupGraphPattern].
%[59]
serviceGraphPattern ==> 
	['SERVICE',?('SILENT'),varOrIRIref,groupGraphPattern].
%[60]
bind ==> 
	['BIND','(',expression,'AS',var,')'].
%[61]
inlineData ==> ['VALUES',dataBlock].
%[62]
dataBlock ==> [inlineDataOneVar or inlineDataFull].
%[63]
inlineDataOneVar ==> [var,'{',*(dataBlockValue),'}'].
%[64]
inlineDataFull ==> [ 'NIL' or ['(',*(var),')'], 
                        '{',*(['(',*(dataBlockValue),')'] or 'NIL'),'}'].
%[65]
dataBlockValue ==> [iriRef].
dataBlockValue ==> [rdfLiteral].
dataBlockValue ==> [numericLiteral].
dataBlockValue ==> [booleanLiteral].
dataBlockValue ==> ['UNDEF'].

%[66]
minusGraphPattern ==> 
	['MINUS',groupGraphPattern].
%[67]
groupOrUnionGraphPattern ==> 
	[groupGraphPattern,*(['UNION',groupGraphPattern])].
%[68]
filter ==>
	['FILTER',constraint].
%[69]
constraint ==> 
	[brackettedExpression].
constraint ==> 
	[builtInCall].
constraint ==> 
	[functionCall].
%[70]
functionCall ==> 
	[iriRef,argList].
%[70]
argList ==> 
	['NIL'].
argList ==> 
	['(',?('DISTINCT'),expression,*([',',expression]),')'].
%[71]
expressionList ==> ['NIL'].
expressionList ==> ['(',expression,*([',',expression]),')'].
%[73]
constructTemplate ==>
	['{',?(constructTriples),'}'].
%[74]
constructTriples ==>
	[triplesSameSubject,?(['.',?(constructTriples)])].
%[75]
triplesSameSubject ==>
	[varOrTerm,propertyListNotEmpty].
triplesSameSubject ==>
	[triplesNode,propertyList].
%[76]
propertyList ==> [propertyListNotEmpty].
propertyList ==> [].
%[77]
propertyListNotEmpty ==> 
	[verb,objectList,*([';',?([verb,objectList])])].
% storeProperty is a dummy for side-effect of remembering property
storeProperty==>[].
%[78]
verb ==> [storeProperty,varOrIRIref].
verb ==> [storeProperty,'a'].
%[79]
objectList ==> 
	[object,*([',',object])].
%[80]
object ==> 
	[graphNode].
%[81]
triplesSameSubjectPath ==> [varOrTerm,propertyListPathNotEmpty].
triplesSameSubjectPath ==> [triplesNodePath,propertyListPath].
%[82]
propertyListPath ==> [propertyListNotEmpty].
propertyListPath ==> [].
%[83]
propertyListPathNotEmpty ==>
	[verbPath or verbSimple,
	objectListPath,
	*([';',?([verbPath or verbSimple,objectList])])].
%[84]
verbPath ==> [path].
%[85]
verbSimple ==> [var].
%[86]
objectListPath ==> 
	[objectPath,*([',',objectPath])].
%[87]
objectPath ==> [graphNodePath].
%[88]
path ==> [pathAlternative].
%[89].
pathAlternative ==>
	[pathSequence,*(['|',pathSequence])].
%[90]
pathSequence ==>
	[pathEltOrInverse,*(['/',pathEltOrInverse])].
%[91]
pathElt ==>
	[pathPrimary,?(pathMod)].
%[92]
pathEltOrInverse ==> [pathElt].
pathEltOrInverse ==> ['^',pathElt].
%[93]  - last case below looks weird because 
%        {0} and {0,1} and {0,} and {,1} are allowed
pathMod ==> ['*'].
pathMod ==> ['?'].
pathMod ==> ['+'].
pathMod ==> 
	['{',
          [integer,
	     ([',', '}' or [integer,'}']])
             or
             '}'
          ]
          or
          [',',integer,'}']
        ].

% Original expression from SPARQL1.1 spec:
%'{' ( Integer 
%        ( ',' 
%            ( '}' | Integer '}' ) 
%        | '}' ) 
%    | ',' Integer '}' ) 

%[94]
pathPrimary ==> [storeProperty,iriRef].
pathPrimary ==> [storeProperty,'a'].
pathPrimary ==> ['!',pathNegatedPropertySet].
pathPrimary ==> ['(',path,')'].

%[95]
pathNegatedPropertySet ==> 
	[pathOneInPropertySet].
pathNegatedPropertySet ==> 
	['(',
	 ?([pathOneInPropertySet,
	    *(['|',pathOneInPropertySet]) ]),
         ')'].
%[96]
pathOneInPropertySet ==> [iriRef].
pathOneInPropertySet ==> ['a'].
pathOneInPropertySet ==> ['^',iriRef or 'a'].
%[97]
integer ==> ['INTEGER'].
%[98]
triplesNode ==> [collection].
triplesNode ==> [blankNodePropertyList].
%[99]
blankNodePropertyList ==> ['[',propertyListNotEmpty,']'].
%[100]
triplesNodePath ==> [collectionPath].
triplesNodePath ==> [blankNodePropertyListPath].
%[101]
blankNodePropertyListPath ==> ['[',propertyListPathNotEmpty,']'].
%[102]
collection ==> ['(',+(graphNode),')'].
%[103]
collectionPath ==> ['(',+(graphNodePath),')'].
%[104]
graphNode ==> [varOrTerm].
graphNode ==> [triplesNode].
%[105]
graphNodePath ==> [varOrTerm].
graphNodePath ==> [triplesNodePath].
%[106]
varOrTerm ==> [var].
varOrTerm ==> [graphTerm].
%[107]
varOrIRIref ==> [var].
varOrIRIref ==> [iriRef].
%[108]
var ==> ['VAR1'].
var ==> ['VAR2'].
%[109]
graphTerm ==> [iriRef].
graphTerm ==> [rdfLiteral].
graphTerm ==> [numericLiteral].
graphTerm ==> [booleanLiteral].
graphTerm ==> [blankNode].
graphTerm ==> ['NIL'].
%[110]
expression ==> [conditionalOrExpression].
%[111]
conditionalOrExpression ==> 
	[conditionalAndExpression,*(['||',conditionalAndExpression])].
%[112]
conditionalAndExpression ==> 
	[valueLogical,*(['&&',valueLogical])].
%[113]
valueLogical ==> [relationalExpression].
%[114]
relationalExpression ==> 
	[numericExpression, 
	 ?(or(['=',numericExpression],
	      ['!=',numericExpression],
	      ['<',numericExpression],
	      ['>',numericExpression],
	      ['<=',numericExpression],
	      ['>=',numericExpression],
	      ['IN',expressionList],
	      ['NOT','IN',expressionList]))].
%[115]
numericExpression ==> [additiveExpression].
%[116]
additiveExpression ==> 
	[multiplicativeExpression, 
	 *(or(['+',multiplicativeExpression],
	      ['-',multiplicativeExpression],
              [numericLiteralPositive or numericLiteralNegative,
	       ?(['*',unaryExpression] or ['/',unaryExpression]) ]))].
%[117]
multiplicativeExpression ==> 
	[unaryExpression,*(['*',unaryExpression] or ['/',unaryExpression])].
%[118]
unaryExpression ==> ['!',primaryExpression].
unaryExpression ==> ['+',primaryExpression].
unaryExpression ==> ['-',primaryExpression].
unaryExpression ==> [primaryExpression].
%[119]
primaryExpression ==> [brackettedExpression].
primaryExpression ==> [builtInCall].
primaryExpression ==> [iriRefOrFunction].
primaryExpression ==> [rdfLiteral].
primaryExpression ==> [numericLiteral].
primaryExpression ==> [booleanLiteral].
primaryExpression ==> [var].
primaryExpression ==> [aggregate].
%[120]
brackettedExpression ==> ['(',expression,')'].
%[121]
builtInCall ==> ['STR','(',expression,')'].
builtInCall ==> ['LANG','(',expression,')'].
builtInCall ==> ['LANGMATCHES','(',expression,',',expression,')'].
builtInCall ==> ['DATATYPE','(',expression,')'].
builtInCall ==> ['BOUND','(',var,')'].
builtInCall ==> ['IRI','(',expression,')'].
builtInCall ==> ['URI','(',expression,')'].
%builtInCall ==> ['BNODE','(',?(expression),')'].  % Avoided use of NIL
%builtInCall ==> ['RAND','(',')'].                 % Avoided use of NIL
builtInCall ==> ['BNODE',['(',expression,')'] or 'NIL'].
builtInCall ==> ['RAND','NIL'].
builtInCall ==> ['ABS','(',expression,')'].
builtInCall ==> ['CEIL','(',expression,')'].
builtInCall ==> ['FLOOR','(',expression,')'].
builtInCall ==> ['ROUND','(',expression,')'].
builtInCall ==> ['CONCAT',expressionList].
builtInCall ==> [substringExpression].
builtInCall ==> ['STRLEN','(',expression,')'].
builtInCall ==> [strReplaceExpression].
builtInCall ==> ['UCASE','(',expression,')'].
builtInCall ==> ['LCASE','(',expression,')'].
builtInCall ==> ['ENCODE_FOR_URI','(',expression,')'].
builtInCall ==> ['CONTAINS','(',expression,',',expression,')'].
builtInCall ==> ['STRSTARTS','(',expression,',',expression,')'].
builtInCall ==> ['STRENDS','(',expression,',',expression,')'].
builtInCall ==> ['STRBEFORE','(',expression,',',expression,')'].
builtInCall ==> ['STRAFTER','(',expression,',',expression,')'].
builtInCall ==> ['YEAR','(',expression,')'].
builtInCall ==> ['MONTH','(',expression,')'].
builtInCall ==> ['DAY','(',expression,')'].
builtInCall ==> ['HOURS','(',expression,')'].
builtInCall ==> ['MINUTES','(',expression,')'].
builtInCall ==> ['SECONDS','(',expression,')'].
builtInCall ==> ['TIMEZONE','(',expression,')'].
builtInCall ==> ['TZ','(',expression,')'].
%builtInCall ==> ['NOW','(',')'].            % Avoided NIL
builtInCall ==> ['NOW','NIL'].
builtInCall ==> ['UUID','NIL'].
builtInCall ==> ['STRUUID','NIL'].
builtInCall ==> ['MD5','(',expression,')'].
builtInCall ==> ['SHA1','(',expression,')'].
builtInCall ==> ['SHA256','(',expression,')'].
builtInCall ==> ['SHA384','(',expression,')'].
builtInCall ==> ['SHA512','(',expression,')'].
builtInCall ==> ['COALESCE',expressionList].
builtInCall ==> ['IF','(',expression,',',expression,',',expression,')'].
builtInCall ==> ['STRLANG','(',expression,',',expression,')'].
builtInCall ==> ['STRDT','(',expression,',',expression,')'].
builtInCall ==> ['SAMETERM','(',expression,',',expression,')'].
builtInCall ==> ['ISIRI','(',expression,')'].
builtInCall ==> ['ISURI','(',expression,')'].
builtInCall ==> ['ISBLANK','(',expression,')'].
builtInCall ==> ['ISLITERAL','(',expression,')'].
builtInCall ==> ['ISNUMERIC','(',expression,')'].
builtInCall ==> [regexExpression].
builtInCall ==> [existsFunc].
builtInCall ==> [notExistsFunc].
%[122]
regexExpression ==> 
	['REGEX','(',expression,',',expression,?([',',expression]),')'].
%[123]
substringExpression ==> 
	['SUBSTR','(',expression,',',expression,?([',',expression]),')'].
%[124]
strReplaceExpression ==> 
	['REPLACE','(',expression,',',expression,',',expression,?([',',expression]),')'].
%[125]
existsFunc ==>
	['EXISTS',groupGraphPattern].
%[126]
notExistsFunc ==>
	['NOT','EXISTS',groupGraphPattern].
%[127]
aggregate ==> ['COUNT','(',?('DISTINCT'),'*' or expression,')'].
aggregate ==> ['SUM','(',?('DISTINCT'),expression,')'].
aggregate ==> ['MIN','(',?('DISTINCT'),expression,')'].
aggregate ==> ['MAX','(',?('DISTINCT'),expression,')'].
aggregate ==> ['AVG','(',?('DISTINCT'),expression,')'].
aggregate ==> ['SAMPLE','(',?('DISTINCT'),expression,')'].
aggregate ==> 
	['GROUP_CONCAT','(',
	 ?('DISTINCT'),
	 expression,
	 ?([';','SEPARATOR','=',string]),
	 ')'].
%[128]
iriRefOrFunction ==> [iriRef,?(argList)].
%[129]
rdfLiteral ==> [string,?('LANGTAG' or ['^^',iriRef])].
%[130]
numericLiteral ==> [numericLiteralUnsigned].
numericLiteral ==> [numericLiteralPositive].
numericLiteral ==> [numericLiteralNegative].
%[131]
numericLiteralUnsigned ==> ['INTEGER'].
numericLiteralUnsigned ==> ['DECIMAL'].
numericLiteralUnsigned ==> ['DOUBLE'].
%[132]
numericLiteralPositive ==> ['INTEGER_POSITIVE'].
numericLiteralPositive ==> ['DECIMAL_POSITIVE'].
numericLiteralPositive ==> ['DOUBLE_POSITIVE'].
%[133]
numericLiteralNegative ==> ['INTEGER_NEGATIVE'].
numericLiteralNegative ==> ['DECIMAL_NEGATIVE'].
numericLiteralNegative ==> ['DOUBLE_NEGATIVE'].
%[134]
booleanLiteral ==> ['TRUE'].
booleanLiteral ==> ['FALSE'].
%[135]
string ==> ['STRING_LITERAL1'].
string ==> ['STRING_LITERAL2'].
string ==> ['STRING_LITERAL_LONG1'].
string ==> ['STRING_LITERAL_LONG2'].
%[136]
iriRef ==> ['IRI_REF'].
iriRef ==> [prefixedName].
%[137]
prefixedName ==> ['PNAME_LN'].
prefixedName ==> ['PNAME_NS'].
%[138]
blankNode ==> ['BLANK_NODE_LABEL'].
blankNode ==> ['ANON'].


% tokens defined by regular expressions elsewhere
tm_regex([

'IRI_REF',

'VAR1',
'VAR2',
'LANGTAG',

'DOUBLE',
'DECIMAL',
'INTEGER',
'DOUBLE_POSITIVE',
'DECIMAL_POSITIVE',
'INTEGER_POSITIVE',
'INTEGER_NEGATIVE',
'DECIMAL_NEGATIVE',
'DOUBLE_NEGATIVE',

'STRING_LITERAL_LONG1',
'STRING_LITERAL_LONG2',
'STRING_LITERAL1',
'STRING_LITERAL2',

'NIL',
'ANON',
'PNAME_LN',
'PNAME_NS',
'BLANK_NODE_LABEL'
]).

% Terminals where name of terminal is uppercased token content
tm_keywords([

'GROUP_CONCAT', % Must appear before GROUP
'DATATYPE',     % Must appear before DATA

'BASE',
'PREFIX',
'SELECT',
'CONSTRUCT',
'DESCRIBE',
'ASK',
'FROM',
'NAMED',
'ORDER',
'BY',
'LIMIT',
'ASC',
'DESC',
'OFFSET',
'DISTINCT',
'REDUCED',
'WHERE',
'GRAPH',
'OPTIONAL',
'UNION',
'FILTER',
'GROUP',
'HAVING',
'AS',
'VALUES',
'LOAD',
'CLEAR',
'DROP',
'CREATE',
'MOVE',
'COPY',
'SILENT',
'INSERT',
'DELETE',
'DATA',
'WITH',
'TO',
'USING',
'NAMED',
'MINUS',
'BIND',

'LANGMATCHES',
'LANG',
'BOUND',
'SAMETERM',
'ISIRI',
'ISURI',
'ISBLANK',
'ISLITERAL',
'REGEX',
'TRUE',
'FALSE',

'UNDEF',
'ADD',
'DEFAULT',
'ALL',
'SERVICE',
'INTO',
'IN',
'NOT',
'IRI',
'URI',
'BNODE',
'RAND',
'ABS',
'CEIL',
'FLOOR',
'ROUND',
'CONCAT',
'STRLEN',
'UCASE',
'LCASE',
'ENCODE_FOR_URI',
'CONTAINS',
'STRSTARTS',
'STRENDS',
'STRBEFORE',
'STRAFTER',
'YEAR',
'MONTH',
'DAY',
'HOURS',
'MINUTES',
'SECONDS',
'TIMEZONE',
'TZ',
'NOW',
'UUID',
'STRUUID',
'MD5',
'SHA1',
'SHA256',
'SHA384',
'SHA512',
'COALESCE',
'IF',
'STRLANG',
'STRDT',
'ISNUMERIC',
'SUBSTR',
'REPLACE',
'EXISTS',
'COUNT',
'SUM',
'MIN',
'MAX',
'AVG',
'SAMPLE',
'SEPARATOR',

'STR'
]).

% Other tokens representing fixed, case sensitive, strings
% Care! order longer tokens first - e.g. IRI_REF, <=, <
% e.g. >=, >
% e.g. NIL, '('
% e.g. ANON, [
% e.g. DOUBLE, DECIMAL, INTEGER
% e.g. INTEGER_POSITIVE, PLUS
tm_punct([
'*'= '\\*',
'a'= 'a',
'.'= '\\.',
'{'= '\\{',
'}'= '\\}',
','= ',',
'('= '\\(',
')'= '\\)',
';'= ';',
'['= '\\[',
']'= '\\]',
'||'= '\\|\\|',
'&&'= '&&',
'='= '=',
'!='= '!=',
'!'= '!',
'<='= '<=',
'>='= '>=',
'<'= '<',
'>'= '>',
'+'= '\\+',
'-'= '-',
'/'= '\\/',
'^^'= '\\^\\^',
'?' = '\\?',
'|' = '\\|',
'^'= '\\^'
]).
