/// <summary> /// Высокий приоритет /// </summary> /// <returns>результат выражения</returns> protected ExprResult Term() { ExprResult result = Factor(); while (true) { switch (e.Current.Token) { case DelphiTokens.Multiply: case DelphiTokens.Division: case DelphiTokens.Div: case DelphiTokens.Mod: case DelphiTokens.And: case DelphiTokens.Shl: case DelphiTokens.Shr: result.WasOperand = true; e.Next(); result.Add(Factor()); break; default: return(result); } } }
private ExprResult Assignment() { /* * assignment → IDENTIFIER "=" assignment * | logic_or ; */ //https://craftinginterpreters.com/statements-and-state.html#assignment return (from expr in LogicOr() //if left is a valid expression from expr2 in LookAhead(expr) //look to see if it's an assignment select expr2); //if not, return expr we gave to the lookahead ExprResult LookAhead(Expr expr) { if (Match(TokenType.Equal)) { var eq = PreviousToken(); return (from value in Assignment() //recurse to snag the right hand expr from assignment in VariableAssignment(expr, value, eq) select assignment); } return(ExprResult.Ok(expr)); //not a variable assignment, give the plain expr back } ExprResult VariableAssignment(Expr expr, Expr value, Token equals) => (expr is VariableExpr variable) ? ExprResult.Ok(new AssignExpr(variable.name, value)) : ExprResult.Err(new ParseError(equals, "Invalid assignment target.")); }
/// <summary> /// Низший приоритет /// </summary> /// <returns>результат выражения</returns> protected ExprResult Expression() { ExprResult result = SimpleExpression(); while (true) { switch (e.Current.Token) { case DelphiTokens.Equal: case DelphiTokens.Less: case DelphiTokens.Greater: case DelphiTokens.LessOrEqual: case DelphiTokens.GreaterOrEqual: case DelphiTokens.NotEqual: case DelphiTokens.In: case DelphiTokens.Is: case DelphiTokens.As: result.WasOperand = true; e.Next(); result.Add(SimpleExpression()); break; default: return(result); } } }
/// <summary> /// Наивысший приоритет /// </summary> /// <returns>результат выражения</returns> protected ExprResult Factor() { ExprResult result = new ExprResult(); switch (e.Current.Token) { case DelphiTokens.Not: case DelphiTokens.AtSign: case DelphiTokens.Inherited: e.Next(); result.Add(Factor()); break; case DelphiTokens.String: case DelphiTokens.Char: case DelphiTokens.Addition: case DelphiTokens.Subtraction: case DelphiTokens.Digits: case DelphiTokens.HexConstant: case DelphiTokens.True: case DelphiTokens.False: result.Value = Const(); break; default: Variable(); result.IsConstant = false; break; } return(result); }
private StmtResult VarDeclaration() => /* * varDecl → "var" IDENTIFIER ( "=" expression )? ";" ; */ from name in Consume(TokenType.Identifier, "Expected variable name.") from initializer in Match(TokenType.Equal) ? Expression() : ExprResult.Ok(null) from _ in Consume(TokenType.Semicolon, "Expected ';' after variable declaration.") select new VarStmt(name, initializer) as Stmt;
/// <summary> /// Объединить результаты двух выражений /// </summary> /// <param name="parent"></param> public void Add(ExprResult parent) { this.isConstant &= parent.isConstant; this.wasOperand |= parent.wasOperand; this.wasValue |= parent.wasValue; if (!this.wasValue) { this.value = parent.value; } }
private StmtResult ReturnStatement() { // returnStmt → "return" expression? ";" ; var keyword = PreviousToken(); return (from value in !Check(TokenType.Semicolon) ? Expression() : ExprResult.Ok(null) from token in Consume(TokenType.Semicolon, "Expected ';' after return value.") select new ReturnStmt(keyword, value) as Stmt); }
private ExprResult ParseLogicalExpr(TokenType tokenType, Func <ExprResult> current, Func <ExprResult> next) { // current -> next ( "token" next )* ; ExprResult ParseRight(Expr left) { var @operator = PreviousToken(); return (from right in current() select new LogicalExpr(left, @operator, right) as Expr); } return (from left in next() from right in Match(tokenType) ? ParseRight(left) : ExprResult.Ok(left) select right); }
/// <summary> /// Собственно анализ /// </summary> /// <param name="sender">инициатор события</param> /// <param name="e">список токенов</param> protected override void DoAnalyse(AnalyserParameters e) { e.First(); this.e = e; ExprResult expr = Expression(); if (expr.IsConstant && !expr.WasOperand) { if ((expr.Value.GetType() == typeof(Int32)) && !(settings as AnalyserSettings.CaseConditionSettings).StdNumbers.Contains(Convert.ToInt32(expr.Value))) { AddError(e, 0); } else if ((settings as AnalyserSettings.CaseConditionSettings).LocateStd) { AddError((settings as AnalyserSettings.CaseConditionSettings).Message, (settings as AnalyserSettings.CaseConditionSettings).StdLevel, e.File, e[0].Line, e[0].MetaTags); } } }
private IEnumerable <ExprResult> Arguments() { //arguments → expression ( "," expression )* ; if (!Check(TokenType.RightParen)) { var counter = 0; do { // maximum args; for compat with bytecode version if (counter >= 255) { yield return(ExprResult.Err(new ParseError(Peek(), "Can't have more than 255 arguments."))); yield break; } counter++; yield return(Expression()); } while (Match(TokenType.Comma)); } }
private ExprResult ParseBinaryOperation(Func <ExprResult> next, params TokenType[] tokenTypes) { /* * current -> next ( ( tokenA | tokenB | etc. ) next )* ; */ return (next() .Bind(expr => { var result = ExprResult.Ok(expr); while (Match(tokenTypes)) { var @operator = PreviousToken(); result = next() .Bind(right => ExprResult.Ok(new BinaryExpr(expr, @operator, right)) ); } return result; })); }
/// <summary> /// Низкий приоритет /// </summary> /// <returns>результат выражения</returns> protected ExprResult SimpleExpression() { ExprResult result = Term(); while (true) { switch (e.Current.Token) { case DelphiTokens.Addition: case DelphiTokens.Subtraction: case DelphiTokens.Or: case DelphiTokens.Xor: result.WasOperand = true; e.Next(); result.Add(Term()); break; default: return(result); } } }
private ExprResult Primary() { /* * primary → NUMBER | STRING | "true" | "false" | "nil" * | "(" expression ")" * | IDENTIFIER ; */ if (Match(TokenType.False)) { return(ExprResult.Ok(new LiteralExpr(false))); } if (Match(TokenType.True)) { return(ExprResult.Ok(new LiteralExpr(true))); } if (Match(TokenType.Nil)) { return(ExprResult.Ok(new LiteralExpr(null))); } if (Match(TokenType.Number, TokenType.String)) { return(ExprResult.Ok(new LiteralExpr(PreviousToken().Literal))); } if (Match(TokenType.Identifier)) { return(ExprResult.Ok(new VariableExpr(PreviousToken()))); } if (Match(TokenType.LeftParen)) { return (from expr in Expression() from token in Consume(TokenType.RightParen, "Expected ')' after expression.") select new GroupingExpr(expr) as Expr); } return(ExprResult.Err(new ParseError(Peek(), "Expected expression."))); }
private ExprResult Call() => // call → primary ( "(" arguments? ")" )* ; from expr in Primary() from call in Match(TokenType.LeftParen) ? FinishCall(expr) : ExprResult.Ok(expr) select call;
private StmtResult ForStatement() { /* * forStmt → "for" "(" ( varDecl | exprStmt | ";" ) * expression? ";" * expression? ")" statement ; */ StmtResult ForInitializer() { if (Match(TokenType.Semicolon)) { return(StmtResult.Ok(null)); } if (Match(TokenType.Var)) { return(VarDeclaration()); } return(ExpressionStatement()); } ExprResult ForCondition() { if (Check(TokenType.Semicolon)) { return(ExprResult.Ok(null)); } return(Expression()); } ExprResult ForIncrementer() { if (Check(TokenType.RightParen)) { return(ExprResult.Ok(null)); } return(Expression()); } Stmt BuildForAst(Stmt initializer, Expr condition, Expr incrementer, Stmt statement) { // express `for(var i = 0; i < 10; i++) { statement }` as a while loop; // var i = 0; // while(i<10) { // { statement; } // i++; // } var body = incrementer is null ? statement : new BlockStmt(new List <Stmt>() { statement, new ExpressionStmt(incrementer) }); var cond = condition ?? new LiteralExpr(true); var loop = new WhileStmt(cond, body); var block = initializer is null ? loop : new BlockStmt(new List <Stmt>() { initializer, loop }) as Stmt; return(block); } return (from lParen in Consume(TokenType.LeftParen, "Expected '(' after 'for'.") from initializer in ForInitializer() //first semi is parsed as part of initializer from condition in ForCondition() from semi2 in Consume(TokenType.Semicolon, "Expected ';' after condition.") from incrementer in ForIncrementer() from rParen in Consume(TokenType.RightParen, "Expected ')' after increment expression.") from statement in Statement() select BuildForAst(initializer, condition, incrementer, statement)); }
internal static AutoCrudMetadata Create(Type dtoType) { if (cache.TryGetValue(dtoType, out var to)) { return(to); } to = new AutoCrudMetadata { DtoType = dtoType, ModelType = GetModelType(dtoType), DtoProps = TypeProperties.Get(dtoType), }; if (to.ModelType != null) { to.ModelDef = to.ModelType.GetModelMetadata(); } to.RowVersionGetter = to.DtoProps.GetPublicGetter(Keywords.RowVersion); var dtoAttrs = dtoType.AllAttributes(); foreach (var dtoAttr in dtoAttrs) { if (dtoAttr is AutoPopulateAttribute populateAttr) { to.PopulateAttrs ??= new List <AutoPopulateAttribute>(); to.PopulateAttrs.Add(populateAttr); } else if (dtoAttr is AutoFilterAttribute filterAttr) { to.AutoFilters ??= new List <AutoFilterAttribute>(); to.AutoFiltersDbFields ??= new List <QueryDbFieldAttribute>(); to.AutoFilters.Add(filterAttr); to.AutoFiltersDbFields.Add(ExprResult.ToDbFieldAttribute(filterAttr)); } } foreach (var pi in to.DtoProps.PublicPropertyInfos) { var allAttrs = pi.AllAttributes(); var propName = pi.Name; if (allAttrs.FirstOrDefault(x => x is AutoMapAttribute) is AutoMapAttribute mapAttr) { to.MapAttrs ??= new Dictionary <string, AutoMapAttribute>(); to.MapAttrs[propName] = mapAttr; propName = mapAttr.To; } if (allAttrs.FirstOrDefault(x => x is AutoUpdateAttribute) is AutoUpdateAttribute updateAttr) { to.UpdateAttrs ??= new Dictionary <string, AutoUpdateAttribute>(); to.UpdateAttrs[propName] = updateAttr; } if (allAttrs.FirstOrDefault(x => x is AutoDefaultAttribute) is AutoDefaultAttribute defaultAttr) { to.DefaultAttrs ??= new Dictionary <string, AutoDefaultAttribute>(); to.DefaultAttrs[propName] = defaultAttr; } if (pi.PropertyType.IsNullableType()) { to.NullableProps ??= new HashSet <string>(); to.NullableProps.Add(propName); } } return(cache[dtoType] = to); }
internal bool GetAutoFilterExpressions(IDbConnection db, object dto, Dictionary <string, object> dtoValues, IRequest req, out string expr, out List <object> exprParams) { var meta = AutoCrudMetadata.Create(dto.GetType()); if (meta.AutoFilters != null) { var dialectProvider = db.GetDialectProvider(); var sb = StringBuilderCache.Allocate(); var exprParamsList = new List <object>(); //Update's require PK's, Delete's don't need to if (dtoValues.TryRemove(meta.ModelDef.PrimaryKey.Name, out var idValue)) { var idColumn = dialectProvider.GetQuotedColumnName(meta.ModelDef, meta.ModelDef.PrimaryKey); sb.Append(idColumn + " = {0}"); exprParamsList.Add(idValue); } var appHost = HostContext.AppHost; for (var i = 0; i < meta.AutoFilters.Count; i++) { var filter = meta.AutoFilters[i]; var dbAttr = meta.AutoFiltersDbFields[i]; var fieldDef = meta.ModelDef.GetFieldDefinition(filter.Field); if (fieldDef == null) { throw new NotSupportedException($"{dto.GetType().Name} '{filter.Field}' AutoFilter was not found on '{meta.ModelType.Name}'"); } var quotedColumn = dialectProvider.GetQuotedColumnName(meta.ModelDef, fieldDef); var value = appHost.EvalScriptValue(filter, req); var ret = ExprResult.CreateExpression("AND", quotedColumn, value, dbAttr); if (ret != null) { if (sb.Length > 0) { sb.Append(" AND "); } var exprResult = ret.Value; if (exprResult.Format.IndexOf("{1}", StringComparison.Ordinal) >= 0) { throw new NotSupportedException($"SQL Template '{exprResult.Format}' with multiple arguments is not supported"); } if (exprResult.Values != null) { for (var index = 0; index < exprResult.Values.Length; index++) { sb.Append(exprResult.Format.Replace("{" + index + "}", "{" + exprParamsList.Count + "}")); exprParamsList.Add(exprResult.Values[index]); } } } expr = StringBuilderCache.ReturnAndFree(sb); exprParams = exprParamsList; return(true); } } expr = null; exprParams = null; return(false); }