// this method must be invoked in any subclass immediatly after constructor completion protected void CompleteInitialization() { lock (this) { if (_isReadOnly) { return; } _isReadOnly = true; } if (typeof(ISyntaxExtender).IsAssignableFrom(typeof(TExtender))) { var api = new TExtender().CastTo <ISyntaxExtender>(); api.ExtendSyntax(this); } NonBreakingIdentifierChars = NonBreakingIdentifierChars.CastTo <List <char> >().AsReadOnly(); SyntaxChars = SyntaxChars.CastTo <Dictionary <int, TokenType> >().AsReadOnly(); Constants = Constants.CastTo <Dictionary <string, object> >().AsReadOnly(); Symbols = Symbols.CastTo <Dictionary <string, TokenType> >().AsReadOnly(); Functions = Functions.CastTo <List <FunctionMap> >().AsReadOnly(); KnownTypes = KnownTypes.CastTo <Dictionary <string, TypeParser> >().AsReadOnly(); ImplementsVariables = Symbols.Values.Any(v => v == TokenType.Declaration) || SyntaxChars.Values.Any(v => v == TokenType.Declaration); IdentifierDelimiter = (char)SyntaxChars.Where(kv => kv.Value == TokenType.IdentifierDelimiter).Select(kv => kv.Key).FirstOrDefault(); }
protected ScriptSyntax() : base(false) { LineComment = '#'; NonBreakingIdentifierChars.Add('$'); SyntaxChars.Add(new Dictionary <int, TokenType> { { '-', TokenType.Negate }, { '(', TokenType.LParen }, { ')', TokenType.RParen }, { '[', TokenType.LArrayBracket }, { ']', TokenType.RArrayBracket }, { ',', TokenType.Delimiter }, { ';', TokenType.LogicalAnd }, // statement seperarator { '|', TokenType.BitwiseOr }, { '&', TokenType.BitwiseAnd }, { '^', TokenType.BitwiseXOr }, { '!', TokenType.LogicalNot }, { '<', TokenType.LessThan }, { '>', TokenType.GreaterThan }, { '~', TokenType.BitwiseNot }, { '/', TokenType.Div }, { '*', TokenType.Mul }, { '+', TokenType.Add }, { '.', TokenType.IdentifierDelimiter }, { '=', TokenType.Assignment }, { '@', TokenType.SyntaxEscape } }); Constants.Add(new Dictionary <string, object> { { "PI", Math.PI }, { "E", Math.E }, { "null", null }, { "true", true }, { "false", false }, { "NaN", double.NaN }, { "INF", double.PositiveInfinity } }); Symbols.Add(new Dictionary <string, TokenType> { { "-", TokenType.Sub }, { "==", TokenType.Equal }, { "!=", TokenType.NotEqual }, { "||", TokenType.LogicalOr }, { "&&", TokenType.LogicalAnd }, { ">>", TokenType.RightShift }, { "<<", TokenType.LeftShift }, { "var", TokenType.Declaration } }); Functions.Add(new List <FunctionMap> { new FunctionMap("if", new IffBuilder()), new FunctionMap("else", new ElseBuilder()), new FunctionMap("format", new FormatBuilder()), new FunctionMap("cast", new CastBuilder()), new FunctionMap("contains", MemberTokens.String.Contains), new FunctionMap("startswith", MemberTokens.String.StartsWith), new FunctionMap("endswith", MemberTokens.String.EndsWith), new FunctionMap("concat", MemberTokens.String.Concat), new FunctionMap("indexof", MemberTokens.String.IndexOf), new FunctionMap("length", MemberTokens.String.Length), new FunctionMap("substring", MemberTokens.String.Substring1), new FunctionMap("substring", MemberTokens.String.Substring2), // overload new FunctionMap("toupper", MemberTokens.String.ToUpper), new FunctionMap("tolower", MemberTokens.String.ToLower), new FunctionMap("trim", MemberTokens.String.Trim), new FunctionMap("year", MemberTokens.DateTime.Year), new FunctionMap("year", MemberTokens.DateTimeOffset.Year), new FunctionMap("month", MemberTokens.DateTime.Month), new FunctionMap("month", MemberTokens.DateTimeOffset.Month), new FunctionMap("day", MemberTokens.DateTime.Day), new FunctionMap("day", MemberTokens.DateTimeOffset.Day), new FunctionMap("day", MemberTokens.TimeSpan.Days), new FunctionMap("hour", MemberTokens.DateTime.Hour), new FunctionMap("hour", MemberTokens.DateTimeOffset.Hour), new FunctionMap("hour", MemberTokens.TimeSpan.Hours), new FunctionMap("minute", MemberTokens.DateTime.Minute), new FunctionMap("minute", MemberTokens.DateTimeOffset.Minute), new FunctionMap("minute", MemberTokens.TimeSpan.Minutes), new FunctionMap("second", MemberTokens.DateTime.Second), new FunctionMap("second", MemberTokens.DateTimeOffset.Second), new FunctionMap("second", MemberTokens.TimeSpan.Seconds), new FunctionMap("fractionalseconds", MemberTokens.DateTime.Millisecond), new FunctionMap("fractionalseconds", MemberTokens.DateTimeOffset.Millisecond), new FunctionMap("fractionalseconds", MemberTokens.TimeSpan.Milliseconds), new FunctionMap("totalfractionalseconds", MemberTokens.TimeSpan.TotalMilliseconds), new FunctionMap("totalseconds", MemberTokens.TimeSpan.TotalSeconds), new FunctionMap("totalminutes", MemberTokens.TimeSpan.TotalMinutes), new FunctionMap("totalhours", MemberTokens.TimeSpan.TotalHours), new FunctionMap("totaldays", MemberTokens.TimeSpan.TotalDays), new FunctionMap("date", MemberTokens.DateTimeOffset.Date), new FunctionMap("time", MemberTokens.DateTimeOffset.TimeOfDay), new FunctionMap("time", MemberTokens.DateTime.TimeOfDay), new FunctionMap("now", MemberTokens.DateTimeOffset.Now), new FunctionMap("utcnow", MemberTokens.DateTimeOffset.UtcNow), new FunctionMap("dow", MemberTokens.DateTimeOffset.DayOfWeek), new FunctionMap("dow", MemberTokens.DateTime.DayOfWeek), }); foreach (var m in typeof(TExtender).GetMethods(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(m => Attribute.IsDefined(m, typeof(ScriptMethodAttribute)))) { Functions.Add(new FunctionMap(m.GetCustomAttribute <ScriptMethodAttribute>().Name, m)); } this.AddMathFunctions(); KnownTypes.Add(new Dictionary <string, TypeParser> { { "X", new TypeParser(typeof(byte[]), lex => lex.ParseBinary()) }, { "string", new TypeParser(typeof(string), lex => lex) }, { "bool", new TypeParser(typeof(bool), lex => bool.Parse(lex)) }, { "byte", new TypeParser(typeof(byte), lex => byte.Parse(lex)) }, { "dt", new TypeParser(typeof(DateTime), lex => XmlConvert.ToDateTime(lex, XmlDateTimeSerializationMode.Local)) }, { "datetime", new TypeParser(typeof(DateTime), lex => XmlConvert.ToDateTime(lex, XmlDateTimeSerializationMode.Local)) }, { "decimal", new TypeParser(typeof(decimal), lex => decimal.Parse(lex)) }, { "double", new TypeParser(typeof(double), lex => double.Parse(lex)) }, { "float", new TypeParser(typeof(float), lex => float.Parse(lex)) }, { "guid", new TypeParser(typeof(Guid), lex => Guid.Parse(lex)) }, { "int16", new TypeParser(typeof(Int16), lex => Int16.Parse(lex)) }, { "int32", new TypeParser(typeof(Int32), lex => int.Parse(lex)) }, { "int64", new TypeParser(typeof(Int64), lex => long.Parse(lex)) }, { "sbyte", new TypeParser(typeof(sbyte), lex => sbyte.Parse(lex)) }, { "ts", new TypeParser(typeof(TimeSpan), lex => XmlConvert.ToTimeSpan(lex)) }, { "timespan", new TypeParser(typeof(TimeSpan), lex => XmlConvert.ToTimeSpan(lex)) }, { "dto", new TypeParser(typeof(DateTimeOffset), lex => XmlConvert.ToDateTimeOffset(lex)) }, { "datetimeoffset", new TypeParser(typeof(DateTimeOffset), lex => XmlConvert.ToDateTimeOffset(lex)) } }); CompleteInitialization(); }
protected ODataSyntax() : base(true) { NonBreakingIdentifierChars.Add('.'); SyntaxChars.Add(new Dictionary <int, TokenType> { { '-', TokenType.Negate }, { '(', TokenType.LParen }, { ')', TokenType.RParen }, { ',', TokenType.Delimiter }, { '/', TokenType.IdentifierDelimiter } }); Symbols.Add(new Dictionary <string, TokenType> { { "and", TokenType.LogicalAnd }, { "or", TokenType.LogicalOr }, { "not", TokenType.LogicalNot }, { "mod", TokenType.Mod }, { "div", TokenType.Div }, { "add", TokenType.Add }, { "mul", TokenType.Mul }, { "sub", TokenType.Sub }, { "has", TokenType.Has }, { "eq", TokenType.Equal }, { "ne", TokenType.NotEqual }, { "lt", TokenType.LessThan }, { "gt", TokenType.GreaterThan }, { "le", TokenType.LessThanOrEqual }, { "ge", TokenType.GreaterThanOrEqual } }); Functions.Add(new List <FunctionMap> { new FunctionMap("cast", new CastBuilder()), new FunctionMap("isof", new IsofBuilder()), new FunctionMap("contains", MemberTokens.String.Contains), new FunctionMap("startswith", MemberTokens.String.StartsWith), new FunctionMap("endswith", MemberTokens.String.EndsWith), new FunctionMap("concat", MemberTokens.String.Concat), new FunctionMap("indexof", MemberTokens.String.IndexOf), new FunctionMap("length", MemberTokens.String.Length), new FunctionMap("substring", MemberTokens.String.Substring1), new FunctionMap("substring", MemberTokens.String.Substring2), // overload new FunctionMap("toupper", MemberTokens.String.ToUpper), new FunctionMap("tolower", MemberTokens.String.ToLower), new FunctionMap("trim", MemberTokens.String.Trim), new FunctionMap("floor", MemberTokens.Math.FloorDecimal), new FunctionMap("floor", MemberTokens.Math.FloorDouble), new FunctionMap("round", MemberTokens.Math.RoundDecimalZeroDigits), new FunctionMap("round", MemberTokens.Math.RoundDoubleZeroDigits), new FunctionMap("ceiling", MemberTokens.Math.CeilingDecimal), new FunctionMap("ceiling", MemberTokens.Math.CeilingDouble), new FunctionMap("year", MemberTokens.DateTime.Year), new FunctionMap("year", MemberTokens.DateTimeOffset.Year), new FunctionMap("month", MemberTokens.DateTime.Month), new FunctionMap("month", MemberTokens.DateTimeOffset.Month), new FunctionMap("day", MemberTokens.DateTime.Day), new FunctionMap("day", MemberTokens.DateTimeOffset.Day), new FunctionMap("day", MemberTokens.TimeSpan.Days), new FunctionMap("hour", MemberTokens.DateTime.Hour), new FunctionMap("hour", MemberTokens.DateTimeOffset.Hour), new FunctionMap("hour", MemberTokens.TimeSpan.Hours), new FunctionMap("minute", MemberTokens.DateTime.Minute), new FunctionMap("minute", MemberTokens.DateTimeOffset.Minute), new FunctionMap("minute", MemberTokens.TimeSpan.Minutes), new FunctionMap("second", MemberTokens.DateTime.Second), new FunctionMap("second", MemberTokens.DateTimeOffset.Second), new FunctionMap("second", MemberTokens.TimeSpan.Seconds), new FunctionMap("fractionalseconds", MemberTokens.DateTime.Millisecond), new FunctionMap("fractionalseconds", MemberTokens.DateTimeOffset.Millisecond), new FunctionMap("fractionalseconds", MemberTokens.TimeSpan.Milliseconds), new FunctionMap("totalfractionalseconds", MemberTokens.TimeSpan.TotalMilliseconds), new FunctionMap("totalseconds", MemberTokens.TimeSpan.TotalSeconds), new FunctionMap("totalminutes", MemberTokens.TimeSpan.TotalMinutes), new FunctionMap("totalhours", MemberTokens.TimeSpan.TotalHours), new FunctionMap("totaldays", MemberTokens.TimeSpan.TotalDays), new FunctionMap("totaloffsetminutes", new TotalOffsetMinutesBuilder()), new FunctionMap("date", MemberTokens.DateTimeOffset.Date), new FunctionMap("time", MemberTokens.DateTimeOffset.TimeOfDay), new FunctionMap("time", MemberTokens.DateTime.TimeOfDay), new FunctionMap("now", MemberTokens.DateTimeOffset.Now), new FunctionMap("utcnow", MemberTokens.DateTimeOffset.UtcNow), // not OData specified new FunctionMap("mindatetime", MemberTokens.DateTimeOffset.MinValue), new FunctionMap("maxdatetime", MemberTokens.DateTimeOffset.MaxValue), new FunctionMap("dow", MemberTokens.DateTimeOffset.DayOfWeek), // not OData specified new FunctionMap("dow", MemberTokens.DateTime.DayOfWeek), }); this.TryAddSqlServerSpatialTypes(); Constants.Add(new Dictionary <string, object> { { "null", null }, { "true", true }, { "false", false }, { "NaN", double.NaN }, { "INF", double.PositiveInfinity } }); KnownTypes.Add(new Dictionary <string, TypeParser> { { "X", new TypeParser(typeof(byte[]), lex => lex.ParseBinary()) }, { "binary", new TypeParser(typeof(byte[]), lex => lex.ParseBinary()) }, { "string", new TypeParser(typeof(string), lex => lex) }, { "boolean", new TypeParser(typeof(bool), lex => bool.Parse(lex)) }, { "byte", new TypeParser(typeof(byte), lex => byte.Parse(lex)) }, { "datetime", new TypeParser(typeof(DateTime), lex => XmlConvert.ToDateTime(lex, XmlDateTimeSerializationMode.Local)) }, { "decimal", new TypeParser(typeof(decimal), lex => decimal.Parse(lex)) }, { "double", new TypeParser(typeof(double), lex => double.Parse(lex)) }, { "single", new TypeParser(typeof(float), lex => float.Parse(lex)) }, { "float", new TypeParser(typeof(float), lex => float.Parse(lex)) }, { "guid", new TypeParser(typeof(Guid), lex => Guid.Parse(lex)) }, { "int16", new TypeParser(typeof(Int16), lex => Int16.Parse(lex)) }, { "int32", new TypeParser(typeof(Int32), lex => int.Parse(lex)) }, { "int64", new TypeParser(typeof(Int64), lex => long.Parse(lex)) }, { "sbyte", new TypeParser(typeof(sbyte), lex => sbyte.Parse(lex)) }, { "time", new TypeParser(typeof(TimeSpan), lex => XmlConvert.ToTimeSpan(lex)) }, { "duration", new TypeParser(typeof(TimeSpan), lex => XmlConvert.ToTimeSpan(lex)) }, { "datetimeoffset", new TypeParser(typeof(DateTimeOffset), lex => XmlConvert.ToDateTimeOffset(lex)) }, { "Edm.Binary", new TypeParser(typeof(byte[]), lex => lex.ParseBinary()) }, { "Edm.String", new TypeParser(typeof(string), lex => lex) }, { "Edm.Boolean", new TypeParser(typeof(bool), lex => bool.Parse(lex)) }, { "Edm.Byte", new TypeParser(typeof(byte), lex => byte.Parse(lex)) }, { "Edm.DateTime", new TypeParser(typeof(DateTime), lex => XmlConvert.ToDateTime(lex, XmlDateTimeSerializationMode.Local)) }, { "Edm.Decimal", new TypeParser(typeof(decimal), lex => decimal.Parse(lex)) }, { "Edm.Double", new TypeParser(typeof(double), lex => double.Parse(lex)) }, { "Edm.Single", new TypeParser(typeof(float), lex => float.Parse(lex)) }, { "Edm.Float", new TypeParser(typeof(float), lex => float.Parse(lex)) }, { "Edm.Guid", new TypeParser(typeof(Guid), lex => Guid.Parse(lex)) }, { "Edm.Int16", new TypeParser(typeof(Int16), lex => Int16.Parse(lex)) }, { "Edm.Int32", new TypeParser(typeof(Int32), lex => int.Parse(lex)) }, { "Edm.Int64", new TypeParser(typeof(Int64), lex => long.Parse(lex)) }, { "Edm.SBbyte", new TypeParser(typeof(sbyte), lex => sbyte.Parse(lex)) }, { "Edm.Time", new TypeParser(typeof(TimeSpan), lex => XmlConvert.ToTimeSpan(lex)) }, { "Edm.Duration", new TypeParser(typeof(TimeSpan), lex => XmlConvert.ToTimeSpan(lex)) }, { "Edm.DateTimeOffset", new TypeParser(typeof(DateTimeOffset), lex => XmlConvert.ToDateTimeOffset(lex)) } }); CompleteInitialization(); }