|
|
|
|
using DOM.DSL.Model;
|
|
|
|
|
using DOM.DSL.Services;
|
|
|
|
|
using DOM.DSL.Tokens;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
|
|
namespace DOM.DSL.Contexts
|
|
|
|
|
{
|
|
|
|
|
internal class TPropertyContext :
|
|
|
|
|
TContext
|
|
|
|
|
{
|
|
|
|
|
private string _name;
|
|
|
|
|
private List<TToken> _indexTokens;
|
|
|
|
|
private TToken _nextToken;
|
|
|
|
|
|
|
|
|
|
public TPropertyContext(TContext parent, string name)
|
|
|
|
|
{
|
|
|
|
|
ParentContext = parent;
|
|
|
|
|
_name = name;
|
|
|
|
|
_indexTokens = new List<TToken>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Read(TStringReader reader)
|
|
|
|
|
{
|
|
|
|
|
if (reader.EOF) return;
|
|
|
|
|
if (reader.Current == TChar.PropertyOrFuncStart)
|
|
|
|
|
{
|
|
|
|
|
if (reader.Move())
|
|
|
|
|
{
|
|
|
|
|
reader.SkipBreaks();
|
|
|
|
|
var name = reader.ReadIdentity();
|
|
|
|
|
if (false == string.IsNullOrWhiteSpace(name))
|
|
|
|
|
{
|
|
|
|
|
reader.Move(name.Length);
|
|
|
|
|
if (reader.Current == TChar.FuncArgsStart)
|
|
|
|
|
{
|
|
|
|
|
// Function '@now.format(dd-mm)'
|
|
|
|
|
reader.Move();
|
|
|
|
|
var context = new TFunctionContext(this, name);
|
|
|
|
|
context.Read(reader);
|
|
|
|
|
_nextToken = context.Complete();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Property '@now.year'
|
|
|
|
|
var context = new TPropertyContext(this, name);
|
|
|
|
|
context.Read(reader);
|
|
|
|
|
_nextToken = context.Complete();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (reader.Current == TChar.PropertyIndexStart)
|
|
|
|
|
{
|
|
|
|
|
var text = new StringBuilder();
|
|
|
|
|
var flushTextToken = new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
if (text.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
_indexTokens.Add(new TTextToken { Text = text.ToString() });
|
|
|
|
|
text.Clear();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
reader.Move();
|
|
|
|
|
while (reader.EOF == false)
|
|
|
|
|
{
|
|
|
|
|
switch (reader.Current)
|
|
|
|
|
{
|
|
|
|
|
#region Ecsaping
|
|
|
|
|
|
|
|
|
|
case TChar.Escape:
|
|
|
|
|
{
|
|
|
|
|
switch (reader.Next)
|
|
|
|
|
{
|
|
|
|
|
case 's':
|
|
|
|
|
text.Append(' ');
|
|
|
|
|
reader.Move(2);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'r':
|
|
|
|
|
text.Append(TChar.CaretReturn);
|
|
|
|
|
reader.Move(2);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'n':
|
|
|
|
|
text.Append(TChar.Newline);
|
|
|
|
|
reader.Move(2);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 't':
|
|
|
|
|
text.Append(TChar.Tab);
|
|
|
|
|
reader.Move(2);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '@':
|
|
|
|
|
case '(':
|
|
|
|
|
case ')':
|
|
|
|
|
case '.':
|
|
|
|
|
case ',':
|
|
|
|
|
case '\\':
|
|
|
|
|
text.Append(reader.Next);
|
|
|
|
|
reader.Move(2);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
text.Append(reader.Current);
|
|
|
|
|
reader.Move();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
#endregion Ecsaping
|
|
|
|
|
|
|
|
|
|
case TChar.PropertyIndexEnd:
|
|
|
|
|
{
|
|
|
|
|
flushTextToken();
|
|
|
|
|
if (reader.Next == TChar.PropertyOrFuncStart)
|
|
|
|
|
{
|
|
|
|
|
reader.Move(2);
|
|
|
|
|
reader.SkipBreaks();
|
|
|
|
|
var name = reader.ReadIdentity();
|
|
|
|
|
reader.Move(name.Length);
|
|
|
|
|
if (reader.Current.Equals(TChar.FuncArgsStart))
|
|
|
|
|
{
|
|
|
|
|
reader.Move();
|
|
|
|
|
var context = new TFunctionContext(this, name);
|
|
|
|
|
context.Read(reader);
|
|
|
|
|
_nextToken = context.Complete();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
text.Append(name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
reader.Move();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case TChar.TokenStart:
|
|
|
|
|
{
|
|
|
|
|
if (reader.Move())
|
|
|
|
|
{
|
|
|
|
|
var name = reader.ReadIdentity();
|
|
|
|
|
if (_elementNames.Contains(name))
|
|
|
|
|
{
|
|
|
|
|
flushTextToken();
|
|
|
|
|
reader.Move(name.Length);
|
|
|
|
|
var elementContext = new TElementContext(this, name);
|
|
|
|
|
elementContext.Read(reader);
|
|
|
|
|
_indexTokens.Add(elementContext.Complete());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
text.Append(TChar.TokenStart);
|
|
|
|
|
text.Append(reader.Current);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
text.Append(reader.Current);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
text.Append(reader.Current);
|
|
|
|
|
reader.Move();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
flushTextToken();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public TToken Complete()
|
|
|
|
|
{
|
|
|
|
|
return new TPropertyToken
|
|
|
|
|
{
|
|
|
|
|
PropertyName = _name,
|
|
|
|
|
PropertyIndex = new TBlockToken(_name, null, _indexTokens.Select(t => t.Clone()).ToArray()),
|
|
|
|
|
NextToken = _nextToken?.Clone()
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|