UNPKG

@jitterbit/soql-parser-js

Version:
669 lines (668 loc) 30.6 kB
import { CstParser } from 'chevrotain'; import * as lexer from './lexer'; export class LexingError extends Error { constructor(lexingError) { super(`${lexingError.message} (${lexingError.line}:${lexingError.column})`); this.name = 'LexingError'; } } export class ParsingError extends Error { constructor(parsingError) { super(parsingError.message); this.name = parsingError.name; } } export class SoqlParser extends CstParser { $_dateFunctionOr = undefined; $_aggregateFunction = undefined; $_otherFunction = undefined; $_atomicExpression = undefined; $_apexBindVariableExpression = undefined; $_arrayExpression = undefined; $_relationalOperator = undefined; $_selectClause = undefined; $_selectClauseFunctionIdentifier = undefined; $_withDataCategoryArr = undefined; allowApexBindVariables = false; ignoreParseErrors = false; constructor({ ignoreParseErrors } = { ignoreParseErrors: false }) { super(lexer.allTokens, { skipValidations: false, recoveryEnabled: !!ignoreParseErrors, }); this.ignoreParseErrors = !!ignoreParseErrors; this.performSelfAnalysis(); } selectStatement = this.RULE('selectStatement', () => { this.SUBRULE(this.selectClause); this.SUBRULE(this.fromClause); this.SUBRULE(this.clauseStatements); }); selectStatementPartial = this.RULE('selectStatementPartial', () => { this.OPTION(() => { this.SUBRULE(this.selectClause); }); this.OPTION1(() => { this.SUBRULE(this.fromClause); }); this.SUBRULE(this.clauseStatements); }); clauseStatements = this.RULE('clauseStatements', () => { this.OPTION(() => { this.SUBRULE(this.usingScopeClause); }); this.OPTION1(() => { this.SUBRULE(this.whereClause); }); this.OPTION2(() => { this.MANY({ DEF: () => { this.SUBRULE(this.withClause); }, }); }); this.OPTION3(() => { this.SUBRULE(this.groupByClause); this.OPTION4(() => { this.SUBRULE(this.havingClause); }); }); this.OPTION5(() => { this.SUBRULE(this.orderByClause); }); this.OPTION6(() => { this.SUBRULE(this.limitClause); }); this.OPTION7(() => { this.SUBRULE(this.offsetClause); }); this.OPTION8(() => { this.SUBRULE(this.forViewOrReference); }); this.OPTION9(() => { this.SUBRULE(this.updateTrackingViewstat); }); }); $_checkBalancedParens(parenCount) { if (!this.RECORDING_PHASE && parenCount) { const parenMatch = parenCount.left - parenCount.right; if (parenMatch !== 0) { this.CONSUME(lexer.RParenMismatch, { ERR_MSG: `Expecting a token type of --> RParen <-- but found --> '' <--` }); } } } selectClause = this.RULE('selectClause', () => { this.CONSUME(lexer.Select); this.AT_LEAST_ONE_SEP({ SEP: lexer.Comma, DEF: () => { this.OR(this.$_selectClause || (this.$_selectClause = [ { ALT: () => this.SUBRULE(this.selectClauseFunctionIdentifier, { LABEL: 'field' }) }, { ALT: () => this.SUBRULE(this.selectClauseSubqueryIdentifier, { LABEL: 'field' }) }, { ALT: () => this.SUBRULE(this.selectClauseTypeOf, { LABEL: 'field' }) }, { ALT: () => this.SUBRULE(this.selectClauseIdentifier, { LABEL: 'field' }) }, ])); }, }); }, { resyncEnabled: false }); selectClauseFunctionIdentifier = this.RULE('selectClauseFunctionIdentifier', () => { this.OR(this.$_selectClauseFunctionIdentifier || (this.$_selectClauseFunctionIdentifier = [ { ALT: () => this.SUBRULE(this.dateFunction, { LABEL: 'fn' }) }, { ALT: () => this.SUBRULE(this.aggregateFunction, { LABEL: 'fn' }) }, { ALT: () => this.SUBRULE(this.locationFunction, { LABEL: 'fn' }) }, { ALT: () => this.SUBRULE(this.fieldsFunction, { LABEL: 'fn' }) }, { ALT: () => this.SUBRULE(this.otherFunction, { LABEL: 'fn' }) }, ])); this.OPTION(() => this.CONSUME(lexer.Identifier, { LABEL: 'alias' })); }, { resyncEnabled: false }); selectClauseSubqueryIdentifier = this.RULE('selectClauseSubqueryIdentifier', () => { this.CONSUME(lexer.LParen); this.SUBRULE(this.selectStatement); this.CONSUME(lexer.RParen); }, { resyncEnabled: false }); selectClauseTypeOf = this.RULE('selectClauseTypeOf', () => { this.CONSUME(lexer.Typeof); this.CONSUME(lexer.Identifier, { LABEL: 'typeOfField' }); this.AT_LEAST_ONE({ DEF: () => { this.SUBRULE(this.selectClauseTypeOfThen); }, }); this.OPTION(() => { this.SUBRULE(this.selectClauseTypeOfElse); }); this.CONSUME(lexer.End); }, { resyncEnabled: false }); selectClauseIdentifier = this.RULE('selectClauseIdentifier', () => { this.CONSUME(lexer.Identifier, { LABEL: 'field' }); this.OPTION(() => this.CONSUME1(lexer.Identifier, { LABEL: 'alias' })); }, { resyncEnabled: false }); selectClauseTypeOfThen = this.RULE('selectClauseTypeOfThen', () => { this.CONSUME(lexer.When); this.CONSUME(lexer.Identifier, { LABEL: 'typeOfField' }); this.CONSUME(lexer.Then); this.AT_LEAST_ONE_SEP({ SEP: lexer.Comma, DEF: () => { this.CONSUME1(lexer.Identifier, { LABEL: 'field' }); }, }); }, { resyncEnabled: false }); selectClauseTypeOfElse = this.RULE('selectClauseTypeOfElse', () => { this.CONSUME(lexer.Else); this.AT_LEAST_ONE_SEP({ SEP: lexer.Comma, DEF: () => { this.CONSUME(lexer.Identifier, { LABEL: 'field' }); }, }); }, { resyncEnabled: false }); fromClause = this.RULE('fromClause', () => { this.CONSUME(lexer.From); this.CONSUME(lexer.Identifier); this.OPTION({ GATE: () => !(this.LA(1).tokenType === lexer.Offset && this.LA(2).tokenType === lexer.UnsignedInteger), DEF: () => this.CONSUME1(lexer.Identifier, { LABEL: 'alias' }), }); }, { resyncEnabled: false }); usingScopeClause = this.RULE('usingScopeClause', () => { this.CONSUME(lexer.Using); this.CONSUME(lexer.Scope); this.CONSUME(lexer.UsingScopeEnumeration); }); whereClause = this.RULE('whereClause', () => { this.CONSUME(lexer.Where); const parenCount = this.getParenCount(); this.AT_LEAST_ONE({ DEF: () => { this.SUBRULE(this.conditionExpression, { ARGS: [parenCount, true, true] }); }, }); this.$_checkBalancedParens(parenCount); }); whereClauseSubqueryIdentifier = this.RULE('whereClauseSubqueryIdentifier', () => { this.CONSUME(lexer.LParen); this.SUBRULE(this.selectStatement); this.CONSUME(lexer.RParen); }); conditionExpression = this.RULE('conditionExpression', (parenCount, allowAggregateFn, allowLocationFn) => { parenCount = this.getParenCount(parenCount); this.OPTION(() => { this.OR([ { ALT: () => this.CONSUME(lexer.And, { LABEL: 'logicalOperator' }) }, { ALT: () => this.CONSUME(lexer.Or, { LABEL: 'logicalOperator' }) }, ]); }); this.MANY({ MAX_LOOKAHEAD: 10, DEF: () => this.SUBRULE(this.expressionPartWithNegation, { ARGS: [parenCount], LABEL: 'expressionNegation' }), }); this.OR1({ MAX_LOOKAHEAD: 10, DEF: [{ ALT: () => this.SUBRULE(this.expression, { ARGS: [parenCount, false, allowAggregateFn, allowLocationFn] }) }], }); }); withClause = this.RULE('withClause', () => { this.CONSUME(lexer.With); this.OR([ { ALT: () => this.CONSUME(lexer.SecurityEnforced, { LABEL: 'withSecurityEnforced' }) }, { ALT: () => this.CONSUME(lexer.UserMode, { LABEL: 'withAccessLevel' }) }, { ALT: () => this.CONSUME(lexer.SystemMode, { LABEL: 'withAccessLevel' }) }, { ALT: () => this.SUBRULE(this.withDataCategory) }, ]); }); withDataCategory = this.RULE('withDataCategory', () => { this.CONSUME(lexer.DataCategory); this.AT_LEAST_ONE_SEP({ SEP: lexer.And, DEF: () => { this.SUBRULE(this.withDataCategoryArr); }, }); }); withDataCategoryArr = this.RULE('withDataCategoryArr', () => { this.CONSUME(lexer.Identifier, { LABEL: 'dataCategoryGroupName' }); this.OR(this.$_withDataCategoryArr || (this.$_withDataCategoryArr = [ { ALT: () => this.CONSUME(lexer.At, { LABEL: 'filteringSelector' }) }, { ALT: () => this.CONSUME(lexer.Above, { LABEL: 'filteringSelector' }) }, { ALT: () => this.CONSUME(lexer.Below, { LABEL: 'filteringSelector' }) }, { ALT: () => this.CONSUME(lexer.AboveOrBelow, { LABEL: 'filteringSelector' }) }, ])); this.OPTION(() => { this.CONSUME1(lexer.LParen); }); this.AT_LEAST_ONE_SEP1({ SEP: lexer.Comma, DEF: () => { this.CONSUME1(lexer.Identifier, { LABEL: 'dataCategoryName' }); }, }); this.OPTION1(() => { this.CONSUME2(lexer.RParen); }); }); groupByClause = this.RULE('groupByClause', () => { this.CONSUME(lexer.GroupBy); this.AT_LEAST_ONE_SEP({ SEP: lexer.Comma, DEF: () => { this.OR([ { ALT: () => this.SUBRULE(this.cubeFunction, { LABEL: 'groupBy' }) }, { ALT: () => this.SUBRULE(this.rollupFunction, { LABEL: 'groupBy' }) }, { ALT: () => this.SUBRULE(this.dateFunction, { LABEL: 'groupBy' }) }, { ALT: () => this.CONSUME(lexer.Identifier, { LABEL: 'groupBy' }) }, ]); }, }); }); havingClause = this.RULE('havingClause', () => { this.CONSUME(lexer.Having); const parenCount = this.getParenCount(); this.AT_LEAST_ONE({ DEF: () => { this.SUBRULE(this.conditionExpression, { ARGS: [parenCount, true, false] }); }, }); this.$_checkBalancedParens(parenCount); }); orderByClause = this.RULE('orderByClause', () => { this.CONSUME(lexer.OrderBy); this.AT_LEAST_ONE_SEP({ SEP: lexer.Comma, DEF: () => { this.OR([ { ALT: () => this.SUBRULE(this.orderByGroupingFunctionExpression, { LABEL: 'orderByExpressionOrFn' }) }, { ALT: () => this.SUBRULE(this.orderBySpecialFunctionExpression, { LABEL: 'orderByExpressionOrFn' }) }, { ALT: () => this.SUBRULE(this.orderByExpression, { LABEL: 'orderByExpressionOrFn' }) }, ]); }, }); }); orderByExpression = this.RULE('orderByExpression', () => { this.CONSUME(lexer.Identifier); this.OPTION(() => { this.OR([{ ALT: () => this.CONSUME(lexer.Asc, { LABEL: 'order' }) }, { ALT: () => this.CONSUME(lexer.Desc, { LABEL: 'order' }) }]); }); this.OPTION1(() => { this.CONSUME(lexer.Nulls); this.OR1([{ ALT: () => this.CONSUME(lexer.First, { LABEL: 'nulls' }) }, { ALT: () => this.CONSUME(lexer.Last, { LABEL: 'nulls' }) }]); }); }); orderByGroupingFunctionExpression = this.RULE('orderByGroupingFunctionExpression', () => { this.CONSUME(lexer.Grouping, { LABEL: 'fn' }); this.SUBRULE(this.functionExpression); }); orderBySpecialFunctionExpression = this.RULE('orderBySpecialFunctionExpression', () => { this.OR([ { ALT: () => this.SUBRULE(this.aggregateFunction) }, { ALT: () => this.SUBRULE(this.dateFunction) }, { ALT: () => this.SUBRULE(this.locationFunction) }, ]); this.OPTION(() => { this.OR1([{ ALT: () => this.CONSUME(lexer.Asc, { LABEL: 'order' }) }, { ALT: () => this.CONSUME(lexer.Desc, { LABEL: 'order' }) }]); }); this.OPTION1(() => { this.CONSUME(lexer.Nulls); this.OR2([{ ALT: () => this.CONSUME(lexer.First, { LABEL: 'nulls' }) }, { ALT: () => this.CONSUME(lexer.Last, { LABEL: 'nulls' }) }]); }); }); limitClause = this.RULE('limitClause', () => { this.CONSUME(lexer.Limit); this.CONSUME(lexer.UnsignedInteger, { LABEL: 'value' }); }); offsetClause = this.RULE('offsetClause', () => { this.CONSUME(lexer.Offset); this.CONSUME(lexer.UnsignedInteger, { LABEL: 'value' }); }); dateFunction = this.RULE('dateFunction', () => { this.OR(this.$_dateFunctionOr || (this.$_dateFunctionOr = [ { ALT: () => this.CONSUME(lexer.CalendarMonth, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.CalendarQuarter, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.CalendarYear, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.DayInMonth, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.DayInWeek, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.DayInYear, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.DayOnly, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.FiscalMonth, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.FiscalQuarter, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.FiscalYear, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.HourInDay, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.WeekInMonth, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.WeekInYear, { LABEL: 'fn' }) }, ])); this.SUBRULE(this.functionExpression); }); aggregateFunction = this.RULE('aggregateFunction', () => { this.OR(this.$_aggregateFunction || (this.$_aggregateFunction = [ { ALT: () => this.CONSUME(lexer.Avg, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.Count, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.CountDistinct, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.Min, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.Max, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.Sum, { LABEL: 'fn' }) }, ])); this.SUBRULE(this.functionExpression, { ARGS: [true] }); }); fieldsFunction = this.RULE('fieldsFunction', () => { this.CONSUME(lexer.Fields, { LABEL: 'fn' }); this.CONSUME(lexer.LParen); this.CONSUME(lexer.FieldsFunctionParamIdentifier, { LABEL: 'params' }); this.CONSUME(lexer.RParen); }); otherFunction = this.RULE('otherFunction', () => { this.OR(this.$_otherFunction || (this.$_otherFunction = [ { ALT: () => this.CONSUME(lexer.Format, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.Tolabel, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.ConvertTimeZone, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.ConvertCurrency, { LABEL: 'fn' }) }, { ALT: () => this.CONSUME(lexer.Grouping, { LABEL: 'fn' }) }, ])); this.SUBRULE(this.functionExpression); }); cubeFunction = this.RULE('cubeFunction', () => { this.CONSUME(lexer.Cube, { LABEL: 'fn' }); this.SUBRULE(this.functionExpression); }); rollupFunction = this.RULE('rollupFunction', () => { this.CONSUME(lexer.Rollup, { LABEL: 'fn' }); this.SUBRULE(this.functionExpression); }); functionExpression = this.RULE('functionExpression', (skipAggregate) => { this.CONSUME(lexer.LParen); this.MANY_SEP({ SEP: lexer.Comma, DEF: () => { this.OR([ { GATE: () => !skipAggregate, ALT: () => this.SUBRULE(this.aggregateFunction, { LABEL: 'params' }) }, { ALT: () => this.SUBRULE(this.otherFunction, { LABEL: 'params' }) }, { ALT: () => this.CONSUME(lexer.StringIdentifier, { LABEL: 'params' }) }, { ALT: () => this.CONSUME(lexer.NumberIdentifier, { LABEL: 'params' }) }, { ALT: () => this.CONSUME(lexer.Identifier, { LABEL: 'params' }) }, ]); }, }); this.CONSUME(lexer.RParen); }); locationFunction = this.RULE('locationFunction', () => { this.CONSUME(lexer.Distance); this.CONSUME(lexer.LParen); this.CONSUME(lexer.Identifier, { LABEL: 'location1' }); this.CONSUME(lexer.Comma); this.OR([ { ALT: () => this.SUBRULE(this.geolocationFunction, { LABEL: 'location2' }) }, { ALT: () => this.CONSUME1(lexer.Identifier, { LABEL: 'location2' }) }, ]); this.CONSUME1(lexer.Comma); this.CONSUME(lexer.GeolocationUnit, { LABEL: 'unit' }); this.CONSUME(lexer.RParen); }); geolocationFunction = this.RULE('geolocationFunction', () => { this.CONSUME(lexer.Geolocation); this.CONSUME(lexer.LParen); this.CONSUME(lexer.NumberIdentifier, { LABEL: 'latitude' }); this.CONSUME(lexer.Comma); this.CONSUME1(lexer.NumberIdentifier, { LABEL: 'longitude' }); this.CONSUME(lexer.RParen); }); expressionPartWithNegation = this.RULE('expressionPartWithNegation', (parenCount) => { let leftParenCount = 0; this.MANY(() => { this.CONSUME(lexer.LParen); leftParenCount++; }); this.CONSUME(lexer.Not, { LABEL: 'expressionNegation' }); if (parenCount && leftParenCount) { parenCount.left += leftParenCount; } }); expression = this.RULE('expression', (parenCount, allowSubquery, allowAggregateFn, allowLocationFn) => { this.OPTION1(() => { this.MANY1(() => { this.CONSUME(lexer.LParen); if (parenCount) { parenCount.left++; } }); }); this.OR1([ { GATE: () => !!allowAggregateFn, ALT: () => this.SUBRULE(this.aggregateFunction, { LABEL: 'lhs' }) }, { GATE: () => !!allowLocationFn, ALT: () => this.SUBRULE(this.locationFunction, { LABEL: 'lhs' }) }, { ALT: () => this.SUBRULE(this.dateFunction, { LABEL: 'lhs' }) }, { ALT: () => this.SUBRULE(this.otherFunction, { LABEL: 'lhs' }) }, { ALT: () => this.CONSUME(lexer.Identifier, { LABEL: 'lhs' }) }, ]); this.OR2([ { ALT: () => this.SUBRULE(this.expressionWithRelationalOperator, { LABEL: 'operator' }) }, { ALT: () => this.SUBRULE(this.expressionWithSetOperator, { LABEL: 'operator', ARGS: [allowSubquery] }) }, ]); this.OPTION3(() => { this.MANY2({ GATE: () => (parenCount ? parenCount.left > parenCount.right : true), DEF: () => { this.CONSUME(lexer.RParen); if (parenCount) { parenCount.right++; } }, }); }); }); expressionWithRelationalOperator = this.RULE('expressionWithRelationalOperator', () => { this.SUBRULE(this.relationalOperator); this.SUBRULE(this.atomicExpression, { LABEL: 'rhs' }); }); expressionWithSetOperator = this.RULE('expressionWithSetOperator', (allowSubquery) => { this.SUBRULE(this.setOperator); this.SUBRULE2(this.atomicExpression, { LABEL: 'rhs', ARGS: [true, allowSubquery] }); }); atomicExpression = this.RULE('atomicExpression', (isArray, allowSubquery) => { this.OR(this.$_atomicExpression || (this.$_atomicExpression = [ { GATE: () => this.allowApexBindVariables, ALT: () => this.SUBRULE(this.apexBindVariableExpression) }, { GATE: () => isArray, ALT: () => this.SUBRULE(this.arrayExpression) }, { GATE: () => isArray && allowSubquery, ALT: () => this.SUBRULE(this.whereClauseSubqueryIdentifier) }, { GATE: () => !isArray, ALT: () => this.CONSUME(lexer.JitterbitVariable, { LABEL: 'jitterbitVariableExpression' }) }, { GATE: () => !isArray, ALT: () => this.CONSUME(lexer.DateIdentifier) }, { GATE: () => !isArray, ALT: () => this.CONSUME(lexer.CurrencyPrefixedDecimal, { LABEL: 'CurrencyPrefixedDecimal' }) }, { GATE: () => !isArray, ALT: () => this.CONSUME(lexer.CurrencyPrefixedInteger, { LABEL: 'CurrencyPrefixedInteger' }) }, { GATE: () => !isArray, ALT: () => this.CONSUME(lexer.NumberIdentifier) }, { GATE: () => !isArray, ALT: () => this.CONSUME(lexer.Null) }, { GATE: () => !isArray, ALT: () => this.SUBRULE(this.booleanValue) }, { GATE: () => !isArray, ALT: () => this.CONSUME(lexer.DateLiteral) }, { GATE: () => !isArray, ALT: () => this.SUBRULE(this.dateNLiteral) }, { GATE: () => !isArray, ALT: () => this.CONSUME(lexer.GeolocationUnit, { LABEL: 'StringIdentifier' }) }, { GATE: () => !isArray, ALT: () => this.CONSUME(lexer.StringIdentifier) }, ])); }); apexBindVariableExpression = this.RULE('apexBindVariableExpression', () => { this.CONSUME(lexer.Colon); this.OPTION(() => { this.SUBRULE(this.apexBindVariableNewInstantiation, { LABEL: 'apex' }); this.OPTION1(() => { this.CONSUME(lexer.Decimal); }); }); this.MANY_SEP({ SEP: lexer.Decimal, DEF: () => { this.OR(this.$_apexBindVariableExpression || (this.$_apexBindVariableExpression = [ { ALT: () => this.SUBRULE(this.apexBindVariableFunctionCall, { LABEL: 'apex' }) }, { ALT: () => this.SUBRULE(this.apexBindVariableIdentifier, { LABEL: 'apex' }) }, ])); }, }); }); apexBindVariableIdentifier = this.RULE('apexBindVariableIdentifier', () => { this.CONSUME(lexer.Identifier); this.OPTION(() => this.SUBRULE(this.apexBindVariableFunctionArrayAccessor)); }); apexBindVariableNewInstantiation = this.RULE('apexBindVariableNewInstantiation', () => { this.CONSUME(lexer.ApexNew, { LABEL: 'new' }); this.CONSUME(lexer.Identifier, { LABEL: 'function' }); this.OPTION(() => { this.SUBRULE(this.apexBindVariableGeneric); }); this.SUBRULE(this.apexBindVariableFunctionParams); this.OPTION1(() => this.SUBRULE(this.apexBindVariableFunctionArrayAccessor)); }); apexBindVariableFunctionCall = this.RULE('apexBindVariableFunctionCall', () => { this.CONSUME(lexer.Identifier, { LABEL: 'function' }); this.SUBRULE(this.apexBindVariableFunctionParams); this.OPTION(() => this.SUBRULE(this.apexBindVariableFunctionArrayAccessor)); }); apexBindVariableGeneric = this.RULE('apexBindVariableGeneric', () => { this.CONSUME(lexer.LessThan); this.AT_LEAST_ONE_SEP({ SEP: lexer.Comma, DEF: () => { this.CONSUME(lexer.Identifier, { LABEL: 'parameter' }); }, }); this.CONSUME(lexer.GreaterThan); }); apexBindVariableFunctionParams = this.RULE('apexBindVariableFunctionParams', () => { this.CONSUME(lexer.LParen); this.MANY_SEP({ SEP: lexer.Comma, DEF: () => { this.CONSUME(lexer.Identifier, { LABEL: 'parameter' }); }, }); this.CONSUME(lexer.RParen); }); apexBindVariableFunctionArrayAccessor = this.RULE('apexBindVariableFunctionArrayAccessor', () => { this.CONSUME(lexer.LSquareBracket); this.OR([ { ALT: () => this.CONSUME(lexer.UnsignedInteger, { LABEL: 'value' }) }, { ALT: () => this.CONSUME(lexer.Identifier, { LABEL: 'value' }) }, ]); this.CONSUME(lexer.RSquareBracket); }); arrayExpression = this.RULE('arrayExpression', () => { this.CONSUME(lexer.LParen); this.AT_LEAST_ONE_SEP({ SEP: lexer.Comma, DEF: () => { this.OR(this.$_arrayExpression || (this.$_arrayExpression = [ { ALT: () => this.CONSUME(lexer.CurrencyPrefixedDecimal, { LABEL: 'value' }) }, { ALT: () => this.CONSUME(lexer.CurrencyPrefixedInteger, { LABEL: 'value' }) }, { ALT: () => this.CONSUME(lexer.NumberIdentifier, { LABEL: 'value' }) }, { ALT: () => this.CONSUME(lexer.DateIdentifier, { LABEL: 'value' }) }, { ALT: () => this.CONSUME(lexer.Null, { LABEL: 'value' }) }, { ALT: () => this.CONSUME(lexer.True, { LABEL: 'value' }) }, { ALT: () => this.CONSUME(lexer.False, { LABEL: 'value' }) }, { ALT: () => this.CONSUME(lexer.DateLiteral, { LABEL: 'value' }) }, { ALT: () => this.SUBRULE(this.dateNLiteral, { LABEL: 'value' }) }, { ALT: () => this.CONSUME(lexer.GeolocationUnit, { LABEL: 'value' }) }, { ALT: () => this.CONSUME(lexer.StringIdentifier, { LABEL: 'value' }) }, ])); }, }); this.CONSUME(lexer.RParen); }); relationalOperator = this.RULE('relationalOperator', () => { this.OR(this.$_relationalOperator || (this.$_relationalOperator = [ { ALT: () => this.CONSUME(lexer.Equal, { LABEL: 'operator' }) }, { ALT: () => this.CONSUME(lexer.NotEqual, { LABEL: 'operator' }) }, { ALT: () => this.CONSUME(lexer.GreaterThan, { LABEL: 'operator' }) }, { ALT: () => this.CONSUME(lexer.GreaterThanOrEqual, { LABEL: 'operator' }) }, { ALT: () => this.CONSUME(lexer.LessThan, { LABEL: 'operator' }) }, { ALT: () => this.CONSUME(lexer.LessThanOrEqual, { LABEL: 'operator' }) }, { ALT: () => this.CONSUME(lexer.Like, { LABEL: 'operator' }) }, ])); }); setOperator = this.RULE('setOperator', () => { this.OR([ { ALT: () => this.CONSUME(lexer.In, { LABEL: 'operator' }) }, { ALT: () => this.SUBRULE(this.notInOperator, { LABEL: 'notIn' }) }, { ALT: () => this.CONSUME(lexer.Includes, { LABEL: 'operator' }) }, { ALT: () => this.CONSUME(lexer.Excludes, { LABEL: 'operator' }) }, ]); }); notInOperator = this.RULE('notInOperator', () => { this.CONSUME(lexer.Not, { LABEL: 'operator' }); this.CONSUME(lexer.In, { LABEL: 'operator' }); }); booleanValue = this.RULE('booleanValue', () => { this.OR([ { ALT: () => this.CONSUME(lexer.True, { LABEL: 'boolean' }) }, { ALT: () => this.CONSUME(lexer.False, { LABEL: 'boolean' }) }, ]); }); dateNLiteral = this.RULE('dateNLiteral', () => { this.CONSUME(lexer.DateNLiteral, { LABEL: 'dateNLiteral' }); this.CONSUME(lexer.Colon); this.OR1([ { ALT: () => this.CONSUME(lexer.UnsignedInteger, { LABEL: 'variable' }) }, { ALT: () => this.CONSUME(lexer.SignedInteger, { LABEL: 'variable' }) }, ]); }); forViewOrReference = this.RULE('forViewOrReference', () => { this.CONSUME(lexer.For); this.OR([ { ALT: () => this.CONSUME(lexer.View, { LABEL: 'value' }) }, { ALT: () => this.CONSUME(lexer.Reference, { LABEL: 'value' }) }, { ALT: () => this.CONSUME(lexer.Update, { LABEL: 'value' }) }, ]); }); updateTrackingViewstat = this.RULE('updateTrackingViewstat', () => { this.CONSUME(lexer.Update); this.OR([ { ALT: () => this.CONSUME(lexer.Tracking, { LABEL: 'value' }) }, { ALT: () => this.CONSUME(lexer.Viewstat, { LABEL: 'value' }) }, ]); }); getParenCount(parenCount) { return parenCount || { right: 0, left: 0 }; } } let parser = new SoqlParser(); export function parse(soql, options) { const { allowApexBindVariables, logErrors, ignoreParseErrors, allowPartialQuery } = options || { allowApexBindVariables: false, logErrors: false, ignoreParseErrors: false, }; const lexResult = lexer.lex(soql); if (lexResult.errors.length > 0) { if (logErrors) { console.log('Lexing Errors:'); console.log(JSON.stringify(lexResult.errors, null, 4)); } throw new LexingError(lexResult.errors[0]); } if (parser.ignoreParseErrors !== ignoreParseErrors) { parser = new SoqlParser({ ignoreParseErrors }); } parser.input = lexResult.tokens; parser.allowApexBindVariables = allowApexBindVariables || false; let cst; if (allowPartialQuery) { cst = parser.selectStatementPartial(); } else { cst = parser.selectStatement(); } if (parser.errors.length > 0) { if (logErrors) { console.log('Parsing Errors:'); console.log(JSON.stringify(parser.errors, null, 4)); } if (!ignoreParseErrors) { throw new ParsingError(parser.errors[0]); } } return { cst, parseErrors: parser.errors.map(err => new ParsingError(err)), }; }