/* BuildInstrument2.c */
/*****************************************************************************/
/*                                                                           */
/*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
/*    Copyright (C) 1994  Thomas R. Lawrence                                 */
/*                                                                           */
/*    This program is free software; you can redistribute it and/or modify   */
/*    it under the terms of the GNU General Public License as published by   */
/*    the Free Software Foundation; either version 2 of the License, or      */
/*    (at your option) any later version.                                    */
/*                                                                           */
/*    This program is distributed in the hope that it will be useful,        */
/*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
/*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
/*    GNU General Public License for more details.                           */
/*                                                                           */
/*    You should have received a copy of the GNU General Public License      */
/*    along with this program; if not, write to the Free Software            */
/*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
/*                                                                           */
/*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
/*                                                                           */
/*****************************************************************************/

#include "MiscInfo.h"
#include "Audit.h"
#include "Debug.h"
#include "Definitions.h"

#include "BuildInstrument2.h"
#include "BuildInstrument3.h"
#include "FixedPoint.h"
#include "SampleConsts.h"
#include "InstrumentStructure.h"
#include "CompilerScanner.h"
#include "Memory.h"
#include "LFOSpecifier.h"
#include "LFOListSpecifier.h"
#include "OscillatorSpecifier.h"
#include "OscillatorListSpecifier.h"
#include "SampleSelector.h"
#include "DataMunging.h"
#include "AnalyzerSpec.h"
#include "EffectSpecList.h"
#include "DelayEffectSpec.h"
#include "Envelope.h"
#include "WaveTableList.h"
#include "AlgoWaveTableList.h"
#include "NonlinearProcSpec.h"
#include "TrashTracker.h"




/*    1:   <instr_definition>      ::= instrument ( <instr_list> ) */
/* FIRST SET: */
/*  <instr_definition>      : {instrument} */
/* FOLLOW SET: */
/*  <instr_definition>      : {$$$} */
BuildInstrErrors						ParseInstrDefinition(InstrumentRec* Instrument,
															ScannerRec* Scanner, long* ErrorLine,
															struct SampleListRec* SampleList,
															struct AlgoSampListRec* AlgoSampList,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		unsigned long							Required;

		CheckPtrExistence(Instrument);
		CheckPtrExistence(Scanner);

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if ((GetTokenType(Token) != eTokenKeyword)
			|| (GetTokenKeywordTag(Token) != eKeywordInstrument))
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedInstrument;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenOpenParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedOpenParen;
			}

		Required = 0;
		Error = ParseInstrList(Instrument,Scanner,ErrorLine,&Required,0,SampleList,
			AlgoSampList,WaveTableList,AlgoWaveTableList);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}
		if (Required != INSTRLIST_REQUIREDMASK)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrSomeRequiredInstrParamsMissing;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenCloseParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedCloseParen;
			}

		return eBuildInstrNoError;
	}




/*    2:   <instr_list>            ::= <instr_elem> ; <instr_list> */
/*    3:                           ::=  */
/* FIRST SET: */
/*  <instr_list>            : {loudness, frequencylfo, oscillator, <instr_elem>} */
/* FOLLOW SET: */
/*  <instr_list>            : {)} */
BuildInstrErrors						ParseInstrList(InstrumentRec* Instrument,
															ScannerRec* Scanner, long* ErrorLine,
															unsigned long* RequiredDefinitions,
															unsigned long OnceOnlyDefinitions,
															struct SampleListRec* SampleList,
															struct AlgoSampListRec* AlgoSampList,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;

		CheckPtrExistence(Instrument);
		CheckPtrExistence(Scanner);

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}

		if (GetTokenType(Token) == eTokenCloseParen)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		 else
			{
				UngetToken(Scanner,Token);

				Error = ParseInstrElem(Instrument,Scanner,ErrorLine,RequiredDefinitions,
					&OnceOnlyDefinitions,SampleList,AlgoSampList,WaveTableList,AlgoWaveTableList);
				if (Error != eBuildInstrNoError)
					{
						return Error;
					}

				/* get semicolon */
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if (GetTokenType(Token) != eTokenSemicolon)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedSemicolon;
					}

				return ParseInstrList(Instrument,Scanner,ErrorLine,RequiredDefinitions,
					OnceOnlyDefinitions,SampleList,AlgoSampList,WaveTableList,AlgoWaveTableList);
			}
		EXECUTE(PRERR(ForceAbort,"ParseInstrList:  control reached end of function"));
	}




/*    4:   <instr_elem>            ::= loudness <number> */
/*    5:                           ::= frequencylfo ( <lfo_definition> ) */
/*    6:                           ::= oscillator <identifier> ( <oscillator_definition> ) */
/*  XXX:                           ::= trackeffect <trackeffect> */
/* FIRST SET: */
/*  <instr_elem>            : {loudness, frequencylfo, oscillator} */
/* FOLLOW SET: */
/*  <instr_elem>            : {;} */
BuildInstrErrors						ParseInstrElem(InstrumentRec* Instrument,
															ScannerRec* Scanner, long* ErrorLine,
															unsigned long* RequiredDefinitions,
															unsigned long* OnceOnlyDefinitions,
															struct SampleListRec* SampleList,
															struct AlgoSampListRec* AlgoSampList,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;

		CheckPtrExistence(Instrument);
		CheckPtrExistence(Scanner);

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedInstrumentMember;
			}

		if (GetTokenKeywordTag(Token) == eKeywordLoudness)
			{
				double										Number;

				if ((*OnceOnlyDefinitions & INSTRLIST_ONCEONLY_LOUDNESS) != 0)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrMultipleInstrLoudness;
					}
				Error = ParseNumber(Scanner,ErrorLine,&Number);
				if (Error != eBuildInstrNoError)
					{
						return Error;
					}
				InstrumentSetOverallLoudness(Instrument,Number);
				*OnceOnlyDefinitions |= INSTRLIST_ONCEONLY_LOUDNESS;
			}
		else if (GetTokenKeywordTag(Token) == eKeywordFrequencylfo)
			{
				unsigned long							LFORequired;
				LFOSpecRec*								LFO;

				/* allocate the LFO */
				LFO = NewLFOSpecifier();
				if (LFO == NIL)
					{
					 LFOAllocFailurePoint1:
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				/* the default arithmetic mode for pitch LFO is halfsteps */
				SetLFOSpecAddingMode(LFO,eLFOHalfSteps);
				if (!LFOListSpecAppendNewEntry(GetInstrumentFrequencyLFOList(Instrument),LFO))
					{
					 LFOAllocFailurePoint2:
						DisposeLFOSpecifier(LFO);
						goto LFOAllocFailurePoint1;
					}

				/* open paren */
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if (GetTokenType(Token) != eTokenOpenParen)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedOpenParen;
					}

				/* parse the low frequency operator */
				LFORequired = 0;
				Error = ParseLfoDefinition(LFO,Scanner,ErrorLine,&LFORequired,0,WaveTableList,
					AlgoWaveTableList);
				if (Error != eBuildInstrNoError)
					{
						return Error;
					}
				if (LFORequired != LFODEFINITION_REQUIREDMASK)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrSomeRequiredLFOParamsMissing;
					}

				/* close paren */
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if (GetTokenType(Token) != eTokenCloseParen)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedCloseParen;
					}
			}
		else if (GetTokenKeywordTag(Token) == eKeywordOscillator)
			{
				char*											Identifier;
				unsigned long							OscillatorRequired;
				OscillatorRec*						Oscillator;

				/* allocate a new oscillator & add it to the instrument */
				Oscillator = NewOscillatorSpecifier();
				if (Oscillator == NIL)
					{
					 OscillatorAllocFailurePoint1:
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if (!AppendOscillatorToList(GetInstrumentOscillatorList(Instrument),Oscillator))
					{
					 OscillatorAllocFailurePoint2:
						DisposeOscillatorSpecifier(Oscillator);
						goto OscillatorAllocFailurePoint1;
					}

				/* get the oscillator's name */
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if (GetTokenType(Token) != eTokenOpenParen)
					{
						UngetToken(Scanner,Token);
						Error = ParseIdentifier(Scanner,ErrorLine,&Identifier);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
						CheckPtrExistence(Identifier);
						/* throw away oscillator name since we don't use them anymore */
						ReleasePtr(Identifier);
					}
				 else
					{
						UngetToken(Scanner,Token);
					}

				/* eat the open paren */
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if (GetTokenType(Token) != eTokenOpenParen)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedOpenParen;
					}

				/* parse oscillator */
				OscillatorRequired = 0;
				Error = ParseOscillatorDefinition(Oscillator,Scanner,ErrorLine,
					&OscillatorRequired,0,WaveTableList,AlgoWaveTableList);
				if (Error != eBuildInstrNoError)
					{
						return Error;
					}
				if (OscillatorRequired != OSCILLATORDEFINITION_REQUIREDMASK)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrSomeRequiredOscillatorParamsMissing;
					}

				/* resolve sample/wave table data references */
				switch (OscillatorGetWhatKindItIs(Oscillator))
					{
						default:
							EXECUTE(PRERR(ForceAbort,"ParseInstrElem:  bad oscillator type"));
							break;
						case eOscillatorSampled:
							if (!ResolveSamplesInSampleList(OscillatorGetSampleIntervalList(
								Oscillator),SampleList,AlgoSampList))
								{
									*ErrorLine = GetCurrentLineNumber(Scanner);
									return eBuildInstrSomeSamplesDontExist;
								}
							break;
						case eOscillatorWaveTable:
							if (!ResolveWaveTablesInSampleList(OscillatorGetSampleIntervalList(
								Oscillator),WaveTableList,AlgoWaveTableList))
								{
									*ErrorLine = GetCurrentLineNumber(Scanner);
									return eBuildInstrSomeWaveTablesDontExist;
								}
							break;
					}

				/* eat the close paren */
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if (GetTokenType(Token) != eTokenCloseParen)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedCloseParen;
					}

				*RequiredDefinitions |= INSTRLIST_REQUIRED_OSCILLATOR;
			}
		else if (GetTokenKeywordTag(Token) == eKeywordTrackeffect)
			{
				Error = ParseTrackEffect(GetInstrumentEffectSpecList(Instrument),
					Scanner,ErrorLine,WaveTableList,AlgoWaveTableList);
				if (Error != eBuildInstrNoError)
					{
						return Error;
					}
			}
		else
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedInstrumentMember;
			}

		return eBuildInstrNoError;
	}




/*   80:   <number>                ::= <integertoken> */
/*   81:                           ::= <floattoken> */
/* FIRST SET: */
/*  <number>                : {<integertoken>, <floattoken>} */
/* FOLLOW SET: */
/*  <number>                : {<integertoken>, <floattoken>, ), ;, type, */
/*       exponential, linear, to, sustainpoint, ampaccent1, ampaccent2, */
/*       ampaccent3, ampaccent4, ampfreq, rateaccent1, rateaccent2, rateaccent3, */
/*       rateaccent4, ratefreq, originadjust, <number>, <env_point_list>, */
/*       <env_point_elem>, <env_attributes>, <env_one_attribute>} */
BuildInstrErrors						ParseNumber(ScannerRec* Scanner, long* ErrorLine,
															double* NumberOut)
	{
		TokenRec*									Token;
		MyBoolean									Negative;

		CheckPtrExistence(Scanner);

		Negative = False;

	 GetAnotherToken:
		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}

		switch (GetTokenType(Token))
			{
				default:
					*ErrorLine = GetCurrentLineNumber(Scanner);
					return eBuildInstrExpectedNumber;
				case eTokenInteger:
					*NumberOut = GetTokenIntegerValue(Token);
					break;
				case eTokenSingle:
					*NumberOut = GetTokenSingleValue(Token);
					break;
				case eTokenDouble:
					*NumberOut = GetTokenDoubleValue(Token);
					break;
				case eTokenFixed:
					*NumberOut = largefixed2double(GetTokenFixedValue(Token));
					break;
				case eTokenMinus:
					Negative = !Negative;
					goto GetAnotherToken;
			}

		if (Negative)
			{
				*NumberOut = - *NumberOut;
			}

		return eBuildInstrNoError;
	}




/*    7:   <lfo_definition>        ::= <lfo_elem> ; <lfo_definition> */
/*    8:                           ::=  */
/* FIRST SET: */
/*  <lfo_definition>        : {oscillator, freqenvelope, modulation, */
/*       ampenvelope, <lfo_elem>} */
/* FOLLOW SET: */
/*  <lfo_definition>        : {)} */
BuildInstrErrors						ParseLfoDefinition(LFOSpecRec* LFO, ScannerRec* Scanner,
															long* ErrorLine, unsigned long* RequiredDefinitions,
															unsigned long OnceOnlyDefinitions,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;

		CheckPtrExistence(LFO);
		CheckPtrExistence(Scanner);

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}

		if (GetTokenType(Token) == eTokenCloseParen)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		 else
			{
				UngetToken(Scanner,Token);

				Error = ParseLfoElem(LFO,Scanner,ErrorLine,RequiredDefinitions,
					&OnceOnlyDefinitions,WaveTableList,AlgoWaveTableList);
				if (Error != eBuildInstrNoError)
					{
						return Error;
					}

				/* get semicolon */
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if (GetTokenType(Token) != eTokenSemicolon)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedSemicolon;
					}

				return ParseLfoDefinition(LFO,Scanner,ErrorLine,RequiredDefinitions,
					OnceOnlyDefinitions,WaveTableList,AlgoWaveTableList);
			}

		EXECUTE(PRERR(ForceAbort,"ParseLfoDefinition:  control reached end of function"));
	}




/* the identifier string returned from here is NOT trash-tracker allocated. */
/*   78:   <identifier>            ::= <identifiertoken> */
/*   79:                           ::= <stringtoken> */
/* FIRST SET: */
/*  <identifier>            : {<identifiertoken>, <stringtoken>} */
/* FOLLOW SET: */
/*  <identifier>            : {<integertoken>, <floattoken>, (, scale, */
/*       <number>} */
BuildInstrErrors						ParseIdentifier(ScannerRec* Scanner, long* ErrorLine,
															char** IdentifierOut)
	{
		TokenRec*									Token;

		CheckPtrExistence(Scanner);

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}

		if (GetTokenType(Token) == eTokenIdentifier)
			{
				*IdentifierOut = CopyPtr(GetTokenIdentifierString(Token));
			}
		else if (GetTokenType(Token) == eTokenString)
			{
				*IdentifierOut = CopyPtr(GetTokenStringValue(Token));
			}
		else
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedStringOrIdentifier;
			}

		if (*IdentifierOut == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		SetTag(*IdentifierOut,"BuildInstr: ParseIdentifier");

		return eBuildInstrNoError;
	}




/*   27:   <oscillator_definition> ::= <oscillator_elem> ; */
/*       <oscillator_definition> */
/*   28:                           ::=  */
/* FIRST SET: */
/*  <oscillator_definition> : {loudness, type, samplelist, */
/*       freqmultiplier, freqdivisor, loudnessenvelope, */
/*       loudnesslfo, indexenvelope, indexlfo, <oscillator_elem>} */
/* FOLLOW SET: */
/*  <oscillator_definition> : {)} */
BuildInstrErrors						ParseOscillatorDefinition(OscillatorRec* Oscillator,
															ScannerRec* Scanner, long* ErrorLine,
															unsigned long* RequiredDefinitions,
															unsigned long OnceOnlyDefinitions,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;

		CheckPtrExistence(Oscillator);
		CheckPtrExistence(Scanner);

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}

		if (GetTokenType(Token) == eTokenCloseParen)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		 else
			{
				UngetToken(Scanner,Token);

				Error = ParseOscillatorElem(Oscillator,Scanner,ErrorLine,RequiredDefinitions,
					&OnceOnlyDefinitions,WaveTableList,AlgoWaveTableList);
				if (Error != eBuildInstrNoError)
					{
						return Error;
					}

				/* get semicolon */
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if (GetTokenType(Token) != eTokenSemicolon)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedSemicolon;
					}

				return ParseOscillatorDefinition(Oscillator,Scanner,ErrorLine,
					RequiredDefinitions,OnceOnlyDefinitions,WaveTableList,AlgoWaveTableList);
			}

		EXECUTE(PRERR(ForceAbort,"ParseOscillatorDefinition:  control reached end of function"));
	}




/*    9:   <lfo_elem>              ::= freqenvelope ( <envelope_definition> ) */
/*   10:                           ::= ampenvelope ( <envelope_definition> ) */
/*   11:                           ::= oscillator <oscillator_type> */
/*   12:                           ::= modulation <modulation_type> */
/*  XXX:                           ::= freqlfo ( <lfo_definition> ) */
/*  XXX:                           ::= amplfo ( <lfo_definition> ) */
/* FIRST SET: */
/*  <lfo_elem>              : {oscillator, freqenvelope, modulation, ampenvelope} */
/* FOLLOW SET: */
/*  <lfo_elem>              : {;} */
BuildInstrErrors						ParseLfoElem(LFOSpecRec* LFO, ScannerRec* Scanner,
															long* ErrorLine, unsigned long* RequiredDefinitions,
															unsigned long* OnceOnlyDefinitions,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		unsigned long							Required;

		CheckPtrExistence(LFO);
		CheckPtrExistence(Scanner);

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedLFOMember;
			}

		switch (GetTokenKeywordTag(Token))
			{
				default:
					*ErrorLine = GetCurrentLineNumber(Scanner);
					return eBuildInstrExpectedLFOMember;

				case eKeywordFreqlfo:
					{
						LFOSpecRec*						LFOSpec;

						/* open paren */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (GetTokenType(Token) != eTokenOpenParen)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedOpenParen;
							}

						LFOSpec = NewLFOSpecifier();
						if (LFOSpec == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (!LFOListSpecAppendNewEntry(GetLFOSpecFrequencyLFOList(LFO),LFOSpec))
							{
								DisposeLFOSpecifier(LFOSpec);
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}

						Required = 0;
						Error = ParseLfoDefinition(LFOSpec,Scanner,ErrorLine,&Required,0,
							WaveTableList,AlgoWaveTableList);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
						if (Required != LFODEFINITION_REQUIREDMASK)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrSomeRequiredLFOParamsMissing;
							}

						/* close paren */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (GetTokenType(Token) != eTokenCloseParen)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedCloseParen;
							}
					}
					break;

				case eKeywordAmplfo:
					{
						LFOSpecRec*						LFOSpec;

						/* open paren */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (GetTokenType(Token) != eTokenOpenParen)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedOpenParen;
							}

						LFOSpec = NewLFOSpecifier();
						if (LFOSpec == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (!LFOListSpecAppendNewEntry(GetLFOSpecAmplitudeLFOList(LFO),LFOSpec))
							{
								DisposeLFOSpecifier(LFOSpec);
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}

						Required = 0;
						Error = ParseLfoDefinition(LFOSpec,Scanner,ErrorLine,&Required,0,
							WaveTableList,AlgoWaveTableList);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
						if (Required != LFODEFINITION_REQUIREDMASK)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrSomeRequiredLFOParamsMissing;
							}

						/* close paren */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (GetTokenType(Token) != eTokenCloseParen)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedCloseParen;
							}
					}
					break;

				case eKeywordFreqenvelope:
					if ((*OnceOnlyDefinitions & LFODEFINITION_ONCEONLY_FREQENVELOPE) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleLFOFreqEnvelope;
						}

					/* open paren */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenOpenParen)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedOpenParen;
						}

					Required = 0;
					Error = ParseEnvelopeDefinition(GetLFOSpecFrequencyEnvelope(LFO),
						Scanner,ErrorLine,&Required,0);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					if (Required != ENVELOPEDEFINITION_REQUIREDMASK)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrSomeRequiredEnvelopeParamsMissing;
						}

					/* close paren */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenCloseParen)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedCloseParen;
						}

					*OnceOnlyDefinitions |= LFODEFINITION_ONCEONLY_FREQENVELOPE;
					break;

				case eKeywordAmpenvelope:
					if ((*OnceOnlyDefinitions & LFODEFINITION_ONCEONLY_AMPENVELOPE) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleLFOAmpEnvelope;
						}

					/* open paren */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenOpenParen)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedOpenParen;
						}

					Required = 0;
					Error = ParseEnvelopeDefinition(GetLFOSpecAmplitudeEnvelope(LFO),
						Scanner,ErrorLine,&Required,0);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					if (Required != ENVELOPEDEFINITION_REQUIREDMASK)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrSomeRequiredEnvelopeParamsMissing;
						}

					/* close paren */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenCloseParen)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedCloseParen;
						}

					*RequiredDefinitions |= LFODEFINITION_REQUIRED_AMPENVELOPE;
					*OnceOnlyDefinitions |= LFODEFINITION_ONCEONLY_AMPENVELOPE;
					break;

				case eKeywordOscillator:
					if ((*OnceOnlyDefinitions & LFODEFINITION_ONCEONLY_OSCILLATORTYPE) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleLFOOscillatorType;
						}

					/*  13:   <oscillator_type>       ::= constant */
					/*  14:                           ::= signsine */
					/*  15:                           ::= plussine */
					/*  16:                           ::= signtriangle */
					/*  17:                           ::= plustriangle */
					/*  18:                           ::= signsquare <number> */
					/*  19:                           ::= plussquare <number> */
					/*  20:                           ::= signramp <number> */
					/*  21:                           ::= plusramp <number> */
					/*  22:                           ::= signlinfuzz <number> <seed> (square | triangle) */
					/*  23:                           ::= pluslinfuzz <number> <seed> (square | triangle) */
					/*  XX:                           ::= wavetable ( <samplelist_definition> */
					/*                                    ) ( <envelope_definition> ) */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenKeyword)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedLFOOscillatorType;
						}
					switch (GetTokenKeywordTag(Token))
						{
							default:
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedLFOOscillatorType;

							case eKeywordConstant:
								SetLFOSpecOscillatorType(LFO,eLFOConstant1);
								break;

							case eKeywordSignsine:
								SetLFOSpecOscillatorType(LFO,eLFOSignedSine);
								break;

							case eKeywordPlussine:
								SetLFOSpecOscillatorType(LFO,eLFOPositiveSine);
								break;

							case eKeywordSigntriangle:
								SetLFOSpecOscillatorType(LFO,eLFOSignedTriangle);
								break;

							case eKeywordPlustriangle:
								SetLFOSpecOscillatorType(LFO,eLFOPositiveTriangle);
								break;

							case eKeywordSignsquare:
								{
									double					Number;

									SetLFOSpecOscillatorType(LFO,eLFOSignedSquare);

									Error = ParseNumber(Scanner,ErrorLine,&Number);
									if (Error != eBuildInstrNoError)
										{
											return Error;
										}
									SetLFOSpecExtraValue(LFO,Number);
								}
								break;

							case eKeywordPlussquare:
								{
									double					Number;

									SetLFOSpecOscillatorType(LFO,eLFOPositiveSquare);

									Error = ParseNumber(Scanner,ErrorLine,&Number);
									if (Error != eBuildInstrNoError)
										{
											return Error;
										}
									SetLFOSpecExtraValue(LFO,Number);
								}
								break;

							case eKeywordSignramp:
								{
									double					Number;

									SetLFOSpecOscillatorType(LFO,eLFOSignedRamp);

									Error = ParseNumber(Scanner,ErrorLine,&Number);
									if (Error != eBuildInstrNoError)
										{
											return Error;
										}
									SetLFOSpecExtraValue(LFO,Number);
								}
								break;

							case eKeywordPlusramp:
								{
									double					Number;

									SetLFOSpecOscillatorType(LFO,eLFOPositiveRamp);

									Error = ParseNumber(Scanner,ErrorLine,&Number);
									if (Error != eBuildInstrNoError)
										{
											return Error;
										}
									SetLFOSpecExtraValue(LFO,Number);
								}
								break;

							case eKeywordSignlinfuzz:
								{
									double					Seed;

									Error = ParseNumber(Scanner,ErrorLine,&Seed);
									if (Error != eBuildInstrNoError)
										{
											return Error;
										}

									Token = GetNextToken(Scanner);
									if (Token == NIL)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
									if (GetTokenType(Token) != eTokenKeyword)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrExpectedSquareOrTriangle;
										}

									switch (GetTokenKeywordTag(Token))
										{
											default:
												*ErrorLine = GetCurrentLineNumber(Scanner);
												return eBuildInstrExpectedSquareOrTriangle;
											case eKeywordSquare:
												SetLFOSpecOscillatorType(LFO,eLFOSignedLinearFuzzSquare);
												break;
											case eKeywordTriangle:
												SetLFOSpecOscillatorType(LFO,eLFOSignedLinearFuzzTriangle);
												break;
										}
									SetLFOSpecExtraValue(LFO,Seed);
								}
								break;

							case eKeywordPluslinfuzz:
								{
									double					Seed;

									Error = ParseNumber(Scanner,ErrorLine,&Seed);
									if (Error != eBuildInstrNoError)
										{
											return Error;
										}

									Token = GetNextToken(Scanner);
									if (Token == NIL)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
									if (GetTokenType(Token) != eTokenKeyword)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrExpectedSquareOrTriangle;
										}

									switch (GetTokenKeywordTag(Token))
										{
											default:
												*ErrorLine = GetCurrentLineNumber(Scanner);
												return eBuildInstrExpectedSquareOrTriangle;
											case eKeywordSquare:
												SetLFOSpecOscillatorType(LFO,eLFOPositiveLinearFuzzSquare);
												break;
											case eKeywordTriangle:
												SetLFOSpecOscillatorType(LFO,eLFOPositiveLinearFuzzTriangle);
												break;
										}
									SetLFOSpecExtraValue(LFO,Seed);
								}
								break;

							case eKeywordWavetable:
								SetLFOSpecOscillatorType(LFO,eLFOWaveTable);

								/* samplelist keyword */
								Token = GetNextToken(Scanner);
								if (Token == NIL)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrOutOfMemory;
									}
								if ((GetTokenType(Token) != eTokenKeyword)
									|| (GetTokenKeywordTag(Token) != eKeywordSamplelist))
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrExpectedSamplelist;
									}

								/* open paren */
								Token = GetNextToken(Scanner);
								if (Token == NIL)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrOutOfMemory;
									}
								if (GetTokenType(Token) != eTokenOpenParen)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrExpectedOpenParen;
									}

								Error = ParseSamplelistDefinition(GetLFOSpecSampleSelector(LFO),
									Scanner,ErrorLine);
								if (Error != eBuildInstrNoError)
									{
										return Error;
									}
								if (!ResolveWaveTablesInSampleList(GetLFOSpecSampleSelector(LFO),
									WaveTableList,AlgoWaveTableList))
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrSomeWaveTablesDontExist;
									}

								/* close paren */
								Token = GetNextToken(Scanner);
								if (Token == NIL)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrOutOfMemory;
									}
								if (GetTokenType(Token) != eTokenCloseParen)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrExpectedCloseParen;
									}

								/* envelope keyword */
								Token = GetNextToken(Scanner);
								if (Token == NIL)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrOutOfMemory;
									}
								if ((GetTokenType(Token) != eTokenKeyword)
									|| (GetTokenKeywordTag(Token) != eKeywordEnvelope))
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrExpectedEnvelope;
									}

								/* open paren */
								Token = GetNextToken(Scanner);
								if (Token == NIL)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrOutOfMemory;
									}
								if (GetTokenType(Token) != eTokenOpenParen)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrExpectedOpenParen;
									}

								Required = 0;
								Error = ParseEnvelopeDefinition(GetLFOSpecWaveTableIndexEnvelope(LFO),
									Scanner,ErrorLine,&Required,0);
								if (Error != eBuildInstrNoError)
									{
										return Error;
									}
								if (Required != ENVELOPEDEFINITION_REQUIREDMASK)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrSomeRequiredEnvelopeParamsMissing;
									}

								/* close paren */
								Token = GetNextToken(Scanner);
								if (Token == NIL)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrOutOfMemory;
									}
								if (GetTokenType(Token) != eTokenCloseParen)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrExpectedCloseParen;
									}

								/* semicolon or indexlfo */
							 IndexLFOParsePoint:
								Token = GetNextToken(Scanner);
								if (Token == NIL)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrOutOfMemory;
									}
								if (GetTokenType(Token) == eTokenSemicolon)
									{
										UngetToken(Scanner,Token);
									}
								else if ((GetTokenType(Token) == eTokenKeyword)
									&& (GetTokenKeywordTag(Token) == eKeywordIndexlfo))
									{
										LFOSpecRec*						LFOSpec;

										/* open paren */
										Token = GetNextToken(Scanner);
										if (Token == NIL)
											{
												*ErrorLine = GetCurrentLineNumber(Scanner);
												return eBuildInstrOutOfMemory;
											}
										if (GetTokenType(Token) != eTokenOpenParen)
											{
												*ErrorLine = GetCurrentLineNumber(Scanner);
												return eBuildInstrExpectedOpenParen;
											}

										LFOSpec = NewLFOSpecifier();
										if (LFOSpec == NIL)
											{
												*ErrorLine = GetCurrentLineNumber(Scanner);
												return eBuildInstrOutOfMemory;
											}
										if (!LFOListSpecAppendNewEntry(GetLFOSpecWaveTableIndexLFOList(
											LFO),LFOSpec))
											{
												DisposeLFOSpecifier(LFOSpec);
												*ErrorLine = GetCurrentLineNumber(Scanner);
												return eBuildInstrOutOfMemory;
											}

										Required = 0;
										Error = ParseLfoDefinition(LFOSpec,Scanner,ErrorLine,&Required,0,
											WaveTableList,AlgoWaveTableList);
										if (Error != eBuildInstrNoError)
											{
												return Error;
											}
										if (Required != LFODEFINITION_REQUIREDMASK)
											{
												*ErrorLine = GetCurrentLineNumber(Scanner);
												return eBuildInstrSomeRequiredLFOParamsMissing;
											}

										/* close paren */
										Token = GetNextToken(Scanner);
										if (Token == NIL)
											{
												*ErrorLine = GetCurrentLineNumber(Scanner);
												return eBuildInstrOutOfMemory;
											}
										if (GetTokenType(Token) != eTokenCloseParen)
											{
												*ErrorLine = GetCurrentLineNumber(Scanner);
												return eBuildInstrExpectedCloseParen;
											}

										goto IndexLFOParsePoint;
									}
								else
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrExpectedIndexLFOOrSemicolon;
									}
								break;
						}

					*OnceOnlyDefinitions |= LFODEFINITION_ONCEONLY_OSCILLATORTYPE;
					break;

				case eKeywordModulation:
					if ((*OnceOnlyDefinitions & LFODEFINITION_ONCEONLY_MODULATIONTYPE) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleLFOModulationType;
						}

					/*  24:   <modulation_type>       ::= additive */
					/*  25:                           ::= multiplicative */
					/*  26:                           ::= inversemult */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenKeyword)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedLFOModulationType;
						}
					switch (GetTokenKeywordTag(Token))
						{
							default:
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedLFOModulationType;
							case eKeywordAdditive:
								SetLFOSpecModulationMode(LFO,eLFOAdditive);
								break;
							case eKeywordMultiplicative:
								SetLFOSpecModulationMode(LFO,eLFOMultiplicative);
								break;
							case eKeywordInversemult:
								SetLFOSpecModulationMode(LFO,eLFOInverseMultiplicative);
								break;
						}

					*OnceOnlyDefinitions |= LFODEFINITION_ONCEONLY_MODULATIONTYPE;
					break;

				case eKeywordHalfsteps:
					if ((*OnceOnlyDefinitions & LFODEFINITION_ONCEONLY_ADDINGMODE) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleLFOAddingMode;
						}

					SetLFOSpecAddingMode(LFO,eLFOHalfSteps);

					*OnceOnlyDefinitions |= LFODEFINITION_ONCEONLY_ADDINGMODE;
					break;

				case eKeywordLinear:
				case eKeywordHertz:
					if ((*OnceOnlyDefinitions & LFODEFINITION_ONCEONLY_ADDINGMODE) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleLFOAddingMode;
						}

					SetLFOSpecAddingMode(LFO,eLFOArithmetic);

					*OnceOnlyDefinitions |= LFODEFINITION_ONCEONLY_ADDINGMODE;
					break;

				case eKeywordExponential:
					if ((*OnceOnlyDefinitions & LFODEFINITION_ONCEONLY_ADDINGMODE) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleLFOAddingMode;
						}

					SetLFOSpecAddingMode(LFO,eLFOGeometric);

					*OnceOnlyDefinitions |= LFODEFINITION_ONCEONLY_ADDINGMODE;
					break;
			}

		return eBuildInstrNoError;
	}




/*   29:   <oscillator_elem>       ::= type <oscillator_type> */
/*   30:                           ::= samplelist ( <samplelist_definition> ) */
/*   32:                           ::= loudness <number> */
/*   33:                           ::= freqmultiplier <number> */
/*   34:                           ::= freqdivisor <integer> */
/*   36:                           ::= loudnessenvelope ( <envelope_definition> ) */
/*   37:                           ::= loudnesslfo ( <lfo_definition> ) */
/*   38:                           ::= indexenvelope ( <envelope_definition> ) */
/*   39:                           ::= indexlfo ( <lfo_definition> ) */
/*   XXX:                          ::= stereobias <number> */
/*   XXX:                          ::= displacement <number> */
/*   XXX:                          ::= frequencylfo ( <lfo_definition> ) */
/*   XXX:                          ::= effect <oscillator_effect> */
/* FIRST SET: */
/*  <oscillator_elem>       : {loudness, type, samplelist, */
/*       freqmultiplier, freqdivisor, loudnessenvelope, */
/*       loudnesslfo, indexenvelope, indexlfo} */
/* FOLLOW SET: */
/*  <oscillator_elem>       : {;} */
BuildInstrErrors						ParseOscillatorElem(OscillatorRec* Oscillator,
															ScannerRec* Scanner, long* ErrorLine,
															unsigned long* RequiredDefinitions,
															unsigned long* OnceOnlyDefinitions,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		double										Number;
		unsigned long							Required;

		CheckPtrExistence(Oscillator);
		CheckPtrExistence(Scanner);

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedOscillatorMember;
			}

		switch (GetTokenKeywordTag(Token))
			{
				default:
					*ErrorLine = GetCurrentLineNumber(Scanner);
					return eBuildInstrExpectedOscillatorMember;

				case eKeywordType:
					if ((*OnceOnlyDefinitions & OSCILLATORDEFINITION_ONCEONLY_TYPE) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleOscType;
						}

					/*  40:   <oscillator_type>       ::= sampled */
					/*  41:                           ::= wavetable */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenKeyword)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedOscType;
						}
					switch (GetTokenKeywordTag(Token))
						{
							default:
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedOscType;
							case eKeywordSampled:
								OscillatorSetTheType(Oscillator,eOscillatorSampled);
								break;
							case eKeywordWavetable:
								OscillatorSetTheType(Oscillator,eOscillatorWaveTable);
								break;
						}

					*OnceOnlyDefinitions |= OSCILLATORDEFINITION_ONCEONLY_TYPE;
					*RequiredDefinitions |= OSCILLATORDEFINITION_REQUIRED_TYPE;
					break;

				case eKeywordSamplelist:
					if ((*OnceOnlyDefinitions & OSCILLATORDEFINITION_ONCEONLY_SAMPLELIST) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleOscSampleList;
						}

					/* open paren */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenOpenParen)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedOpenParen;
						}

					Error = ParseSamplelistDefinition(OscillatorGetSampleIntervalList(Oscillator),
						Scanner,ErrorLine);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}

					/* close paren */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenCloseParen)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedCloseParen;
						}

					*OnceOnlyDefinitions |= OSCILLATORDEFINITION_ONCEONLY_SAMPLELIST;
					*RequiredDefinitions |= OSCILLATORDEFINITION_REQUIRED_SAMPLELIST;
					break;

				case eKeywordLoudness:
					if ((*OnceOnlyDefinitions & OSCILLATORDEFINITION_ONCEONLY_LOUDNESS) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleOscLoudness;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					PutOscillatorNewOutputLoudness(Oscillator,Number);

					*OnceOnlyDefinitions |= OSCILLATORDEFINITION_ONCEONLY_LOUDNESS;
					break;

				case eKeywordFreqmultiplier:
					if ((*OnceOnlyDefinitions & OSCILLATORDEFINITION_ONCEONLY_FREQMULTIPLIER) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleOscFreqMultiplier;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					PutOscillatorNewFrequencyFactors(Oscillator,Number,
						OscillatorGetFrequencyDivisor(Oscillator));

					*OnceOnlyDefinitions |= OSCILLATORDEFINITION_ONCEONLY_FREQMULTIPLIER;
					break;

				case eKeywordFreqdivisor:
					if ((*OnceOnlyDefinitions & OSCILLATORDEFINITION_ONCEONLY_FREQDIVISOR) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleOscFreqDivisor;
						}

					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenInteger)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedInteger;
						}
					PutOscillatorNewFrequencyFactors(Oscillator,
						OscillatorGetFrequencyMultiplier(Oscillator),GetTokenIntegerValue(Token));

					*OnceOnlyDefinitions |= OSCILLATORDEFINITION_ONCEONLY_FREQDIVISOR;
					break;

				case eKeywordFreqadder:
					if ((*OnceOnlyDefinitions & OSCILLATORDEFINITION_ONCEONLY_FREQADDER) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleOscFreqAdder;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					PutOscillatorFrequencyAdder(Oscillator,Number);

					*OnceOnlyDefinitions |= OSCILLATORDEFINITION_ONCEONLY_FREQADDER;
					break;

				case eKeywordLoudnessenvelope:
					if ((*OnceOnlyDefinitions & OSCILLATORDEFINITION_ONCEONLY_LOUDNESSENVELOPE) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleOscLoudnessEnvelope;
						}

					/* open paren */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenOpenParen)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedOpenParen;
						}

					Required = 0;
					Error = ParseEnvelopeDefinition(OscillatorGetLoudnessEnvelope(Oscillator),
						Scanner,ErrorLine,&Required,0);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					if (Required != ENVELOPEDEFINITION_REQUIREDMASK)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrSomeRequiredEnvelopeParamsMissing;
						}

					/* close paren */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenCloseParen)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedCloseParen;
						}

					*OnceOnlyDefinitions |= OSCILLATORDEFINITION_ONCEONLY_LOUDNESSENVELOPE;
					*RequiredDefinitions |= OSCILLATORDEFINITION_REQUIRED_LOUDNESSENVELOPE;
					break;

				case eKeywordLoudnesslfo:
					{
						LFOSpecRec*					LFO;

						/* create the LFO */
						LFO = NewLFOSpecifier();
						if (LFO == NIL)
							{
							 LoudnessLFOAllocFailurePoint1:
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (!LFOListSpecAppendNewEntry(OscillatorGetLoudnessLFOList(Oscillator),LFO))
							{
							 LoudnessLFOAllocFailurePoint2:
								DisposeLFOSpecifier(LFO);
								goto LoudnessLFOAllocFailurePoint1;
							}

						/* open paren */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (GetTokenType(Token) != eTokenOpenParen)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedOpenParen;
							}

						Required = 0;
						Error = ParseLfoDefinition(LFO,Scanner,ErrorLine,&Required,0,
							WaveTableList,AlgoWaveTableList);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
						if (Required != LFODEFINITION_REQUIREDMASK)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrSomeRequiredEnvelopeParamsMissing;
							}

						/* close paren */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (GetTokenType(Token) != eTokenCloseParen)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedCloseParen;
							}
					}
					break;

				case eKeywordIndexenvelope:
					if ((*OnceOnlyDefinitions & OSCILLATORDEFINITION_ONCEONLY_INDEXENVELOPE) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleOscIndexEnvelope;
						}

					/* open paren */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenOpenParen)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedOpenParen;
						}

					Required = 0;
					Error = ParseEnvelopeDefinition(OscillatorGetExcitationEnvelope(Oscillator),
						Scanner,ErrorLine,&Required,0);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					if (Required != ENVELOPEDEFINITION_REQUIREDMASK)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrSomeRequiredEnvelopeParamsMissing;
						}

					/* close paren */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenCloseParen)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedCloseParen;
						}

					*OnceOnlyDefinitions |= OSCILLATORDEFINITION_ONCEONLY_INDEXENVELOPE;
					break;

				case eKeywordIndexlfo:
					{
						LFOSpecRec*					LFO;

						/* create the LFO */
						LFO = NewLFOSpecifier();
						if (LFO == NIL)
							{
							 IndexLFOAllocFailurePoint1:
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (!LFOListSpecAppendNewEntry(OscillatorGetExcitationLFOList(Oscillator),LFO))
							{
							 IndexLFOAllocFailurePoint2:
								DisposeLFOSpecifier(LFO);
								goto IndexLFOAllocFailurePoint1;
							}

						/* open paren */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (GetTokenType(Token) != eTokenOpenParen)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedOpenParen;
							}

						Required = 0;
						Error = ParseLfoDefinition(LFO,Scanner,ErrorLine,&Required,0,
							WaveTableList,AlgoWaveTableList);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
						if (Required != LFODEFINITION_REQUIREDMASK)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrSomeRequiredEnvelopeParamsMissing;
							}

						/* close paren */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (GetTokenType(Token) != eTokenCloseParen)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedCloseParen;
							}
					}
					break;

				case eKeywordStereobias:
					if ((*OnceOnlyDefinitions & OSCILLATORDEFINITION_ONCEONLY_STEREOBIAS) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleOscStereoBias;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					OscillatorPutStereoBias(Oscillator,Number);

					*OnceOnlyDefinitions |= OSCILLATORDEFINITION_ONCEONLY_STEREOBIAS;
					break;

				case eKeywordDisplacement:
					if ((*OnceOnlyDefinitions & OSCILLATORDEFINITION_ONCEONLY_TIMEDISPLACEMENT) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleOscDisplacement;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					OscillatorPutTimeDisplacement(Oscillator,Number);

					*OnceOnlyDefinitions |= OSCILLATORDEFINITION_ONCEONLY_TIMEDISPLACEMENT;
					break;

				case eKeywordSurroundbias:
					if ((*OnceOnlyDefinitions & OSCILLATORDEFINITION_ONCEONLY_SURROUNDBIAS) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleOscSurroundBias;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					OscillatorPutSurroundBias(Oscillator,Number);

					*OnceOnlyDefinitions |= OSCILLATORDEFINITION_ONCEONLY_SURROUNDBIAS;
					break;

				case eKeywordFrequencylfo:
					{
						unsigned long							LFORequired;
						LFOSpecRec*								LFO;

						/* allocate the LFO */
						LFO = NewLFOSpecifier();
						if (LFO == NIL)
							{
							 LFOAllocFailurePoint1:
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						/* the default arithmetic mode for pitch LFO is halfsteps */
						SetLFOSpecAddingMode(LFO,eLFOHalfSteps);
						if (!LFOListSpecAppendNewEntry(GetOscillatorFrequencyLFOList(Oscillator),LFO))
							{
							 LFOAllocFailurePoint2:
								DisposeLFOSpecifier(LFO);
								goto LFOAllocFailurePoint1;
							}

						/* open paren */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (GetTokenType(Token) != eTokenOpenParen)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedOpenParen;
							}

						/* parse the low frequency operator */
						LFORequired = 0;
						Error = ParseLfoDefinition(LFO,Scanner,ErrorLine,&LFORequired,0,WaveTableList,
							AlgoWaveTableList);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
						if (LFORequired != LFODEFINITION_REQUIREDMASK)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrSomeRequiredLFOParamsMissing;
							}

						/* close paren */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (GetTokenType(Token) != eTokenCloseParen)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedCloseParen;
							}
					}
					break;

				case eKeywordEffect:
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenKeyword)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedOscillatorEffect;
						}
					switch (GetTokenKeywordTag(Token))
						{
							default:
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedOscillatorEffect;

							case eKeywordAnalyzer:
								{
									char*										IDString;
									AnalyzerSpecRec*				Analyzer;

									Error = ParseIdentifier(Scanner,ErrorLine,&IDString);
									if (Error != eBuildInstrNoError)
										{
											return Error;
										}
									Analyzer = NewAnalyzerSpec(IDString);
									ReleasePtr(IDString);
									if (Analyzer == NIL)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
									if (!AddAnalyzerToEffectSpecList(GetOscillatorEffectList(
										Oscillator),Analyzer))
										{
											DisposeAnalyzerSpec(Analyzer);
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
								}
								break;

							/* delayline ( <oscdelayelems> ) */
							case eKeywordDelayline:
								{
									DelayEffectRec*				DelayEffect;
									unsigned long					OnceOnlyThang;

									DelayEffect = NewDelayLineSpec();
									if (DelayEffect == NIL)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
									if (!AddDelayToEffectSpecList(GetOscillatorEffectList(
										Oscillator),DelayEffect))
										{
											DisposeDelayLineSpec(DelayEffect);
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}

									Token = GetNextToken(Scanner);
									if (Token == NIL)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
									if (GetTokenType(Token) != eTokenOpenParen)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrExpectedOpenParen;
										}

									OnceOnlyThang = 0;
									Error = ParseOscDelayElems(DelayEffect,Scanner,ErrorLine,
										&OnceOnlyThang,WaveTableList,AlgoWaveTableList);
									if (Error != eBuildInstrNoError)
										{
											return Error;
										}

									Token = GetNextToken(Scanner);
									if (Token == NIL)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
									if (GetTokenType(Token) != eTokenCloseParen)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrExpectedCloseParen;
										}
								}
								break;

							/* nlproc wavetable <identifier> inputscalingenvelope ( */
							/* <envelope_definition> ) <nlinputscalinglfolist> */
							/* outputscalingenvelope ( <envelope_definition> ) */
							/* <nloutputscalinglfolist> indexenvelope ( <envelope_definition> */
							/* ) <nlindexlfolist> */
							case eKeywordNlproc:
								{
									struct WaveTableObjectRec*			DataWaveTable;
									struct AlgoWaveTableObjectRec*	AlgoWaveTable;
									char*														WaveTableName;
									NonlinProcSpecRec*							NLProcSpec;
									unsigned long										RequiredDefs;

									/* wavetable */
									Token = GetNextToken(Scanner);
									if (Token == NIL)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
									if ((GetTokenType(Token) != eTokenKeyword)
										|| (GetTokenKeywordTag(Token) != eKeywordWavetable))
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrExpectedWavetable;
										}
									/* get wavetable name */
									Error = ParseIdentifier(Scanner,ErrorLine,&WaveTableName);
									if (Error != eBuildInstrNoError)
										{
											return Error;
										}
									DataWaveTable = WaveTableListLookupNamedWaveTable(WaveTableList,
										WaveTableName);
									if (DataWaveTable != NIL)
										{
											NLProcSpec = NewNonlinProcSpecDataWave(DataWaveTable);
											if (NLProcSpec == NIL)
												{
													ReleasePtr(WaveTableName);
													*ErrorLine = GetCurrentLineNumber(Scanner);
													return eBuildInstrOutOfMemory;
												}
										}
									 else
										{
											AlgoWaveTable = AlgoWaveTableListLookupNamedAlgoWaveTable(
												AlgoWaveTableList,WaveTableName);
											if (AlgoWaveTable == NIL)
												{
													ReleasePtr(WaveTableName);
													*ErrorLine = GetCurrentLineNumber(Scanner);
													return eBuildInstrUndefinedWavetable;
												}
											NLProcSpec = NewNonlinProcSpecAlgoWave(AlgoWaveTable);
											if (NLProcSpec == NIL)
												{
													ReleasePtr(WaveTableName);
													*ErrorLine = GetCurrentLineNumber(Scanner);
													return eBuildInstrOutOfMemory;
												}
										}
									ReleasePtr(WaveTableName);
									if (!AddNLProcToEffectSpecList(GetOscillatorEffectList(
										Oscillator),NLProcSpec))
										{
											DisposeNonlinProcSpec(NLProcSpec);
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
									/* inputscalingenvelope OPAREN */
									Token = GetNextToken(Scanner);
									if (Token == NIL)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
									if ((GetTokenType(Token) != eTokenKeyword)
										|| (GetTokenKeywordTag(Token) != eKeywordInputscalingenvelope))
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrExpectedInputScalingEnvelope;
										}
									Token = GetNextToken(Scanner);
									if (Token == NIL)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
									if (GetTokenType(Token) != eTokenOpenParen)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrExpectedOpenParen;
										}
									/* <envelope_definition> */
									RequiredDefs = 0;
									Error = ParseEnvelopeDefinition(GetNLProcInputEnvelope(NLProcSpec),
										Scanner,ErrorLine,&RequiredDefs,0);
									if (Error != eBuildInstrNoError)
										{
											return Error;
										}
									if (RequiredDefs != ENVELOPEDEFINITION_REQUIREDMASK)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrSomeRequiredEnvelopeParamsMissing;
										}
									/* CPAREN */
									Token = GetNextToken(Scanner);
									if (Token == NIL)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
									if (GetTokenType(Token) != eTokenCloseParen)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrExpectedCloseParen;
										}
									/* <nlinputscalinglfolist> */
									Error = ParseNLInputScalingLFOList(GetNLProcInputLFO(NLProcSpec),
										Scanner,ErrorLine,WaveTableList,AlgoWaveTableList);
									if (Error != eBuildInstrNoError)
										{
											return Error;
										}
									/* outputscalingenvelope OPAREN */
									Token = GetNextToken(Scanner);
									if (Token == NIL)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
									if ((GetTokenType(Token) != eTokenKeyword)
										|| (GetTokenKeywordTag(Token) != eKeywordOutputscalingenvelope))
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrExpectedOutputScalingEnvelope;
										}
									Token = GetNextToken(Scanner);
									if (Token == NIL)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
									if (GetTokenType(Token) != eTokenOpenParen)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrExpectedOpenParen;
										}
									/* <envelope_definition> */
									RequiredDefs = 0;
									Error = ParseEnvelopeDefinition(GetNLProcOutputEnvelope(NLProcSpec),
										Scanner,ErrorLine,&RequiredDefs,0);
									if (Error != eBuildInstrNoError)
										{
											return Error;
										}
									if (RequiredDefs != ENVELOPEDEFINITION_REQUIREDMASK)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrSomeRequiredEnvelopeParamsMissing;
										}
									/* CPAREN */
									Token = GetNextToken(Scanner);
									if (Token == NIL)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
									if (GetTokenType(Token) != eTokenCloseParen)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrExpectedCloseParen;
										}
									/* <nloutputscalinglfolist> */
									Error = ParseNLOutputScalingLFOList(GetNLProcOutputLFO(NLProcSpec),
										Scanner,ErrorLine,WaveTableList,AlgoWaveTableList);
									if (Error != eBuildInstrNoError)
										{
											return Error;
										}
									/* indexenvelope OPAREN */
									Token = GetNextToken(Scanner);
									if (Token == NIL)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
									if ((GetTokenType(Token) != eTokenKeyword)
										|| (GetTokenKeywordTag(Token) != eKeywordIndexenvelope))
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrExpectedIndexEnvelope;
										}
									Token = GetNextToken(Scanner);
									if (Token == NIL)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
									if (GetTokenType(Token) != eTokenOpenParen)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrExpectedOpenParen;
										}
									/* <envelope_definition> */
									RequiredDefs = 0;
									Error = ParseEnvelopeDefinition(GetNLProcIndexEnvelope(NLProcSpec),
										Scanner,ErrorLine,&RequiredDefs,0);
									if (Error != eBuildInstrNoError)
										{
											return Error;
										}
									if (RequiredDefs != ENVELOPEDEFINITION_REQUIREDMASK)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrSomeRequiredEnvelopeParamsMissing;
										}
									/* CPAREN */
									Token = GetNextToken(Scanner);
									if (Token == NIL)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
									if (GetTokenType(Token) != eTokenCloseParen)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrExpectedCloseParen;
										}
									/* <nlindexlfolist> */
									Error = ParseNLIndexLFOList(GetNLProcIndexLFO(NLProcSpec),
										Scanner,ErrorLine,WaveTableList,AlgoWaveTableList);
									if (Error != eBuildInstrNoError)
										{
											return Error;
										}
								}
								break;

							/* filter ( <oscfilterelems> ) */
							case eKeywordFilter:
								{
									FilterSpecRec*				FilterSpec;

									Token = GetNextToken(Scanner);
									if (Token == NIL)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
									if (GetTokenType(Token) != eTokenOpenParen)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrExpectedOpenParen;
										}

									FilterSpec = NewFilterSpec();
									if (FilterSpec == NIL)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
									if (!AddFilterToEffectSpecList(GetOscillatorEffectList(Oscillator),
										FilterSpec))
										{
											DisposeFilterSpec(FilterSpec);
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}

									Error = ParseOscFilterElems(FilterSpec,Scanner,ErrorLine,
										WaveTableList,AlgoWaveTableList);
									if (Error != eBuildInstrNoError)
										{
											return Error;
										}

									Token = GetNextToken(Scanner);
									if (Token == NIL)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrOutOfMemory;
										}
									if (GetTokenType(Token) != eTokenCloseParen)
										{
											*ErrorLine = GetCurrentLineNumber(Scanner);
											return eBuildInstrExpectedCloseParen;
										}
								}
								break;
						}
					break;
			}

		return eBuildInstrNoError;
	}




/*   42:   <envelope_definition>   ::= <envelope_elem> ; <envelope_definition> */
/*   43:                           ::=  */
/* FIRST SET: */
/*  <envelope_definition>   : {totalscaling, points, <envelope_elem>} */
/* FOLLOW SET: */
/*  <envelope_definition>   : {)} */
BuildInstrErrors						ParseEnvelopeDefinition(EnvelopeRec* Envelope,
															ScannerRec* Scanner, long* ErrorLine,
															unsigned long* RequiredDefinitions,
															unsigned long OnceOnlyDefinitions)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;

		CheckPtrExistence(Envelope);
		CheckPtrExistence(Scanner);

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}

		if (GetTokenType(Token) == eTokenCloseParen)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		 else
			{
				UngetToken(Scanner,Token);

				Error = ParseEnvelopeElem(Envelope,Scanner,ErrorLine,RequiredDefinitions,
					&OnceOnlyDefinitions);
				if (Error != eBuildInstrNoError)
					{
						return Error;
					}

				/* get semicolon */
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if (GetTokenType(Token) != eTokenSemicolon)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedSemicolon;
					}

				return ParseEnvelopeDefinition(Envelope,Scanner,ErrorLine,RequiredDefinitions,
					OnceOnlyDefinitions);
			}

		EXECUTE(PRERR(ForceAbort,"ParseEnvelopeDefinition:  control reached end of function"));
	}




/*   68:   <samplelist_definition> ::= <samplelist_elem> ; */
/*       <samplelist_definition> */
/*   69:                           ::=  */
/* FIRST SET: */
/*  <samplelist_definition> : {<identifiertoken>, <stringtoken>, */
/*       <identifier>, <samplelist_elem>} */
/* FOLLOW SET: */
/*  <samplelist_definition> : {)} */
BuildInstrErrors						ParseSamplelistDefinition(SampleSelectorRec* SampleList,
															ScannerRec* Scanner, long* ErrorLine)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;

		CheckPtrExistence(SampleList);
		CheckPtrExistence(Scanner);

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}

		if (GetTokenType(Token) == eTokenCloseParen)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		 else
			{
				UngetToken(Scanner,Token);

				Error = ParseSamplelistElem(SampleList,Scanner,ErrorLine);
				if (Error != eBuildInstrNoError)
					{
						return Error;
					}

				/* get semicolon */
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if (GetTokenType(Token) != eTokenSemicolon)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedSemicolon;
					}

				return ParseSamplelistDefinition(SampleList,Scanner,ErrorLine);
			}

		EXECUTE(PRERR(ForceAbort,"ParseSamplelistDefinition:  control reached end of function"));
	}




/*   45:   <envelope_elem>         ::= totalscaling <number> */
/*   49:                           ::= points ( <env_point_list> ) */
/*   XX:                           ::= pitchcontrol slope <number> center <number> */
/* FIRST SET: */
/*  <envelope_elem>         : {totalscaling, points} */
/* FOLLOW SET: */
/*  <envelope_elem>         : {;} */
BuildInstrErrors						ParseEnvelopeElem(EnvelopeRec* Envelope,
															ScannerRec* Scanner, long *ErrorLine,
															unsigned long* RequiredDefinitions,
															unsigned long* OnceOnlyDefinitions)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		double										Number;

		CheckPtrExistence(Envelope);
		CheckPtrExistence(Scanner);

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedEnvelopeMember;
			}

		switch (GetTokenKeywordTag(Token))
			{
				default:
					*ErrorLine = GetCurrentLineNumber(Scanner);
					return eBuildInstrExpectedEnvelopeMember;

				case eKeywordTotalscaling:
					if ((*OnceOnlyDefinitions & ENVELOPEDEFINITION_ONCEONLY_TOTALSCALING) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvTotalScaling;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetOverallAmplitude(Envelope,Number);

					*OnceOnlyDefinitions |= ENVELOPEDEFINITION_ONCEONLY_TOTALSCALING;
					break;

				case eKeywordPoints:
					if ((*OnceOnlyDefinitions & ENVELOPEDEFINITION_ONCEONLY_POINTS) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPoints;
						}

					/* open paren */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenOpenParen)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedOpenParen;
						}

					Error = ParseEnvPointList(Envelope,Scanner,ErrorLine);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}

					/* close paren */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenCloseParen)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedCloseParen;
						}

					*OnceOnlyDefinitions |= ENVELOPEDEFINITION_ONCEONLY_POINTS;
					break;

				case eKeywordPitchcontrol:
					if ((*OnceOnlyDefinitions & ENVELOPEDEFINITION_ONCEONLY_PITCHCONTROL) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultiplePitchControl;
						}

					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if ((GetTokenType(Token) != eTokenKeyword)
						|| (GetTokenKeywordTag(Token) != eKeywordSlope))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedSlope;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					PutGlobalEnvelopePitchRateRolloff(Envelope,Number);

					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if ((GetTokenType(Token) != eTokenKeyword)
						|| (GetTokenKeywordTag(Token) != eKeywordCenter))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedCenter;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					PutGlobalEnvelopePitchRateNormalization(Envelope,Number);

					*OnceOnlyDefinitions |= ENVELOPEDEFINITION_ONCEONLY_PITCHCONTROL;
					break;
			}

		return eBuildInstrNoError;
	}




/*   70:   <samplelist_elem>       ::= <identifier> <number> */
/* FIRST SET: */
/*  <samplelist_elem>       : {<identifiertoken>, <stringtoken>, <identifier>} */
/* FOLLOW SET: */
/*  <samplelist_elem>       : {;} */
BuildInstrErrors						ParseSamplelistElem(SampleSelectorRec* SampleList,
															ScannerRec* Scanner, long* ErrorLine)
	{
		BuildInstrErrors					Error;
		char*											SampleName;
		double										Number;

		CheckPtrExistence(SampleList);
		CheckPtrExistence(Scanner);

		Error = ParseIdentifier(Scanner,ErrorLine,&SampleName);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}

		Error = ParseNumber(Scanner,ErrorLine,&Number);
		if (Error != eBuildInstrNoError)
			{
				ReleasePtr(SampleName);
				return Error;
			}

		if (!AppendSampleSelector(SampleList,Number,SampleName))
			{
				ReleasePtr(SampleName);
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}

		return eBuildInstrNoError;
	}




/*   50:   <env_point_list>        ::= <env_point_elem> ; <env_point_list> */
/*   51:                           ::=  */
/* FIRST SET: */
/*  <env_point_list>        : {<integertoken>, <floattoken>, <number>, */
/*       <env_point_elem>} */
/* FOLLOW SET: */
/*  <env_point_list>        : {)} */
BuildInstrErrors						ParseEnvPointList(EnvelopeRec* Envelope,
															ScannerRec* Scanner, long *ErrorLine)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;

		CheckPtrExistence(Envelope);
		CheckPtrExistence(Scanner);

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}

		if (GetTokenType(Token) == eTokenCloseParen)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		 else
			{
				UngetToken(Scanner,Token);

				Error = ParseEnvPointElem(Envelope,Scanner,ErrorLine);
				if (Error != eBuildInstrNoError)
					{
						return Error;
					}

				/* get semicolon */
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if (GetTokenType(Token) != eTokenSemicolon)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedSemicolon;
					}

				return ParseEnvPointList(Envelope,Scanner,ErrorLine);
			}

		EXECUTE(PRERR(ForceAbort,"ParseEnvPointList:  control reached end of function"));
	}




/*   52:   <env_point_elem>        ::= delay <number> level <number> <env_attributes> */
/*   XX:                           ::= origin */
/* FIRST SET: */
/*  <env_point_elem>        : {delay} */
/* FOLLOW SET: */
/*  <env_point_elem>        : {<integertoken>, <floattoken>, ), <number>, */
/*       <env_point_list>, <env_point_elem>} */
BuildInstrErrors						ParseEnvPointElem(EnvelopeRec* Envelope,
															ScannerRec* Scanner, long *ErrorLine)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		double										Delay;
		double										Level;

		CheckPtrExistence(Envelope);
		CheckPtrExistence(Scanner);

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedDelayOrOrigin;
			}

		switch (GetTokenKeywordTag(Token))
			{
				default:
					*ErrorLine = GetCurrentLineNumber(Scanner);
					return eBuildInstrExpectedDelayOrOrigin;

				case eKeywordDelay:
					Error = ParseNumber(Scanner,ErrorLine,&Delay);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}

					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if ((GetTokenType(Token) != eTokenKeyword)
						|| ((GetTokenKeywordTag(Token) != eKeywordLevel)
							&& (GetTokenKeywordTag(Token) != eKeywordScale)))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedLevelOrScale;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Level);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}

					if (!EnvelopeInsertPhase(Envelope,GetEnvelopeNumFrames(Envelope)))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenKeywordTag(Token) == eKeywordScale)
						{
							EnvelopeSetPhaseTargetType(Envelope,GetEnvelopeNumFrames(Envelope) - 1,
								eEnvelopeTargetScaling);
						}
					 else
						{
							EnvelopeSetPhaseTargetType(Envelope,GetEnvelopeNumFrames(Envelope) - 1,
								eEnvelopeTargetAbsolute);
						}
					EnvelopeSetPhaseDuration(Envelope,GetEnvelopeNumFrames(Envelope) - 1,Delay);
					EnvelopeSetPhaseFinalValue(Envelope,GetEnvelopeNumFrames(Envelope) - 1,Level);

					return ParseEnvAttributes(Envelope,Scanner,ErrorLine,0);

				case eKeywordOrigin:
					EnvelopeSetOrigin(Envelope,GetEnvelopeNumFrames(Envelope));
					return eBuildInstrNoError;
			}
		EXECUTE(PRERR(ForceAbort,"ParseEnvPointElem:  Control reached end of function"));
	}




/*   50:   <env_attributes>        ::= <env_one_attribute> <env_attributes> */
/*   51:                           ::=  */
/* FIRST SET: */
/*  <env_attributes>        : {exponential, linear, sustainpoint, */
/*       ampaccent1, ampaccent2, ampaccent3, ampaccent4, ampfreq, rateaccent1, */
/*       rateaccent2, rateaccent3, rateaccent4, ratefreq, <env_one_attribute>} */
/* FOLLOW SET: */
/*  <env_attributes>        : {;} */
BuildInstrErrors						ParseEnvAttributes(EnvelopeRec* Envelope,
															ScannerRec* Scanner, long *ErrorLine,
															unsigned long OnceOnly)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;

		CheckPtrExistence(Envelope);
		CheckPtrExistence(Scanner);

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}

		if (GetTokenType(Token) == eTokenSemicolon)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		 else
			{
				UngetToken(Scanner,Token);

				Error = ParseEnvOneAttribute(Envelope,Scanner,ErrorLine,&OnceOnly);
				if (Error != eBuildInstrNoError)
					{
						return Error;
					}

				return ParseEnvAttributes(Envelope,Scanner,ErrorLine,OnceOnly);
			}

		EXECUTE(PRERR(ForceAbort,"ParseEnvAttributes:  control reached end of function"));
	}




/*   52:   <env_one_attribute>     ::= sustainpoint <integertoken> */
/*   53:                           ::= ampaccent1 <number> */
/*   54:                           ::= ampaccent2 <number> */
/*   55:                           ::= ampaccent3 <number> */
/*   56:                           ::= ampaccent4 <number> */
/*   57:                           ::= ampfreq <number> <number> */
/*   58:                           ::= rateaccent1 <number> */
/*   59:                           ::= rateaccent2 <number> */
/*   60:                           ::= rateaccent3 <number> */
/*   61:                           ::= rateaccent4 <number> */
/*   62:                           ::= ratefreq <number> <number> */
/*   63:                           ::= exponential */
/*   64:                           ::= linear */
/* FIRST SET: */
/*  <env_one_attribute>     : {exponential, linear, sustainpoint, */
/*       ampaccent1, ampaccent2, ampaccent3, ampaccent4, ampfreq, */
/*       rateaccent1, rateaccent2, rateaccent3, rateaccent4, ratefreq} */
/* FOLLOW SET: */
/*  <env_one_attribute>     : {;, exponential, linear, */
/*       sustainpoint, ampaccent1, ampaccent2, ampaccent3, ampaccent4, */
/*       ampfreq, rateaccent1, rateaccent2, rateaccent3, rateaccent4, */
/*       ratefreq, <env_attributes>, <env_one_attribute>} */
BuildInstrErrors						ParseEnvOneAttribute(EnvelopeRec* Envelope,
															ScannerRec* Scanner, long *ErrorLine,
															unsigned long* OnceOnlyDefinitions)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		double										Number;

		CheckPtrExistence(Envelope);
		CheckPtrExistence(Scanner);

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrNoError;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedEnvPointMember;
			}

		switch (GetTokenKeywordTag(Token))
			{
				default:
					*ErrorLine = GetCurrentLineNumber(Scanner);
					return eBuildInstrExpectedEnvPointMember;

				case eKeywordSustainpoint:
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrNoError;
						}
					if (GetTokenType(Token) != eTokenInteger)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedInteger;
						}
					switch (GetTokenIntegerValue(Token))
						{
							default:
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedIntBetween1And3;
							case 1:
								if (GetEnvelopeReleasePoint1(Envelope) != -1)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrEnvSustainPointAlreadyDefined;
									}
								EnvelopeSetReleasePoint1(Envelope,GetEnvelopeNumFrames(Envelope) - 1,
									eEnvelopeSustainPointSkip);
								break;
							case 2:
								if (GetEnvelopeReleasePoint2(Envelope) != -1)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrEnvSustainPointAlreadyDefined;
									}
								EnvelopeSetReleasePoint2(Envelope,GetEnvelopeNumFrames(Envelope) - 1,
									eEnvelopeSustainPointSkip);
								break;
							case 3:
								if (GetEnvelopeReleasePoint3(Envelope) != -1)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrEnvSustainPointAlreadyDefined;
									}
								EnvelopeSetReleasePoint3(Envelope,GetEnvelopeNumFrames(Envelope) - 1,
									eEnvelopeSustainPointSkip);
								break;
						}
					break;

				case eKeywordReleasepoint:
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrNoError;
						}
					if (GetTokenType(Token) != eTokenInteger)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedInteger;
						}
					switch (GetTokenIntegerValue(Token))
						{
							default:
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedIntBetween1And3;
							case 1:
								if (GetEnvelopeReleasePoint1(Envelope) != -1)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrEnvSustainPointAlreadyDefined;
									}
								EnvelopeSetReleasePoint1(Envelope,GetEnvelopeNumFrames(Envelope) - 1,
									eEnvelopeReleasePointSkip);
								break;
							case 2:
								if (GetEnvelopeReleasePoint2(Envelope) != -1)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrEnvSustainPointAlreadyDefined;
									}
								EnvelopeSetReleasePoint2(Envelope,GetEnvelopeNumFrames(Envelope) - 1,
									eEnvelopeReleasePointSkip);
								break;
							case 3:
								if (GetEnvelopeReleasePoint3(Envelope) != -1)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrEnvSustainPointAlreadyDefined;
									}
								EnvelopeSetReleasePoint3(Envelope,GetEnvelopeNumFrames(Envelope) - 1,
									eEnvelopeReleasePointSkip);
								break;
						}
					break;

				case eKeywordSustainpointnoskip:
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrNoError;
						}
					if (GetTokenType(Token) != eTokenInteger)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedInteger;
						}
					switch (GetTokenIntegerValue(Token))
						{
							default:
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedIntBetween1And3;
							case 1:
								if (GetEnvelopeReleasePoint1(Envelope) != -1)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrEnvSustainPointAlreadyDefined;
									}
								EnvelopeSetReleasePoint1(Envelope,GetEnvelopeNumFrames(Envelope) - 1,
									eEnvelopeSustainPointNoSkip);
								break;
							case 2:
								if (GetEnvelopeReleasePoint2(Envelope) != -1)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrEnvSustainPointAlreadyDefined;
									}
								EnvelopeSetReleasePoint2(Envelope,GetEnvelopeNumFrames(Envelope) - 1,
									eEnvelopeSustainPointNoSkip);
								break;
							case 3:
								if (GetEnvelopeReleasePoint3(Envelope) != -1)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrEnvSustainPointAlreadyDefined;
									}
								EnvelopeSetReleasePoint3(Envelope,GetEnvelopeNumFrames(Envelope) - 1,
									eEnvelopeSustainPointNoSkip);
								break;
						}
					break;

				case eKeywordReleasepointnoskip:
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrNoError;
						}
					if (GetTokenType(Token) != eTokenInteger)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedInteger;
						}
					switch (GetTokenIntegerValue(Token))
						{
							default:
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedIntBetween1And3;
							case 1:
								if (GetEnvelopeReleasePoint1(Envelope) != -1)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrEnvSustainPointAlreadyDefined;
									}
								EnvelopeSetReleasePoint1(Envelope,GetEnvelopeNumFrames(Envelope) - 1,
									eEnvelopeReleasePointNoSkip);
								break;
							case 2:
								if (GetEnvelopeReleasePoint2(Envelope) != -1)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrEnvSustainPointAlreadyDefined;
									}
								EnvelopeSetReleasePoint2(Envelope,GetEnvelopeNumFrames(Envelope) - 1,
									eEnvelopeReleasePointNoSkip);
								break;
							case 3:
								if (GetEnvelopeReleasePoint3(Envelope) != -1)
									{
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrEnvSustainPointAlreadyDefined;
									}
								EnvelopeSetReleasePoint3(Envelope,GetEnvelopeNumFrames(Envelope) - 1,
									eEnvelopeReleasePointNoSkip);
								break;
						}
					break;

				case eKeywordAmpaccent1:
					if ((*OnceOnlyDefinitions & ENVPOINTDEFINITION_ONCEONLY_AMPACCENT1) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPointAmpAccent1;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetAccent1Amp(Envelope,Number,GetEnvelopeNumFrames(Envelope) - 1);

					*OnceOnlyDefinitions |= ENVPOINTDEFINITION_ONCEONLY_AMPACCENT1;
					break;

				case eKeywordAmpaccent2:
					if ((*OnceOnlyDefinitions & ENVPOINTDEFINITION_ONCEONLY_AMPACCENT2) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPointAmpAccent2;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetAccent2Amp(Envelope,Number,GetEnvelopeNumFrames(Envelope) - 1);

					*OnceOnlyDefinitions |= ENVPOINTDEFINITION_ONCEONLY_AMPACCENT2;
					break;

				case eKeywordAmpaccent3:
					if ((*OnceOnlyDefinitions & ENVPOINTDEFINITION_ONCEONLY_AMPACCENT3) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPointAmpAccent3;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetAccent3Amp(Envelope,Number,GetEnvelopeNumFrames(Envelope) - 1);

					*OnceOnlyDefinitions |= ENVPOINTDEFINITION_ONCEONLY_AMPACCENT3;
					break;

				case eKeywordAmpaccent4:
					if ((*OnceOnlyDefinitions & ENVPOINTDEFINITION_ONCEONLY_AMPACCENT4) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPointAmpAccent4;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetAccent4Amp(Envelope,Number,GetEnvelopeNumFrames(Envelope) - 1);

					*OnceOnlyDefinitions |= ENVPOINTDEFINITION_ONCEONLY_AMPACCENT4;
					break;

				case eKeywordAmpaccent5:
					if ((*OnceOnlyDefinitions & ENVPOINTDEFINITION_ONCEONLY_AMPACCENT5) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPointAmpAccent5;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetAccent5Amp(Envelope,Number,GetEnvelopeNumFrames(Envelope) - 1);

					*OnceOnlyDefinitions |= ENVPOINTDEFINITION_ONCEONLY_AMPACCENT5;
					break;

				case eKeywordAmpaccent6:
					if ((*OnceOnlyDefinitions & ENVPOINTDEFINITION_ONCEONLY_AMPACCENT6) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPointAmpAccent6;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetAccent6Amp(Envelope,Number,GetEnvelopeNumFrames(Envelope) - 1);

					*OnceOnlyDefinitions |= ENVPOINTDEFINITION_ONCEONLY_AMPACCENT6;
					break;

				case eKeywordAmpaccent7:
					if ((*OnceOnlyDefinitions & ENVPOINTDEFINITION_ONCEONLY_AMPACCENT7) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPointAmpAccent7;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetAccent7Amp(Envelope,Number,GetEnvelopeNumFrames(Envelope) - 1);

					*OnceOnlyDefinitions |= ENVPOINTDEFINITION_ONCEONLY_AMPACCENT7;
					break;

				case eKeywordAmpaccent8:
					if ((*OnceOnlyDefinitions & ENVPOINTDEFINITION_ONCEONLY_AMPACCENT8) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPointAmpAccent8;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetAccent8Amp(Envelope,Number,GetEnvelopeNumFrames(Envelope) - 1);

					*OnceOnlyDefinitions |= ENVPOINTDEFINITION_ONCEONLY_AMPACCENT8;
					break;

				case eKeywordAmpfreq:
					if ((*OnceOnlyDefinitions & ENVPOINTDEFINITION_ONCEONLY_AMPFREQ) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPointAmpFreq;
						}

					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrNoError;
						}
					if ((GetTokenType(Token) != eTokenKeyword)
						|| (GetTokenKeywordTag(Token) != eKeywordSlope))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedSlope;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetFreqAmpRolloff(Envelope,Number,GetEnvelopeNumFrames(Envelope) - 1);

					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrNoError;
						}
					if ((GetTokenType(Token) != eTokenKeyword)
						|| (GetTokenKeywordTag(Token) != eKeywordCenter))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedCenter;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetFreqAmpNormalization(Envelope,Number,GetEnvelopeNumFrames(Envelope) - 1);

					*OnceOnlyDefinitions |= ENVPOINTDEFINITION_ONCEONLY_AMPFREQ;
					break;

				case eKeywordRateaccent1:
					if ((*OnceOnlyDefinitions & ENVPOINTDEFINITION_ONCEONLY_RATEACCENT1) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPointRateAccent1;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetAccent1Rate(Envelope,Number,GetEnvelopeNumFrames(Envelope) - 1);

					*OnceOnlyDefinitions |= ENVPOINTDEFINITION_ONCEONLY_RATEACCENT1;
					break;

				case eKeywordRateaccent2:
					if ((*OnceOnlyDefinitions & ENVPOINTDEFINITION_ONCEONLY_RATEACCENT2) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPointRateAccent2;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetAccent2Rate(Envelope,Number,GetEnvelopeNumFrames(Envelope) - 1);

					*OnceOnlyDefinitions |= ENVPOINTDEFINITION_ONCEONLY_RATEACCENT2;
					break;

				case eKeywordRateaccent3:
					if ((*OnceOnlyDefinitions & ENVPOINTDEFINITION_ONCEONLY_RATEACCENT3) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPointRateAccent3;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetAccent3Rate(Envelope,Number,GetEnvelopeNumFrames(Envelope) - 1);

					*OnceOnlyDefinitions |= ENVPOINTDEFINITION_ONCEONLY_RATEACCENT3;
					break;

				case eKeywordRateaccent4:
					if ((*OnceOnlyDefinitions & ENVPOINTDEFINITION_ONCEONLY_RATEACCENT4) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPointRateAccent4;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetAccent4Rate(Envelope,Number,GetEnvelopeNumFrames(Envelope) - 1);

					*OnceOnlyDefinitions |= ENVPOINTDEFINITION_ONCEONLY_RATEACCENT4;
					break;

				case eKeywordRateaccent5:
					if ((*OnceOnlyDefinitions & ENVPOINTDEFINITION_ONCEONLY_RATEACCENT5) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPointRateAccent5;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetAccent5Rate(Envelope,Number,GetEnvelopeNumFrames(Envelope) - 1);

					*OnceOnlyDefinitions |= ENVPOINTDEFINITION_ONCEONLY_RATEACCENT5;
					break;

				case eKeywordRateaccent6:
					if ((*OnceOnlyDefinitions & ENVPOINTDEFINITION_ONCEONLY_RATEACCENT6) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPointRateAccent6;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetAccent6Rate(Envelope,Number,GetEnvelopeNumFrames(Envelope) - 1);

					*OnceOnlyDefinitions |= ENVPOINTDEFINITION_ONCEONLY_RATEACCENT6;
					break;

				case eKeywordRateaccent7:
					if ((*OnceOnlyDefinitions & ENVPOINTDEFINITION_ONCEONLY_RATEACCENT7) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPointRateAccent7;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetAccent7Rate(Envelope,Number,GetEnvelopeNumFrames(Envelope) - 1);

					*OnceOnlyDefinitions |= ENVPOINTDEFINITION_ONCEONLY_RATEACCENT7;
					break;

				case eKeywordRateaccent8:
					if ((*OnceOnlyDefinitions & ENVPOINTDEFINITION_ONCEONLY_RATEACCENT8) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPointRateAccent8;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetAccent8Rate(Envelope,Number,GetEnvelopeNumFrames(Envelope) - 1);

					*OnceOnlyDefinitions |= ENVPOINTDEFINITION_ONCEONLY_RATEACCENT8;
					break;

				case eKeywordRatefreq:
					if ((*OnceOnlyDefinitions & ENVPOINTDEFINITION_ONCEONLY_RATEFREQ) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPointRateFreq;
						}

					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrNoError;
						}
					if ((GetTokenType(Token) != eTokenKeyword)
						|| (GetTokenKeywordTag(Token) != eKeywordSlope))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedSlope;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetFreqRateRolloff(Envelope,Number,GetEnvelopeNumFrames(Envelope) - 1);

					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrNoError;
						}
					if ((GetTokenType(Token) != eTokenKeyword)
						|| (GetTokenKeywordTag(Token) != eKeywordCenter))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedCenter;
						}

					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					EnvelopeSetFreqRateNormalization(Envelope,Number,GetEnvelopeNumFrames(Envelope) - 1);

					*OnceOnlyDefinitions |= ENVPOINTDEFINITION_ONCEONLY_RATEFREQ;
					break;

				case eKeywordExponential:
					if ((*OnceOnlyDefinitions & ENVPOINTDEFINITION_ONCEONLY_CURVE) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPointCurveSpec;
						}

					EnvelopeSetPhaseTransitionType(Envelope,GetEnvelopeNumFrames(Envelope) - 1,
						eEnvelopeLinearInDecibels);

					*OnceOnlyDefinitions |= ENVPOINTDEFINITION_ONCEONLY_CURVE;
					break;

				case eKeywordLinear:
					if ((*OnceOnlyDefinitions & ENVPOINTDEFINITION_ONCEONLY_CURVE) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleEnvPointCurveSpec;
						}

					EnvelopeSetPhaseTransitionType(Envelope,GetEnvelopeNumFrames(Envelope) - 1,
						eEnvelopeLinearInAmplitude);

					*OnceOnlyDefinitions |= ENVPOINTDEFINITION_ONCEONLY_CURVE;
					break;
			}

		return eBuildInstrNoError;
	}




/*    1:                   ::= delayline ( <delayelemlist> )  */
/*  XXX:                   ::= nlproc wavetable <string> inputscaling <number> */
/*                             outputscaling <number> wavetableindex <number> */
/*                             <nlattributes> */
/*  XXX:                   ::= filter ( <filterstuff> ) */
/*  XXX:                   ::= analyzer <string> */
/* FOLLOW SET */
/* { ; } */
BuildInstrErrors						ParseTrackEffect(EffectSpecListRec* EffectList,
															ScannerRec* Scanner, long *ErrorLine,
															WaveTableListRec* WaveTableList,
															AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		unsigned long							OnceOnlyEnforcer;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedEffectName;
			}

		switch (GetTokenKeywordTag(Token))
			{
				default:
					*ErrorLine = GetCurrentLineNumber(Scanner);
					return eBuildInstrExpectedEffectName;

				case eKeywordAnalyzer:
					{
						char*										IDString;
						AnalyzerSpecRec*				Analyzer;

						Error = ParseIdentifier(Scanner,ErrorLine,&IDString);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
						Analyzer = NewAnalyzerSpec(IDString);
						ReleasePtr(IDString);
						if (Analyzer == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (!AddAnalyzerToEffectSpecList(EffectList,Analyzer))
							{
								DisposeAnalyzerSpec(Analyzer);
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
					}
					break;

				case eKeywordFilter:
					{
						FilterSpecRec*					FilterSpec;

						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (GetTokenType(Token) != eTokenOpenParen)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedOpenParen;
							}

						FilterSpec = NewFilterSpec();
						if (FilterSpec == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (!AddFilterToEffectSpecList(EffectList,FilterSpec))
							{
								DisposeFilterSpec(FilterSpec);
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}

						Error = ParseFilterList(FilterSpec,Scanner,ErrorLine);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}

						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (GetTokenType(Token) != eTokenCloseParen)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedCloseParen;
							}
					}
					break;

				case eKeywordNlproc:
					{
						struct WaveTableObjectRec*			DataWaveTable;
						struct AlgoWaveTableObjectRec*	AlgoWaveTable;
						char*														WaveTableName;
						NonlinProcSpecRec*							NLProcSpec;
						double													Number;

						/* toss 'wavetable' */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if ((GetTokenType(Token) != eTokenKeyword)
							|| (GetTokenKeywordTag(Token) != eKeywordWavetable))
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedWavetable;
							}
						/* get wavetable name */
						Error = ParseIdentifier(Scanner,ErrorLine,&WaveTableName);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
						DataWaveTable = WaveTableListLookupNamedWaveTable(WaveTableList,
							WaveTableName);
						if (DataWaveTable != NIL)
							{
								NLProcSpec = NewNonlinProcSpecDataWave(DataWaveTable);
								if (NLProcSpec == NIL)
									{
										ReleasePtr(WaveTableName);
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrOutOfMemory;
									}
							}
						 else
							{
								AlgoWaveTable = AlgoWaveTableListLookupNamedAlgoWaveTable(
									AlgoWaveTableList,WaveTableName);
								if (AlgoWaveTable == NIL)
									{
										ReleasePtr(WaveTableName);
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrUndefinedWavetable;
									}
								NLProcSpec = NewNonlinProcSpecAlgoWave(AlgoWaveTable);
								if (NLProcSpec == NIL)
									{
										ReleasePtr(WaveTableName);
										*ErrorLine = GetCurrentLineNumber(Scanner);
										return eBuildInstrOutOfMemory;
									}
							}
						ReleasePtr(WaveTableName);
						if (!AddNLProcToEffectSpecList(EffectList,NLProcSpec))
							{
								DisposeNonlinProcSpec(NLProcSpec);
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						/* toss 'inputscaling' */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if ((GetTokenType(Token) != eTokenKeyword)
							|| (GetTokenKeywordTag(Token) != eKeywordInputscaling))
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedInputscaling;
							}
						/* get input scaling value */
						Error = ParseNumber(Scanner,ErrorLine,&Number);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
						PutNLProcInputScaling(NLProcSpec,Number);
						/* toss 'outputscaling' */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if ((GetTokenType(Token) != eTokenKeyword)
							|| (GetTokenKeywordTag(Token) != eKeywordOutputscaling))
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedOutputscaling;
							}
						/* get the output scaling value */
						Error = ParseNumber(Scanner,ErrorLine,&Number);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
						PutNLProcOutputScaling(NLProcSpec,Number);
						/* toss 'wavetableindex' */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if ((GetTokenType(Token) != eTokenKeyword)
							|| (GetTokenKeywordTag(Token) != eKeywordWavetableindex))
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedWavetableindex;
							}
						/* get wave table index */
						Error = ParseNumber(Scanner,ErrorLine,&Number);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
						PutNLProcWaveTableIndex(NLProcSpec,Number);
						/* parse attributes */
						OnceOnlyEnforcer = 0;
						Error = ParseNLAttributes(NLProcSpec,Scanner,ErrorLine,&OnceOnlyEnforcer);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
					}
					break;

				case eKeywordDelayline:
					{
						DelayEffectRec*						DelayEffect;

						DelayEffect = NewDelayLineSpec();
						if (DelayEffect == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (!AddDelayToEffectSpecList(EffectList,DelayEffect))
							{
								DisposeDelayLineSpec(DelayEffect);
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (GetTokenType(Token) != eTokenOpenParen)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedOpenParen;
							}
						OnceOnlyEnforcer = 0;
						Error = ParseDelayElemList(DelayEffect,Scanner,ErrorLine,&OnceOnlyEnforcer);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (GetTokenType(Token) != eTokenCloseParen)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedCloseParen;
							}
					}
					break;
			}

		return eBuildInstrNoError;
	}




/*    2:   <delayelemlist> ::= <delayelem> ; <delayelemlist>  */
/*    3:                   ::=   */
/* FIRST SET */
/*  <delayelemlist> : {tap, <delayelem>} */
/* FOLLOW SET */
/*  <delayelemlist> : {)} */
BuildInstrErrors						ParseDelayElemList(DelayEffectRec* DelayEffect,
															ScannerRec* Scanner, long *ErrorLine,
															unsigned long* OnceOnlyDefinitions)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) == eTokenCloseParen)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}

		UngetToken(Scanner,Token);
		Error = ParseDelayElem(DelayEffect,Scanner,ErrorLine,OnceOnlyDefinitions);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenSemicolon)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedSemicolon;
			}

		return ParseDelayElemList(DelayEffect,Scanner,ErrorLine,OnceOnlyDefinitions);
	}




/*    6:                   ::= tap <tapsource> <number> to <tapsource> <number> */
/*                             scale <number> <tapattributes> */
/*  XXX:                   ::= maxdelaytime <number> */
BuildInstrErrors						ParseDelayElem(DelayEffectRec* DelayEffect,
															ScannerRec* Scanner, long *ErrorLine,
															unsigned long* OnceOnlyDefinitions)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		double										Number;
		unsigned long							OnceOnlyGuard;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedDelayLineElem;
			}

		switch (GetTokenKeywordTag(Token))
			{
				default:
					*ErrorLine = GetCurrentLineNumber(Scanner);
					return eBuildInstrExpectedDelayLineElem;
				case eKeywordMaxdelaytime: /* maxdelaytime <number> */
					if ((*OnceOnlyDefinitions & DELAYEFFECT_ONCEONLY_MAXDELAYTIME) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleMaxDelayTime;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetDelayMaxTime(DelayEffect,Number);
					*OnceOnlyDefinitions |= DELAYEFFECT_ONCEONLY_MAXDELAYTIME;
					break;
				case eKeywordTap:
					{
						DelayTapRec*					Tap;
						double								Number;
						unsigned long					OnceOnlyGuard;

						/* tap <tapsource> <number> to <tapsource> <number> scale */
						/* <number> <tapattributes>  */
						/* --- <tapsource> == {left, right, mono} */
						Tap = NewDelayTap();
						if (Tap == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (!AppendTapToDelayEffect(DelayEffect,Tap))
							{
								DisposeDelayTap(Tap);
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						/* do source */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (GetTokenType(Token) != eTokenKeyword)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedTapChannel;
							}
						switch (GetTokenKeywordTag(Token))
							{
								default:
									*ErrorLine = GetCurrentLineNumber(Scanner);
									return eBuildInstrExpectedTapChannel;
								case eKeywordLeft:
									SetDelayTapSource(Tap,eTapLeftChannel);
									break;
								case eKeywordRight:
									SetDelayTapSource(Tap,eTapRightChannel);
									break;
								case eKeywordMono:
									SetDelayTapSource(Tap,eTapMonoChannel);
									break;
							}
						/* get source delay time */
						Error = ParseNumber(Scanner,ErrorLine,&Number);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
						SetDelayTapSourceTime(Tap,Number);
						/* eat "to" */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if ((GetTokenType(Token) != eTokenKeyword)
							|| (GetTokenKeywordTag(Token) != eKeywordTo))
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedTo;
							}
						/* tap target */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if (GetTokenType(Token) != eTokenKeyword)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedTapChannel;
							}
						switch (GetTokenKeywordTag(Token))
							{
								default:
									*ErrorLine = GetCurrentLineNumber(Scanner);
									return eBuildInstrExpectedTapChannel;
								case eKeywordLeft:
									SetDelayTapTarget(Tap,eTapLeftChannel);
									break;
								case eKeywordRight:
									SetDelayTapTarget(Tap,eTapRightChannel);
									break;
								case eKeywordMono:
									SetDelayTapTarget(Tap,eTapMonoChannel);
									break;
							}
						/* get target delay time */
						Error = ParseNumber(Scanner,ErrorLine,&Number);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
						SetDelayTapTargetTime(Tap,Number);
						/* eat "scale" */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if ((GetTokenType(Token) != eTokenKeyword)
							|| (GetTokenKeywordTag(Token) != eKeywordScale))
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedScale;
							}
						/* get scaling number */
						Error = ParseNumber(Scanner,ErrorLine,&Number);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
						SetDelayTapScale(Tap,Number);
						/* do attributes */
						OnceOnlyGuard = 0;
						Error = ParseTapAttributes(Tap,Scanner,ErrorLine,&OnceOnlyGuard);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
					}
					break;
			}

		return eBuildInstrNoError;
	}




/*   13:   <tapattributes> ::= <tapattr> <tapattributes> */
/*   26:                   ::=  */
/* FOLLOW SET */
/*  <tapattributes> : {;} */
BuildInstrErrors						ParseTapAttributes(DelayTapRec* Tap,
															ScannerRec* Scanner, long *ErrorLine,
															unsigned long* OnceOnlyDefinitions)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) == eTokenSemicolon)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		UngetToken(Scanner,Token);

		Error = ParseTapAttr(Tap,Scanner,ErrorLine,OnceOnlyDefinitions);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}

		return ParseTapAttributes(Tap,Scanner,ErrorLine,OnceOnlyDefinitions);
	}




/*  14:                   ::= sourceaccent1 <number> */
/*  15:                   ::= sourceaccent2 <number> */
/*  16:                   ::= sourceaccent3 <number> */
/*  17:                   ::= sourceaccent4 <number> */
/*  18:                   ::= targetaccent1 <number> */
/*  19:                   ::= targetaccent2 <number> */
/*  20:                   ::= targetaccent3 <number> */
/*  21:                   ::= targetaccent4 <number> */
/*  22:                   ::= scaleaccent1 <number> */
/*  23:                   ::= scaleaccent2 <number> */
/*  24:                   ::= scaleaccent3 <number> */
/*  25:                   ::= scaleaccent4 <number> */
/*   X:                   ::= lowpass freq <number> */
/*   X:                   ::= freqaccent1 <number> */
/*   X:                   ::= freqaccent2 <number> */
/*   X:                   ::= freqaccent3 <number> */
/*   X:                   ::= freqaccent4 <number> */
BuildInstrErrors						ParseTapAttr(DelayTapRec* Tap,
															ScannerRec* Scanner, long *ErrorLine,
															unsigned long* OnceOnlyDefinitions)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		double										Number;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedTapAttr;
			}
		switch (GetTokenKeywordTag(Token))
			{
				default:
					*ErrorLine = GetCurrentLineNumber(Scanner);
					return eBuildInstrExpectedTapAttr;
				case eKeywordSourceaccent1:
					if ((*OnceOnlyDefinitions & DELAYEFFECTATTR_ONCEONLY_SOURCEACCENT1) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleSourceAccent1;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetDelayTapSourceTimeAccent1(Tap,Number);
					*OnceOnlyDefinitions |= DELAYEFFECTATTR_ONCEONLY_SOURCEACCENT1;
					break;
				case eKeywordSourceaccent2:
					if ((*OnceOnlyDefinitions & DELAYEFFECTATTR_ONCEONLY_SOURCEACCENT2) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleSourceAccent2;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetDelayTapSourceTimeAccent2(Tap,Number);
					*OnceOnlyDefinitions |= DELAYEFFECTATTR_ONCEONLY_SOURCEACCENT2;
					break;
				case eKeywordSourceaccent3:
					if ((*OnceOnlyDefinitions & DELAYEFFECTATTR_ONCEONLY_SOURCEACCENT3) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleSourceAccent3;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetDelayTapSourceTimeAccent3(Tap,Number);
					*OnceOnlyDefinitions |= DELAYEFFECTATTR_ONCEONLY_SOURCEACCENT3;
					break;
				case eKeywordSourceaccent4:
					if ((*OnceOnlyDefinitions & DELAYEFFECTATTR_ONCEONLY_SOURCEACCENT4) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleSourceAccent4;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetDelayTapSourceTimeAccent4(Tap,Number);
					*OnceOnlyDefinitions |= DELAYEFFECTATTR_ONCEONLY_SOURCEACCENT4;
					break;
				case eKeywordTargetaccent1:
					if ((*OnceOnlyDefinitions & DELAYEFFECTATTR_ONCEONLY_TARGETACCENT1) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleTargetAccent1;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetDelayTapTargetTimeAccent1(Tap,Number);
					*OnceOnlyDefinitions |= DELAYEFFECTATTR_ONCEONLY_TARGETACCENT1;
					break;
				case eKeywordTargetaccent2:
					if ((*OnceOnlyDefinitions & DELAYEFFECTATTR_ONCEONLY_TARGETACCENT2) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleTargetAccent2;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetDelayTapTargetTimeAccent2(Tap,Number);
					*OnceOnlyDefinitions |= DELAYEFFECTATTR_ONCEONLY_TARGETACCENT2;
					break;
				case eKeywordTargetaccent3:
					if ((*OnceOnlyDefinitions & DELAYEFFECTATTR_ONCEONLY_TARGETACCENT3) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleTargetAccent3;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetDelayTapTargetTimeAccent3(Tap,Number);
					*OnceOnlyDefinitions |= DELAYEFFECTATTR_ONCEONLY_TARGETACCENT3;
					break;
				case eKeywordTargetaccent4:
					if ((*OnceOnlyDefinitions & DELAYEFFECTATTR_ONCEONLY_TARGETACCENT4) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleTargetAccent4;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetDelayTapTargetTimeAccent4(Tap,Number);
					*OnceOnlyDefinitions |= DELAYEFFECTATTR_ONCEONLY_TARGETACCENT4;
					break;
				case eKeywordScaleaccent1:
					if ((*OnceOnlyDefinitions & DELAYEFFECTATTR_ONCEONLY_SCALEACCENT1) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleScaleAccent1;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetDelayTapScaleAccent1(Tap,Number);
					*OnceOnlyDefinitions |= DELAYEFFECTATTR_ONCEONLY_SCALEACCENT1;
					break;
				case eKeywordScaleaccent2:
					if ((*OnceOnlyDefinitions & DELAYEFFECTATTR_ONCEONLY_SCALEACCENT2) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleScaleAccent2;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetDelayTapScaleAccent2(Tap,Number);
					*OnceOnlyDefinitions |= DELAYEFFECTATTR_ONCEONLY_SCALEACCENT2;
					break;
				case eKeywordScaleaccent3:
					if ((*OnceOnlyDefinitions & DELAYEFFECTATTR_ONCEONLY_SCALEACCENT3) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleScaleAccent3;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetDelayTapScaleAccent3(Tap,Number);
					*OnceOnlyDefinitions |= DELAYEFFECTATTR_ONCEONLY_SCALEACCENT3;
					break;
				case eKeywordScaleaccent4:
					if ((*OnceOnlyDefinitions & DELAYEFFECTATTR_ONCEONLY_SCALEACCENT4) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleScaleAccent4;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetDelayTapScaleAccent4(Tap,Number);
					*OnceOnlyDefinitions |= DELAYEFFECTATTR_ONCEONLY_SCALEACCENT4;
					break;
				case eKeywordLowpass:
					if ((*OnceOnlyDefinitions & DELAYEFFECTATTR_ONCEONLY_LOWPASSCUTOFF) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleDelayLowpassFreq;
						}
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if ((GetTokenType(Token) != eTokenKeyword)
						|| (GetTokenKeywordTag(Token) != eKeywordFreq))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedFreq;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetDelayTapFilterEnable(Tap,True);
					SetDelayTapFilterCutoff(Tap,Number);
					*OnceOnlyDefinitions |= DELAYEFFECTATTR_ONCEONLY_LOWPASSCUTOFF;
					break;
				case eKeywordFreqaccent1:
					if ((*OnceOnlyDefinitions & DELAYEFFECTATTR_ONCEONLY_CUTOFFACCENT1) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleDelayFilterAccent1;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetDelayTapFilterEnable(Tap,True);
					SetDelayTapFilterCutoffAccent1(Tap,Number);
					*OnceOnlyDefinitions |= DELAYEFFECTATTR_ONCEONLY_CUTOFFACCENT1;
					break;
				case eKeywordFreqaccent2:
					if ((*OnceOnlyDefinitions & DELAYEFFECTATTR_ONCEONLY_CUTOFFACCENT2) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleDelayFilterAccent2;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetDelayTapFilterEnable(Tap,True);
					SetDelayTapFilterCutoffAccent2(Tap,Number);
					*OnceOnlyDefinitions |= DELAYEFFECTATTR_ONCEONLY_CUTOFFACCENT2;
					break;
				case eKeywordFreqaccent3:
					if ((*OnceOnlyDefinitions & DELAYEFFECTATTR_ONCEONLY_CUTOFFACCENT3) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleDelayFilterAccent3;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetDelayTapFilterEnable(Tap,True);
					SetDelayTapFilterCutoffAccent3(Tap,Number);
					*OnceOnlyDefinitions |= DELAYEFFECTATTR_ONCEONLY_CUTOFFACCENT3;
					break;
				case eKeywordFreqaccent4:
					if ((*OnceOnlyDefinitions & DELAYEFFECTATTR_ONCEONLY_CUTOFFACCENT4) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleDelayFilterAccent4;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetDelayTapFilterEnable(Tap,True);
					SetDelayTapFilterCutoffAccent4(Tap,Number);
					*OnceOnlyDefinitions |= DELAYEFFECTATTR_ONCEONLY_CUTOFFACCENT4;
					break;
			}

		return eBuildInstrNoError;
	}




/* <nlattributes>         ::= inputaccent1 <number> */
/*                        ::= inputaccent2 <number> */
/*                        ::= inputaccent3 <number> */
/*                        ::= inputaccent4 <number> */
/*                        ::= outputaccent1 <number> */
/*                        ::= outputaccent2 <number> */
/*                        ::= outputaccent3 <number> */
/*                        ::= outputaccent4 <number> */
/* FOLLOW SET */
/*  <nlattributes> : {;} */
BuildInstrErrors						ParseNLAttributes(NonlinProcSpecRec* NLProcSpec,
															ScannerRec* Scanner, long *ErrorLine,
															unsigned long* OnceOnlyDefinitions)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		double										Number;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) == eTokenSemicolon)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedNLAttribute;
			}
		switch (GetTokenKeywordTag(Token))
			{
				default:
					*ErrorLine = GetCurrentLineNumber(Scanner);
					return eBuildInstrExpectedNLAttribute;
				case eKeywordInputaccent1:
					if ((*OnceOnlyDefinitions & NLPROCEFFECTATTR_ONCEONLY_INPUTACCENT1) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleInputaccent1;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					PutNLProcInputAccent1(NLProcSpec,Number);
					*OnceOnlyDefinitions |= NLPROCEFFECTATTR_ONCEONLY_INPUTACCENT1;
					break;
				case eKeywordInputaccent2:
					if ((*OnceOnlyDefinitions & NLPROCEFFECTATTR_ONCEONLY_INPUTACCENT2) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleInputaccent2;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					PutNLProcInputAccent2(NLProcSpec,Number);
					*OnceOnlyDefinitions |= NLPROCEFFECTATTR_ONCEONLY_INPUTACCENT2;
					break;
				case eKeywordInputaccent3:
					if ((*OnceOnlyDefinitions & NLPROCEFFECTATTR_ONCEONLY_INPUTACCENT3) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleInputaccent3;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					PutNLProcInputAccent3(NLProcSpec,Number);
					*OnceOnlyDefinitions |= NLPROCEFFECTATTR_ONCEONLY_INPUTACCENT3;
					break;
				case eKeywordInputaccent4:
					if ((*OnceOnlyDefinitions & NLPROCEFFECTATTR_ONCEONLY_INPUTACCENT4) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleInputaccent4;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					PutNLProcInputAccent4(NLProcSpec,Number);
					*OnceOnlyDefinitions |= NLPROCEFFECTATTR_ONCEONLY_INPUTACCENT4;
					break;
				case eKeywordOutputaccent1:
					if ((*OnceOnlyDefinitions & NLPROCEFFECTATTR_ONCEONLY_OUTPUTACCENT1) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleOutputaccent1;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					PutNLProcOutputAccent1(NLProcSpec,Number);
					*OnceOnlyDefinitions |= NLPROCEFFECTATTR_ONCEONLY_OUTPUTACCENT1;
					break;
				case eKeywordOutputaccent2:
					if ((*OnceOnlyDefinitions & NLPROCEFFECTATTR_ONCEONLY_OUTPUTACCENT2) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleOutputaccent2;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					PutNLProcOutputAccent2(NLProcSpec,Number);
					*OnceOnlyDefinitions |= NLPROCEFFECTATTR_ONCEONLY_OUTPUTACCENT2;
					break;
				case eKeywordOutputaccent3:
					if ((*OnceOnlyDefinitions & NLPROCEFFECTATTR_ONCEONLY_OUTPUTACCENT3) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleOutputaccent3;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					PutNLProcOutputAccent3(NLProcSpec,Number);
					*OnceOnlyDefinitions |= NLPROCEFFECTATTR_ONCEONLY_OUTPUTACCENT3;
					break;
				case eKeywordOutputaccent4:
					if ((*OnceOnlyDefinitions & NLPROCEFFECTATTR_ONCEONLY_OUTPUTACCENT4) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleOutputaccent4;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					PutNLProcOutputAccent4(NLProcSpec,Number);
					*OnceOnlyDefinitions |= NLPROCEFFECTATTR_ONCEONLY_OUTPUTACCENT4;
					break;
				case eKeywordIndexaccent1:
					if ((*OnceOnlyDefinitions & NLPROCEFFECTATTR_ONCEONLY_INDEXACCENT1) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleIndexaccent1;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					PutNLProcIndexAccent1(NLProcSpec,Number);
					*OnceOnlyDefinitions |= NLPROCEFFECTATTR_ONCEONLY_INDEXACCENT1;
					break;
				case eKeywordIndexaccent2:
					if ((*OnceOnlyDefinitions & NLPROCEFFECTATTR_ONCEONLY_INDEXACCENT2) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleIndexaccent2;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					PutNLProcIndexAccent2(NLProcSpec,Number);
					*OnceOnlyDefinitions |= NLPROCEFFECTATTR_ONCEONLY_INDEXACCENT2;
					break;
				case eKeywordIndexaccent3:
					if ((*OnceOnlyDefinitions & NLPROCEFFECTATTR_ONCEONLY_INDEXACCENT3) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleIndexaccent3;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					PutNLProcIndexAccent3(NLProcSpec,Number);
					*OnceOnlyDefinitions |= NLPROCEFFECTATTR_ONCEONLY_INDEXACCENT3;
					break;
				case eKeywordIndexaccent4:
					if ((*OnceOnlyDefinitions & NLPROCEFFECTATTR_ONCEONLY_INDEXACCENT4) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleIndexaccent4;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					PutNLProcIndexAccent4(NLProcSpec,Number);
					*OnceOnlyDefinitions |= NLPROCEFFECTATTR_ONCEONLY_INDEXACCENT4;
					break;
			}

		return ParseNLAttributes(NLProcSpec,Scanner,ErrorLine,OnceOnlyDefinitions);
	}




/*  XXX:                   ::= filter <filter> <filterlist> */
/*  XXX:                   ::= */
/* FOLLOW SET */
/* { ) } */
BuildInstrErrors						ParseFilterList(FilterSpecRec* FilterSpec,
															ScannerRec* Scanner, long *ErrorLine)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) == eTokenCloseParen)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		if ((GetTokenType(Token) != eTokenKeyword)
			|| (GetTokenKeywordTag(Token) != eKeywordFilter))
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedFilter;
			}

		Error = ParseFilter(FilterSpec,Scanner,ErrorLine);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}

		return ParseFilterList(FilterSpec,Scanner,ErrorLine);
	}




/*  XXX:                   ::= <filtertype> [order <number>] freq <number> */
/*                           [order <number>]<bandwidth> <gain> */
/*                           <scaling> <channel> <filterattributes> ; */
BuildInstrErrors						ParseFilter(FilterSpecRec* FilterSpec,
															ScannerRec* Scanner, long *ErrorLine)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		FilterTypes								FilterType;
		OneFilterRec*							FilterElement;
		double										Number;
		unsigned long							OnceOnlyChecker;

		/* <filtertype> */
		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedFilterType;
			}
		switch (GetTokenKeywordTag(Token))
			{
				default:
					*ErrorLine = GetCurrentLineNumber(Scanner);
					return eBuildInstrExpectedFilterType;
				case eKeywordNull:
					FilterType = eFilterNull;
					break;
				case eKeywordLowpass:
					FilterType = eFilterFirstOrderLowpass;
					break;
				case eKeywordHighpass:
					FilterType = eFilterFirstOrderHighpass;
					break;
				case eKeywordReson:
					FilterType = eFilterSecondOrderResonant;
					break;
				case eKeywordZero:
					FilterType = eFilterSecondOrderZero;
					break;
				case eKeywordButterworthlowpass:
					FilterType = eFilterButterworthLowpass;
					break;
				case eKeywordButterworthhighpass:
					FilterType = eFilterButterworthHighpass;
					break;
				case eKeywordButterworthbandpass:
					FilterType = eFilterButterworthBandpass;
					break;
				case eKeywordButterworthbandreject:
					FilterType = eFilterButterworthBandreject;
					break;
				case eKeywordParameq:
					FilterType = eFilterParametricEQ;
					break;
				case eKeywordResonantlowpass:
					FilterType = eFilterResonantLowpass;
					break;
			}

		FilterElement = NewSingleFilterSpec(FilterType);
		if (FilterElement == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (!AppendFilterToSpec(FilterSpec,FilterElement))
			{
				DisposeSingleFilterSpec(FilterElement);
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}

		/* freq <number> */
		if (FilterType != eFilterNull)
			{
				if (FilterType == eFilterResonantLowpass)
					{
						double				Order;
						long					Order2;

						/* order <number> */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if ((GetTokenType(Token) != eTokenKeyword)
							|| (GetTokenKeywordTag(Token) != eKeywordOrder))
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedOrder;
							}
						/* get order number */
						Error = ParseNumber(Scanner,ErrorLine,&Order);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
						Order2 = Order;
						if ((Order2 < 0) || (Order2 != Order) || ((Order2 % 2) != 0))
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOrderMustBeNonNegativeEvenInteger;
							}
						/* remember value */
						SetFilterLowpassOrder(FilterElement,Order2);
					}
				/* freq */
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if ((GetTokenType(Token) != eTokenKeyword)
					|| (GetTokenKeywordTag(Token) != eKeywordFreq))
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedFreq;
					}
				/* <number> */
				Error = ParseNumber(Scanner,ErrorLine,&Number);
				if (Error != eBuildInstrNoError)
					{
						return Error;
					}
				SetSingleFilterCutoff(FilterElement,Number);
			}

		/* <bandwidth>             ::= bandwidth <number>  */
		/*                         ::= */
		if ((FilterType == eFilterSecondOrderResonant)
			|| (FilterType == eFilterSecondOrderZero)
			|| (FilterType == eFilterButterworthBandpass)
			|| (FilterType == eFilterButterworthBandreject)
			|| (FilterType == eFilterParametricEQ)
			|| (FilterType == eFilterResonantLowpass))
			{
				if (FilterType == eFilterResonantLowpass)
					{
						double				Order;
						long					Order2;

						/* order <number> */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if ((GetTokenType(Token) != eTokenKeyword)
							|| (GetTokenKeywordTag(Token) != eKeywordOrder))
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedOrder;
							}
						/* get order number */
						Error = ParseNumber(Scanner,ErrorLine,&Order);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
						Order2 = Order;
						if ((Order2 < 0) || (Order2 != Order) || ((Order2 % 2) != 0))
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOrderMustBeNonNegativeEvenInteger;
							}
						/* remember value */
						SetFilterBandpassOrder(FilterElement,Order2);
					}
				/* bandwidth */
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if ((GetTokenType(Token) != eTokenKeyword)
					|| (GetTokenKeywordTag(Token) != eKeywordBandwidth))
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedBandwidth;
					}
				/* <number> */
				Error = ParseNumber(Scanner,ErrorLine,&Number);
				if (Error != eBuildInstrNoError)
					{
						return Error;
					}
				SetSingleFilterBandwidth(FilterElement,Number);
			}

		/* <gain>                  ::= gain <number>  */
		/*                         ::= */
		if ((FilterType == eFilterParametricEQ)
			|| (FilterType == eFilterResonantLowpass))
			{
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if ((GetTokenType(Token) != eTokenKeyword)
					|| (GetTokenKeywordTag(Token) != eKeywordGain))
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedGain;
					}
				Error = ParseNumber(Scanner,ErrorLine,&Number);
				if (Error != eBuildInstrNoError)
					{
						return Error;
					}
				SetSingleFilterGain(FilterElement,Number);
			}

		/* scaling mode */
		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if ((GetTokenType(Token) == eTokenKeyword)
			&& ((GetTokenKeywordTag(Token) == eKeywordDefaultscaling)
				|| (GetTokenKeywordTag(Token) == eKeywordUnitymidbandgain)
				|| (GetTokenKeywordTag(Token) == eKeywordUnitynoisegain)
				|| (GetTokenKeywordTag(Token) == eKeywordUnityzerohertzgain)))
			{
				switch (FilterType)
					{
						default:
							EXECUTE(PRERR(ForceAbort,"ParseFilter:  bad filter type"));
							break;
						case eFilterNull:
						case eFilterFirstOrderLowpass:
						case eFilterFirstOrderHighpass:
						case eFilterButterworthLowpass:
						case eFilterButterworthHighpass:
						case eFilterButterworthBandpass:
						case eFilterButterworthBandreject:
						case eFilterParametricEQ:
						case eFilterResonantLowpass:
							if (GetTokenKeywordTag(Token) != eKeywordDefaultscaling)
								{
									*ErrorLine = GetCurrentLineNumber(Scanner);
									return eBuildInstrExpectedDefaultScaling;
								}
							break;
						case eFilterSecondOrderResonant:
							if (GetTokenKeywordTag(Token) == eKeywordDefaultscaling)
								{
								}
							else if (GetTokenKeywordTag(Token) == eKeywordUnitymidbandgain)
								{
									SetSingleFilterScalingMode(FilterElement,eFilterResonMidbandGain1);
								}
							else if (GetTokenKeywordTag(Token) == eKeywordUnitynoisegain)
								{
									SetSingleFilterScalingMode(FilterElement,eFilterResonNoiseGain1);
								}
							else
								{
									*ErrorLine = GetCurrentLineNumber(Scanner);
									return eBuildInstrExpectedResonScaling;
								}
							break;
						case eFilterSecondOrderZero:
							if (GetTokenKeywordTag(Token) == eKeywordDefaultscaling)
								{
								}
							else if (GetTokenKeywordTag(Token) == eKeywordUnityzerohertzgain)
								{
									SetSingleFilterScalingMode(FilterElement,eFilterZeroGain1);
								}
							else
								{
									*ErrorLine = GetCurrentLineNumber(Scanner);
									return eBuildInstrExpectedZeroScaling;
								}
							break;
					}
			}
		 else
			{
				UngetToken(Scanner,Token);
			}

		/* <channel> ::= {left | right | mono} */
		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedFilterChannel;
			}
		switch (GetTokenKeywordTag(Token))
			{
				default:
					*ErrorLine = GetCurrentLineNumber(Scanner);
					return eBuildInstrExpectedFilterChannel;
				case eKeywordLeft:
					SetSingleFilterChannel(FilterElement,eFilterLeft);
					break;
				case eKeywordRight:
					SetSingleFilterChannel(FilterElement,eFilterRight);
					break;
				case eKeywordMono:
					SetSingleFilterChannel(FilterElement,eFilterBoth);
					break;
			}

		/* <filterattributes> */
		OnceOnlyChecker = 0;
		Error = ParseFilterAttributes(FilterElement,Scanner,ErrorLine,
			&OnceOnlyChecker,FilterType);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenSemicolon)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedSemicolon;
			}

		return eBuildInstrNoError;
	}




/* XXX:                    ::= <filterattr> <filterattributes> */
/*                         ::= */
/* FOLLOW SET: */
/* { ; } */
BuildInstrErrors						ParseFilterAttributes(OneFilterRec* FilterElement,
															ScannerRec* Scanner, long *ErrorLine,
															unsigned long* OnceOnlyDefinitions,
															FilterTypes FilterType)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) == eTokenSemicolon)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		UngetToken(Scanner,Token);

		Error = ParseFilterAttr(FilterElement,Scanner,ErrorLine,
			OnceOnlyDefinitions,FilterType);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}

		return ParseFilterAttributes(FilterElement,Scanner,ErrorLine,
			OnceOnlyDefinitions,FilterType);
	}




/* XXX:                    ::= freqaccent1 <number> */
/*                         ::= freqaccent2 <number> */
/*                         ::= freqaccent3 <number> */
/*                         ::= freqaccent4 <number> */
/*                         ::= bandwidthaccent1 <number> */
/*                         ::= bandwidthaccent2 <number> */
/*                         ::= bandwidthaccent3 <number> */
/*                         ::= bandwidthaccent4 <number> */
/*                         ::= outputscaling <number> */
/*                         ::= outputscalingaccent1 <number> */
/*                         ::= outputscalingaccent2 <number> */
/*                         ::= outputscalingaccent3 <number> */
/*                         ::= outputscalingaccent4 <number> */
/*                         ::= gainaccent1 <number> */
/*                         ::= gainaccent2 <number> */
/*                         ::= gainaccent3 <number> */
/*                         ::= gainaccent4 <number> */
BuildInstrErrors						ParseFilterAttr(OneFilterRec* FilterElement,
															ScannerRec* Scanner, long *ErrorLine,
															unsigned long* OnceOnlyDefinitions,
															FilterTypes FilterType)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		double										Number;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedFilterAttr;
			}
		switch (GetTokenKeywordTag(Token))
			{
				default:
					*ErrorLine = GetCurrentLineNumber(Scanner);
					return eBuildInstrExpectedFilterAttr;
				case eKeywordFreqaccent1:
					if (FilterType == eFilterNull)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrNullFilterHasNoFreqAccent1;
						}
					if ((*OnceOnlyDefinitions & FILTEREFFECTATTR_ONCEONLY_FREQACCENT1) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleFreqaccent1;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetSingleFilterCutoffAccent1(FilterElement,Number);
					*OnceOnlyDefinitions |= FILTEREFFECTATTR_ONCEONLY_FREQACCENT1;
					break;
				case eKeywordFreqaccent2:
					if (FilterType == eFilterNull)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrNullFilterHasNoFreqAccent2;
						}
					if ((*OnceOnlyDefinitions & FILTEREFFECTATTR_ONCEONLY_FREQACCENT2) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleFreqaccent2;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetSingleFilterCutoffAccent2(FilterElement,Number);
					*OnceOnlyDefinitions |= FILTEREFFECTATTR_ONCEONLY_FREQACCENT2;
					break;
				case eKeywordFreqaccent3:
					if (FilterType == eFilterNull)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrNullFilterHasNoFreqAccent3;
						}
					if ((*OnceOnlyDefinitions & FILTEREFFECTATTR_ONCEONLY_FREQACCENT3) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleFreqaccent3;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetSingleFilterCutoffAccent3(FilterElement,Number);
					*OnceOnlyDefinitions |= FILTEREFFECTATTR_ONCEONLY_FREQACCENT3;
					break;
				case eKeywordFreqaccent4:
					if (FilterType == eFilterNull)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrNullFilterHasNoFreqAccent4;
						}
					if ((*OnceOnlyDefinitions & FILTEREFFECTATTR_ONCEONLY_FREQACCENT4) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleFreqaccent4;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetSingleFilterCutoffAccent4(FilterElement,Number);
					*OnceOnlyDefinitions |= FILTEREFFECTATTR_ONCEONLY_FREQACCENT4;
					break;
				case eKeywordBandwidthaccent1:
					if ((FilterType != eFilterSecondOrderResonant)
						&& (FilterType != eFilterSecondOrderZero)
						&& (FilterType != eFilterButterworthBandpass)
						&& (FilterType != eFilterButterworthBandreject)
						&& (FilterType != eFilterParametricEQ)
						&& (FilterType != eFilterResonantLowpass))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrFilterHasNoBandwidthAccent1;
						}
					if ((*OnceOnlyDefinitions & FILTEREFFECTATTR_ONCEONLY_BANDWIDTHACCENT1) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleBandwidthaccent1;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetSingleFilterBandwidthAccent1(FilterElement,Number);
					*OnceOnlyDefinitions |= FILTEREFFECTATTR_ONCEONLY_BANDWIDTHACCENT1;
					break;
				case eKeywordBandwidthaccent2:
					if ((FilterType != eFilterSecondOrderResonant)
						&& (FilterType != eFilterSecondOrderZero)
						&& (FilterType != eFilterButterworthBandpass)
						&& (FilterType != eFilterButterworthBandreject)
						&& (FilterType != eFilterParametricEQ)
						&& (FilterType != eFilterResonantLowpass))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrFilterHasNoBandwidthAccent2;
						}
					if ((*OnceOnlyDefinitions & FILTEREFFECTATTR_ONCEONLY_BANDWIDTHACCENT2) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleBandwidthaccent2;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetSingleFilterBandwidthAccent2(FilterElement,Number);
					*OnceOnlyDefinitions |= FILTEREFFECTATTR_ONCEONLY_BANDWIDTHACCENT2;
					break;
				case eKeywordBandwidthaccent3:
					if ((FilterType != eFilterSecondOrderResonant)
						&& (FilterType != eFilterSecondOrderZero)
						&& (FilterType != eFilterButterworthBandpass)
						&& (FilterType != eFilterButterworthBandreject)
						&& (FilterType != eFilterParametricEQ)
						&& (FilterType != eFilterResonantLowpass))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrFilterHasNoBandwidthAccent3;
						}
					if ((*OnceOnlyDefinitions & FILTEREFFECTATTR_ONCEONLY_BANDWIDTHACCENT3) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleBandwidthaccent3;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetSingleFilterBandwidthAccent3(FilterElement,Number);
					*OnceOnlyDefinitions |= FILTEREFFECTATTR_ONCEONLY_BANDWIDTHACCENT3;
					break;
				case eKeywordBandwidthaccent4:
					if ((FilterType != eFilterSecondOrderResonant)
						&& (FilterType != eFilterSecondOrderZero)
						&& (FilterType != eFilterButterworthBandpass)
						&& (FilterType != eFilterButterworthBandreject)
						&& (FilterType != eFilterParametricEQ)
						&& (FilterType != eFilterResonantLowpass))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrFilterHasNoBandwidthAccent4;
						}
					if ((*OnceOnlyDefinitions & FILTEREFFECTATTR_ONCEONLY_BANDWIDTHACCENT4) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleBandwidthaccent4;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetSingleFilterBandwidthAccent4(FilterElement,Number);
					*OnceOnlyDefinitions |= FILTEREFFECTATTR_ONCEONLY_BANDWIDTHACCENT4;
					break;
				case eKeywordOutputscaling:
					if ((*OnceOnlyDefinitions & FILTEREFFECTATTR_ONCEONLY_OUTPUTSCALING) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleOutputScaling;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetSingleFilterOutputMultiplier(FilterElement,Number);
					*OnceOnlyDefinitions |= FILTEREFFECTATTR_ONCEONLY_OUTPUTSCALING;
					break;
				case eKeywordOutputaccent1:
					if ((*OnceOnlyDefinitions & FILTEREFFECTATTR_ONCEONLY_OUTPUTSCALINGACCENT1) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleOutputScalingAccent1;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetSingleFilterOutputMultiplierAccent1(FilterElement,Number);
					*OnceOnlyDefinitions |= FILTEREFFECTATTR_ONCEONLY_OUTPUTSCALINGACCENT1;
					break;
				case eKeywordOutputaccent2:
					if ((*OnceOnlyDefinitions & FILTEREFFECTATTR_ONCEONLY_OUTPUTSCALINGACCENT2) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleOutputScalingAccent2;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetSingleFilterOutputMultiplierAccent2(FilterElement,Number);
					*OnceOnlyDefinitions |= FILTEREFFECTATTR_ONCEONLY_OUTPUTSCALINGACCENT2;
					break;
				case eKeywordOutputaccent3:
					if ((*OnceOnlyDefinitions & FILTEREFFECTATTR_ONCEONLY_OUTPUTSCALINGACCENT3) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleOutputScalingAccent3;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetSingleFilterOutputMultiplierAccent3(FilterElement,Number);
					*OnceOnlyDefinitions |= FILTEREFFECTATTR_ONCEONLY_OUTPUTSCALINGACCENT3;
					break;
				case eKeywordOutputaccent4:
					if ((*OnceOnlyDefinitions & FILTEREFFECTATTR_ONCEONLY_OUTPUTSCALINGACCENT4) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleOutputScalingAccent4;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetSingleFilterOutputMultiplierAccent4(FilterElement,Number);
					*OnceOnlyDefinitions |= FILTEREFFECTATTR_ONCEONLY_OUTPUTSCALINGACCENT4;
					break;
				case eKeywordGainaccent1:
					if ((FilterType != eFilterParametricEQ)
						&& (FilterType != eFilterResonantLowpass))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrFilterHasNoGainAccent1;
						}
					if ((*OnceOnlyDefinitions & FILTEREFFECTATTR_ONCEONLY_GAINACCENT1) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleGainAccent1;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetSingleFilterGainAccent1(FilterElement,Number);
					*OnceOnlyDefinitions |= FILTEREFFECTATTR_ONCEONLY_GAINACCENT1;
					break;
				case eKeywordGainaccent2:
					if ((FilterType != eFilterParametricEQ)
						&& (FilterType != eFilterResonantLowpass))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrFilterHasNoGainAccent2;
						}
					if ((*OnceOnlyDefinitions & FILTEREFFECTATTR_ONCEONLY_GAINACCENT2) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleGainAccent2;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetSingleFilterGainAccent2(FilterElement,Number);
					*OnceOnlyDefinitions |= FILTEREFFECTATTR_ONCEONLY_GAINACCENT2;
					break;
				case eKeywordGainaccent3:
					if ((FilterType != eFilterParametricEQ)
						&& (FilterType != eFilterResonantLowpass))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrFilterHasNoGainAccent3;
						}
					if ((*OnceOnlyDefinitions & FILTEREFFECTATTR_ONCEONLY_GAINACCENT3) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleGainAccent3;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetSingleFilterGainAccent3(FilterElement,Number);
					*OnceOnlyDefinitions |= FILTEREFFECTATTR_ONCEONLY_GAINACCENT3;
					break;
				case eKeywordGainaccent4:
					if ((FilterType != eFilterParametricEQ)
						&& (FilterType != eFilterResonantLowpass))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrFilterHasNoGainAccent4;
						}
					if ((*OnceOnlyDefinitions & FILTEREFFECTATTR_ONCEONLY_GAINACCENT4) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleGainAccent4;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetSingleFilterGainAccent4(FilterElement,Number);
					*OnceOnlyDefinitions |= FILTEREFFECTATTR_ONCEONLY_GAINACCENT4;
					break;
			}

		return eBuildInstrNoError;
	}




/* <oscdelayelems>          ::= <oscdelayelem> ; <oscdelayelems> */
/*                          ::= */
/* FOLLOW SET */
/* { ) } */
BuildInstrErrors						ParseOscDelayElems(DelayEffectRec* DelayEffect,
															ScannerRec* Scanner, long *ErrorLine,
															unsigned long* OnceOnlyDefinitions,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		DelayTapRec*							DelayTap;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) == eTokenCloseParen)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		UngetToken(Scanner,Token);

		DelayTap = NewDelayTap();
		if (DelayTap == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (!AppendTapToDelayEffect(DelayEffect,DelayTap))
			{
				DisposeDelayTap(DelayTap);
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}

		Error = ParseOscDelayElem(DelayEffect,DelayTap,Scanner,ErrorLine,
			OnceOnlyDefinitions,GetDelayEffectSpecNumTaps(DelayEffect) - 1/*index*/,
			WaveTableList,AlgoWaveTableList);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenSemicolon)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedSemicolon;
			}

		return ParseOscDelayElems(DelayEffect,Scanner,ErrorLine,OnceOnlyDefinitions,
			WaveTableList,AlgoWaveTableList);
	}
