mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-07-04 02:01:51 +00:00
Import code from previous AssetBuilder version
This commit is contained in:
85
src/ZoneCodeGenerator/Parsing/Parser.cs
Normal file
85
src/ZoneCodeGenerator/Parsing/Parser.cs
Normal file
@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using ZoneCodeGenerator.Parsing.Testing;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing
|
||||
{
|
||||
class Parser<TState> where TState : IParserState<TState>
|
||||
{
|
||||
// Amount of consecutive tokens that are output after a parser error to show the region where the error happened.
|
||||
private const int ParserErrorTokenPeekCount = 3;
|
||||
|
||||
private readonly ILexer lexer;
|
||||
private readonly TState state;
|
||||
|
||||
public Parser(TState state, ILexer lexer)
|
||||
{
|
||||
this.state = state;
|
||||
this.lexer = lexer;
|
||||
}
|
||||
|
||||
public bool Parse()
|
||||
{
|
||||
while (!lexer.IsEndOfStream)
|
||||
{
|
||||
var testSuccessful = false;
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var test in state.GetTests())
|
||||
{
|
||||
switch (test.PerformTest(state, lexer))
|
||||
{
|
||||
case TokenTestResult.Match:
|
||||
lexer.SkipTokens(test.ConsumedTokenCount);
|
||||
testSuccessful = true;
|
||||
break;
|
||||
case TokenTestResult.NoMatch:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
if (testSuccessful)
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (LoadingException e)
|
||||
{
|
||||
PrintParserError(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!testSuccessful)
|
||||
{
|
||||
PrintParserError(new LoadingException("Could not parse expression"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Peek for the next token here to be able to determine if the stream is at its end or not
|
||||
lexer.PeekToken();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void PrintParserError(LoadingException e)
|
||||
{
|
||||
Console.WriteLine($"Parsing failed in file '{lexer.CurrentFile}' at line {lexer.CurrentLine}:");
|
||||
|
||||
Console.WriteLine(e.Message);
|
||||
|
||||
Console.Write(" ");
|
||||
|
||||
var tokenCountToShow = Math.Max(ParserErrorTokenPeekCount, lexer.CachedTokenCount);
|
||||
for (var i = 0; i < tokenCountToShow; i++)
|
||||
{
|
||||
var token = lexer.PeekToken(i);
|
||||
if (string.IsNullOrEmpty(token))
|
||||
break;
|
||||
Console.Write($"{token} ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user