using System;
using System.Collections.Generic;
using LLama.Exceptions;
using LLama.Native;
namespace LLama.Grammars
{
///
/// A single rule in a
///
public sealed record GrammarRule
{
///
/// Name of this rule
///
public string Name { get; }
///
/// The elements of this grammar rule
///
public IReadOnlyList Elements { get; }
///
/// Create a new GrammarRule containing the given elements
///
///
///
///
public GrammarRule(string name, IReadOnlyList elements)
{
Validate(elements, name);
Name = name;
Elements = elements;
}
private static void Validate(IReadOnlyList elements, string name)
{
if (elements.Count == 0)
throw new ArgumentException("Cannot create a GrammarRule with zero elements", nameof(elements));
if (elements[elements.Count - 1].Type != LLamaGrammarElementType.END)
throw new ArgumentException("Last grammar element must be END", nameof(elements));
for (var i = 0; i < elements.Count; i++)
{
switch (elements[i].Type)
{
case LLamaGrammarElementType.END:
if (i != elements.Count - 1)
throw new GrammarUnexpectedEndElement(name, i);
continue;
case LLamaGrammarElementType.CHAR_RNG_UPPER:
if (i == 0 || !elements[i - 1].IsCharElement())
throw new GrammarUnexpectedCharRngElement(name, i);
break;
case LLamaGrammarElementType.CHAR_ALT:
if (i == 0 || !elements[i - 1].IsCharElement())
throw new GrammarUnexpectedCharAltElement(name, i);
break;
case LLamaGrammarElementType.ALT:
case LLamaGrammarElementType.RULE_REF:
case LLamaGrammarElementType.CHAR:
case LLamaGrammarElementType.CHAR_NOT:
break;
default:
throw new ArgumentException($"Unknown grammar element type: '{elements[i].Type}'", nameof(elements));
}
}
}
}
}