Lumenarium/assembly_parser.cpp

203 lines
7.0 KiB
C++
Raw Normal View History

2019-07-19 20:56:21 +00:00
internal assembly_token
ParseToken (tokenizer* Tokenizer)
{
assembly_token Result = {};
Result.Token = Tokenizer->At;
Result.Length = 1;
Tokenizer->At++;
if (*Result.Token == ':'){ Result.Type = AssemblyToken_Colon; }
else if (*Result.Token == ';'){ Result.Type = AssemblyToken_SemiColon; }
else if (*Result.Token =='{'){ Result.Type = AssemblyToken_LeftCurlyBrace; }
else if (*Result.Token =='}'){ Result.Type = AssemblyToken_RightCurlyBrace; }
else if (*Result.Token ==','){ Result.Type = AssemblyToken_Comma; }
else if (IsNumericExtended(*Result.Token))
{
while(*Tokenizer->At && IsNumericExtended(*Tokenizer->At)) { Tokenizer->At++; }
Result.Type = AssemblyToken_Number;
Result.Length = Tokenizer->At - Result.Token;
}
else if (*Result.Token =='\"')
{
while(*Tokenizer->At && *Tokenizer->At != '\"') { Tokenizer->At++; }
Result.Token++; // Skip the quote
Result.Type = AssemblyToken_String;
Result.Length = (Tokenizer->At - Result.Token) - 1;
}
else if (*Result.Token == '(')
{
while(*Tokenizer->At && *Tokenizer->At != ')') { Tokenizer->At++; }
Result.Token++; // Skip the paren
Result.Type = AssemblyToken_Vector;
Result.Length = (Tokenizer->At - Result.Token) - 1;
}
else if (CharArraysEqualUpToLength(Result.Token, LED_STRIP_IDENTIFIER, CharArrayLength(LED_STRIP_IDENTIFIER)))
{
Result.Type = AssemblyToken_LEDStrip;
Result.Length = CharArrayLength(LED_STRIP_IDENTIFIER);
Tokenizer->At += Result.Length - 1;
}
else if (CharArraysEqualUpToLength(Result.Token, END_ASSEMBLY_FILE_IDENTIFIER, CharArrayLength(END_ASSEMBLY_FILE_IDENTIFIER)))
{
Result.Type = AssemblyToken_EndOfFile;
Result.Length = CharArrayLength(END_ASSEMBLY_FILE_IDENTIFIER);
Tokenizer->At += Result.Length - 1;
}
else
{
Result.Type = AssemblyToken_Identifier;
while(*Tokenizer->At && !IsWhitespace(*Tokenizer->At)) { Tokenizer->At++; }
}
return Result;
}
internal v3
ParseAssemblyVector (char* String)
{
v3 Result = {};
tokenizer Tokenizer = {};
Tokenizer.At = String;
EatWhitespace(&Tokenizer);
2019-07-29 00:24:10 +00:00
Result.x = ParseFloatUnsafe(Tokenizer.At).FloatValue;
2019-07-19 20:56:21 +00:00
EatPastCharacter(&Tokenizer, ',');
EatWhitespace(&Tokenizer);
2019-07-29 00:24:10 +00:00
Result.y = ParseFloatUnsafe(Tokenizer.At).FloatValue;
2019-07-19 20:56:21 +00:00
EatPastCharacter(&Tokenizer, ',');
EatWhitespace(&Tokenizer);
2019-07-29 00:24:10 +00:00
Result.z = ParseFloatUnsafe(Tokenizer.At).FloatValue;
2019-07-19 20:56:21 +00:00
EatPastCharacter(&Tokenizer, ',');
return Result;
}
internal void
ParseAssemblyFileHeader (assembly_definition* Assembly, tokenizer* Tokenizer)
2019-07-19 20:56:21 +00:00
{
if (CharArraysEqualUpToLength(Tokenizer->At, LED_STRIP_COUNT_IDENTIFIER, CharArrayLength(LED_STRIP_COUNT_IDENTIFIER)))
{
Tokenizer->At += CharArrayLength(LED_STRIP_COUNT_IDENTIFIER);
EatWhitespace(Tokenizer);
assembly_token CountToken = ParseToken(Tokenizer);
if (CountToken.Type == AssemblyToken_Number)
{
Assembly->LEDStripSize = ParseSignedIntUnsafe(CountToken.Token).SignedIntValue;
2019-07-19 20:56:21 +00:00
}
else
{
InvalidCodePath;
}
EatWhitespace(Tokenizer);
}
else
{
// TODO(Peter): Handle corrupted files, try to recover?
InvalidCodePath;
}
}
internal void
ParseLEDStrip (assembly_definition* Assembly, tokenizer* Tokenizer)
2019-07-19 20:56:21 +00:00
{
led_strip_definition* LEDStripDef = Assembly->LEDStrips + Assembly->LEDStripCount;
Assert(Assembly->LEDStripCount < Assembly->LEDStripSize);
2019-07-19 20:56:21 +00:00
Assembly->LEDStripCount++;
// Control Box Index
while (*Tokenizer->At && !IsNumericExtended(*Tokenizer->At)) { Tokenizer->At++; }
assembly_token BoxIDToken = ParseToken(Tokenizer);
Assert(BoxIDToken.Type == AssemblyToken_Number);
2019-07-29 00:24:10 +00:00
LEDStripDef->ControlBoxID = ParseSignedIntUnsafe(BoxIDToken.Token).SignedIntValue;
2019-07-19 20:56:21 +00:00
// Start Universe
EatPastCharacter(Tokenizer, ',');
EatWhitespace(Tokenizer);
assembly_token StartUniverseToken = ParseToken(Tokenizer);
Assert(BoxIDToken.Type == AssemblyToken_Number);
2019-07-29 00:24:10 +00:00
LEDStripDef->StartUniverse = ParseSignedIntUnsafe(StartUniverseToken.Token).SignedIntValue;
2019-07-19 20:56:21 +00:00
// Start Channel
EatPastCharacter(Tokenizer, ',');
EatWhitespace(Tokenizer);
assembly_token StartChannelToken = ParseToken(Tokenizer);
Assert(BoxIDToken.Type == AssemblyToken_Number);
2019-07-29 00:24:10 +00:00
LEDStripDef->StartChannel = ParseSignedIntUnsafe(StartChannelToken.Token).SignedIntValue;
2019-07-19 20:56:21 +00:00
// Strip Type
// TODO(Peter): This is unused for now, and would be a branch point for parsing
// the rest of the info. Fix this.
EatPastCharacter(Tokenizer, ',');
EatWhitespace(Tokenizer);
if (CharArraysEqualUpToLength(Tokenizer->At, INTERPOLATE_POINTS_IDENTIFIER, CharArrayLength(INTERPOLATE_POINTS_IDENTIFIER)))
{
LEDStripDef->InterpolationType = StripInterpolate_Points;
// Start Position
EatPastCharacter(Tokenizer, ',');
EatWhitespace(Tokenizer);
assembly_token StartPositionToken = ParseToken(Tokenizer);
Assert(StartPositionToken.Type == AssemblyToken_Vector);
LEDStripDef->InterpolatePositionStart = ParseAssemblyVector(StartPositionToken.Token);
// End Position
EatPastCharacter(Tokenizer, ',');
EatWhitespace(Tokenizer);
assembly_token EndPositionToken = ParseToken(Tokenizer);
Assert(EndPositionToken.Type == AssemblyToken_Vector);
LEDStripDef->InterpolatePositionEnd = ParseAssemblyVector(EndPositionToken.Token);
// LEDs Per Strip
EatPastCharacter(Tokenizer, ',');
EatWhitespace(Tokenizer);
assembly_token LEDsPerStripToken = ParseToken(Tokenizer);
Assert(BoxIDToken.Type == AssemblyToken_Number);
2019-07-29 00:24:10 +00:00
LEDStripDef->LEDsPerStrip = ParseSignedIntUnsafe(LEDsPerStripToken.Token).SignedIntValue;
2019-07-19 20:56:21 +00:00
}
EatPastCharacter(Tokenizer, '}');
EatWhitespace(Tokenizer);
}
internal void
ParseAssemblyFileBody (assembly_definition* Assembly, tokenizer* Tokenizer)
2019-07-19 20:56:21 +00:00
{
EatWhitespace(Tokenizer);
2019-07-19 20:56:21 +00:00
while(*Tokenizer->At)
2019-07-19 20:56:21 +00:00
{
EatWhitespace(Tokenizer);
assembly_token Token = ParseToken(Tokenizer);
2019-07-19 20:56:21 +00:00
if (Token.Type != AssemblyToken_EndOfFile)
{
switch (Token.Type)
{
case AssemblyToken_LEDStrip:
{
ParseLEDStrip(Assembly, Tokenizer);
2019-07-19 20:56:21 +00:00
} break;
// TODO(Peter): Other cases? What else would need to be in the assembly body?
InvalidDefaultCase;
2019-07-19 20:56:21 +00:00
}
}
else
{
break;
}
}
// NOTE(Peter): Ensure the validity of the assembly file. We probably don't want an assert here,
// more likely we want to load a valid assembly anyways, and just raise this as an error to the user
// so they can fix it.
Assert(Assembly->LEDStripCount == Assembly->LEDStripSize);
2019-07-19 20:56:21 +00:00
}