Good day I have simple grammar which describe columns for select. User can specify simple column name, column name and subcolumns for them (and so on), or use '*' to select all fields.
Some example:
exp = "(Id)" - select only Id column
exp = "(Id, Name)" - select Id and Name columns
exp = "(Id, Type(Id, Name)" - select Id, Type.Id, Type.Name columns
exp = "(Id, Type(*))" - select Id and all columns in Type
so, i define token enum:
enum FieldExpressionToken
{
Undefined,
[Token(Example = "(")]
LBracket,
[Token(Example = ")")]
RBracket,
[Token(Example = ",")]
Comma,
[Token(Example = ":")]
Colon,
[Token(Example = "*")]
Star,
Identifier
}
and tokenizer for them:
static class FieldExpressionTokenizer
{
private static TextParser<TextSpan> FieldNameToken { get; } =
Span.Regex(@"@?[a-zA-Z_]\w*(\.@?[a-zA-Z_]\w*)*");
public static Tokenizer<FieldExpressionToken> Instance { get; } =
new TokenizerBuilder<FieldExpressionToken>()
.Match(Character.EqualTo('*'), FieldExpressionToken.Star)
.Match(Character.EqualTo('('), FieldExpressionToken.LBracket)
.Match(Character.EqualTo(')'), FieldExpressionToken.RBracket)
.Match(Character.EqualTo(','), FieldExpressionToken.Comma)
.Match(Character.EqualTo(':'), FieldExpressionToken.Colon)
.Match(FieldNameToken, FieldExpressionToken.Identifier)
.Build();
}
now i try to create parser. Parser for single field:
private static readonly TokenListParser<FieldExpressionToken, Field> Field =
from identifier in Token
.EqualTo(FieldExpressionToken.Identifier)
.Or(Token.EqualTo(FieldExpressionToken.Star))
.Named("column name")
select new Field(identifier.ToStringValue());
Parser for composite field:
private static readonly TokenListParser<FieldExpressionToken, Field> ComplexField =
from identifier in Token
.EqualTo(FieldExpressionToken.Identifier)
.Or(Token.EqualTo(FieldExpressionToken.Star))
.Named("column name")
.Try()
.Then(x => Token
.EqualTo(FieldExpressionToken.Colon)
.IgnoreThen(Parse.Ref(() => FieldList))
.Named("child fields")
.Select(value => new Field(x.ToStringValue(), new[] {value})))
select identifier;
Parser for list:
private static readonly TokenListParser<FieldExpressionToken, Field> FieldList =
from begin in Token.EqualTo(FieldExpressionToken.LBracket)
from fields in Parse
.Ref(() => FieldExpression)
.Named("fields")
.ManyDelimitedBy(
Token.EqualTo(FieldExpressionToken.Comma),
end: Token.EqualTo(FieldExpressionToken.RBracket))
select new Field("", fields.Select(x => new Field(x.ToString())));
and total expression parser:
private static TokenListParser<FieldExpressionToken, Field> FieldExpression { get; } =
Field
.Or(ComplexField)
.Or(FieldList);
i can parse simple expression like (Name)
or (Id,Name)
, but on expression (Name:(Id))
i get error Syntax error (line 1, column 6): unexpected
:, expected
).
can anybody help me to correct my parser?