Below is most of the code for the JSON Parser state machine function..

#include "stdafx.h"

#include "jsonparser.h"

//For working out error source in code:
int ErrNo = -1;

/////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////
/// Json Parse code
/// Parses JSon string both for records and name value pairs within records
/// Parser parses a stream and is implemented as a State machine

// Parser state machine states:
enum Expecting
{
	...
	...
};


void IncrementState()
{
	...
	...
}

BOOL Expect(char c)
{
	...
	...
}

//The current state of the State Machine
Expecting parseState = startOfArray;

//Assume by default getting an array, ie starts with 
//If starts with { then just getting one record so jump to that mode and done one that record is interpretted.
BOOL gGettingArray = true;

NameValue CurrentNameValue;

/*
Parses a JSon array of records of name value pairs
*/
BOOL ParseJsonString(char c)
{

	//If result is false then subsequent parses are aborted
	BOOL result = true;
	ErrNo = -1;
	int strnlength;

	// Signal to format print a name-vale pair after switch statement
	BOOL gotANameValuePair = false;

	switch (parseState)
	{
		case startOfArray:
			result = Expect(c);
			if (result)
			{
				//Start of array so no records yet.
				RecordNo = 0;
				output.println(F("\r\n1: Starting parse of array."));
			}
			//If the string starts with { just getting one record rather than an array
			if (parseState == startOfName)
			{
				RecordNo++;
				//Start of new record so no no name value pairs yet
				NameValueIndex = 0;
				output.println(F("\r\n2: New record."));
				gGettingArray = false;
			}
			break;
		case startOfRecord:
			result = Expect(c);
			if (result)
			{
				RecordNo++;
				//Start of new record so no no name value pairs yet
				NameValueIndex = 0;
				output.println(F("\r\n2: New record."));
			}
			break;
		case startOfName:
			result = Expect(c);
			if (result)
			{
				NameValueIndex++;
				int index = REC_NO(RecordNo - 1, NameValueIndex - 1);
				if (1 == 0) //(index >= MAX_NO_NAME_VALUE_PAIRS)
				{
					output.println(F("\r\n2: Max No of Name-value pairs exceeded"));
					ErrNo = 11;
					NameValueIndex--;
					RecordNo--;
					result = false;
				}
				else
				{
					//output.println(F("3: New record Name-Value Pair."));

					strcpy(CurrentNameValue.Name, "");
					strcpy(CurrentNameValue.StringValue, "");
					CurrentNameValue.BooleanValue = false;
					CurrentNameValue.IntegerValue = 0;
					CurrentNameValue.FloatValue = 0;
					CurrentNameValue.DType = tUnknown;
				}
			}
			break;
		case gettingName:
			if (c != '\"')
			{
				//output.println(F("4: Getting Name-Value Name."));
				//Append to name
				strnlength = strlen(CurrentNameValue.Name);
				if (strnlength == 0)
				{
					if ((isalpha(c)) || (c == '_'))  //Can lead only with alpha and _
					{
						strnlength = strlen(CurrentNameValue.Name);
						CurrentNameValue.Name[strnlength] = c;
						CurrentNameValue.Name[strnlength + 1] = '\0';
					}
					else
					{
						result = false;
						ErrNo = 101;
					}
				}
				else if ((isalpha(c)) || (c == '_') || (isdigit(c)))  //Can use _ or alpha in name
				{
					strnlength = strlen(CurrentNameValue.Name);
					CurrentNameValue.Name[strnlength] = c;
					CurrentNameValue.Name[strnlength + 1] = '\0';
				}
				else
				if (parseState != done)
				{
					result = false;
					ErrNo = 1;
				}
			}
			else
			{
				//Got end of name
				IncrementState();
			}
			break;
		case nameValueSeparator:
			result = Expect(c);
			break;
		case startOfValue:
			//output.println(F("Getting value."));
			CurrentNameValue.StringValue[0] = '\0';
			switch (c)
			{
			case '\"':
				parseState = gettingString;
				break;
			case 'T':
				parseState = gettingBoolean;
				strnlength = strlen(CurrentNameValue.StringValue);
				CurrentNameValue.StringValue[strnlength] = c;
				CurrentNameValue.StringValue[strnlength + 1] = '\0';
				break;
			case 't':
				parseState = gettingBoolean;
				strnlength = strlen(CurrentNameValue.StringValue);
				CurrentNameValue.StringValue[strnlength] = c;
				CurrentNameValue.StringValue[strnlength + 1] = '\0';
				break;
			case 'F':
				parseState = gettingBoolean;
				strnlength = strlen(CurrentNameValue.StringValue);
				CurrentNameValue.StringValue[strnlength] = c;
				CurrentNameValue.StringValue[strnlength + 1] = '\0';
				break;
			case 'f':
				parseState = gettingBoolean;
				strnlength = strlen(CurrentNameValue.StringValue);
				CurrentNameValue.StringValue[strnlength] = c;
				CurrentNameValue.StringValue[strnlength + 1] = '\0';
				break;
			case 'N':
				parseState = gettingNull;
				strnlength = strlen(CurrentNameValue.StringValue);
				CurrentNameValue.StringValue[strnlength] = c;
				CurrentNameValue.StringValue[strnlength + 1] = '\0';
				break;
			case 'n':
				parseState = gettingNull;
				strnlength = strlen(CurrentNameValue.StringValue);
				CurrentNameValue.StringValue[strnlength] = c;
				CurrentNameValue.StringValue[strnlength + 1] = '\0';
				break;
			default:
				if (isdigit(c))
				{
					parseState = gettingInteger;
					strnlength = strlen(CurrentNameValue.StringValue);
					CurrentNameValue.StringValue[strnlength] = c;
					CurrentNameValue.StringValue[strnlength + 1] = '\0';
				}
				else
				{
					ErrNo = 2;
					result = false;
				}
				break;
			}
			break;
		case gettingString:
			if (c == '\"')
			{
				gotANameValuePair = true;
				CurrentNameValue.DType = tString;
				parseState = gettingEndOfValueORRecord;
			}
			else
			{ //Added these brackets 5/4/15
				strnlength = strlen(CurrentNameValue.StringValue);
				CurrentNameValue.StringValue[strnlength] = c;
				CurrentNameValue.StringValue[strnlength + 1] = '\0';
			}
			break;
		case gettingBoolean:
			if ((c == '}') || (c == ','))
			{
				if (c == '}')
					parseState = gotEndOfRecord;
				else
				{
					//Comma, so start new name-value pair
					parseState = startOfName;
				}
				int i = -1;
				while (CurrentNameValue.StringValue[++i])
				{
					CurrentNameValue.StringValue[i] = tolower(CurrentNameValue.StringValue[i]);
				}
				if (strcmp(CurrentNameValue.StringValue, "false") == 0)
				{
					CurrentNameValue.BooleanValue = false;
					CurrentNameValue.DType = tBoolean;
					gotANameValuePair = true;
				}
				else if (strcmp(CurrentNameValue.StringValue, "true") == 0)
				{
					CurrentNameValue.BooleanValue = true;
					CurrentNameValue.DType = tBoolean;
					gotANameValuePair = true;
				}
				else
				{
					ErrNo = 3;
					result = false;
				}
			}
			else
			{
				strnlength = strlen(CurrentNameValue.StringValue);
				CurrentNameValue.StringValue[strnlength] = c;
				CurrentNameValue.StringValue[strnlength + 1] = '\0';
			}
			break;
		case gettingNull:
			if ((c == '}') || (c == ','))
			{
				if (c == '}')
					parseState = gotEndOfRecord;
				else
				{
					//Comma, so start new name-value pair
					parseState = startOfName;
				}
				int i = 0;
				while (CurrentNameValue.StringValue[i])
				{
					CurrentNameValue.StringValue[i] = tolower(CurrentNameValue.StringValue[i++]);
				}
				if (strcmp(CurrentNameValue.StringValue, "null") == 0)
				{
					CurrentNameValue.BooleanValue = false;
					CurrentNameValue.DType = tNull;
					gotANameValuePair = true;
				}
				else
				{
					ErrNo = 4;
					result = false;
				}
			}
			else
			{
				strnlength = strlen(CurrentNameValue.StringValue);
				CurrentNameValue.StringValue[strnlength] = c;
				CurrentNameValue.StringValue[strnlength + 1] = '\0';
			}
			break;
		case gettingInteger:
			if ((c == '}') || (c == ','))
			{
				int val = atoi(CurrentNameValue.StringValue);
				CurrentNameValue.IntegerValue = val;
				CurrentNameValue.DType = tInteger;
				gotANameValuePair = true;
				if (c == '}')
				{
					parseState = gotEndOfRecord;
				}
				else
					//Comma, so start new name-value pair
					parseState = startOfName;
			}
			else if (c == '.')
			{
				parseState = gettingFloat;
				strnlength = strlen(CurrentNameValue.StringValue);
				CurrentNameValue.StringValue[strnlength] = c;
				CurrentNameValue.StringValue[strnlength + 1] = '\0';
			}
			else if (isdigit(c))
			{
				strnlength = strlen(CurrentNameValue.StringValue);
				CurrentNameValue.StringValue[strnlength] = c;
				CurrentNameValue.StringValue[strnlength + 1] = '\0';
			}
			else
			{
				ErrNo = 5;
				result = false;
			}
			break;
		case gettingFloat:
			if ((c == '}') || (c == ','))
			{
				//Parse number
				CurrentNameValue.FloatValue = (float) atof(CurrentNameValue.StringValue);
				CurrentNameValue.DType = tFloat;
				gotANameValuePair = true;
				if (c == '}')
				{
					parseState = gotEndOfRecord;
				}
				else
					//Comma, so start new name-value pair
					parseState = startOfName;
			}
			else if (isdigit(c))
			{
				strnlength = strlen(CurrentNameValue.StringValue);
				CurrentNameValue.StringValue[strnlength] = c;
				CurrentNameValue.StringValue[strnlength + 1] = '\0';
			}
			else
			{
				ErrNo = 6;
				result = false;
			}
			break;
		case gettingEndOfValueORRecord:
			//PREV: gettingString
			//This state is only taken (as next state) after  the end of a string literal
			if ((c == '}') || (c == ','))
			{
				if (c == '}')
				{
					parseState = gotEndOfRecord;
					if (!gGettingArray)
					{
						output.println(F("End of Record."));
						output.println(F("End of Array.\r\n"));
						parseState = done;
					}
				}
				else
				{
					parseState = startOfName;
				}
			}
			else
			{
				ErrNo = 7;
				result = false;
			}
			break;
		case gotEndOfRecord:
			// PREV : getting<value type except string> or gettingEndOfValueORRecord
			// After a record can get comma which means more name-values to come
			// Or  which means at end of array and string
			if (c == ',')
			{
				//Got comma so expect another record
				parseState = startOfRecord;
				output.println(F("End of Record."));
			}
			else if (c == '')
			{
				//Got  so end of array. We are done
				output.println(F("End of Record."));
				output.println(F("End of Array.\r\n"));
				parseState = done;
			}
			else
			{
				ErrNo = 8;
				result = false;
			}
			break;
		default:
		{
			ErrNo = 9;
			result = false;
		}
	}
	if ((gotANameValuePair) && (result))
	{
		if (RecordNo == 1)
			numNameValuePairsPerRecord = NameValueIndex;
		AddNameValue(CurrentNameValue, RecordNo, NameValueIndex - 1);
	}
	else if (!result)
	{
		// If any errors then signal halt to state machine.
		parseState = error;
		output.print(F("An error has occured. ErrNo:"));
		output.println(ErrNo);
		output.println(CurrentNameValue.StringValue);
		output.print(F("StringValue:"));
		CurrentNameValue.StringValue[8] = '\0';
		output.println(CurrentNameValue.StringValue);*/
		delay(2000);
		if (ErrNo == 11)
		{
			output.println(F("Couldn't parse all name-value pairs"));
		}
	}
	return result;
}