/** We here treat the property values as expressions: padding: {expression} {expression} {expression}; margin: {expression}; */ func (parser *Parser) ParseExpr(inParenthesis bool) ast.Expr { var pos = parser.Pos // plus or minus. This creates an unary expression that holds the later term. // this is for: +3 or -4 var expr ast.Expr = nil if tok := parser.acceptAnyOf2(ast.T_PLUS, ast.T_MINUS); tok != nil { if term := parser.ParseTerm(); term != nil { expr = ast.NewUnaryExpr(ast.NewOpWithToken(tok), term) if uexpr, ok := expr.(*ast.UnaryExpr); ok { // if it's evaluatable just return the evaluated value. if val, ok := runtime.ReduceExpr(uexpr, parser.GlobalContext); ok { expr = ast.Expr(val) } } } else { parser.restore(pos) return nil } } else { expr = parser.ParseTerm() } if expr == nil { debug("ParseExpr failed, got %+v, restoring to %d", expr, pos) parser.restore(pos) return nil } var rightTok = parser.peek() for rightTok.Type == ast.T_PLUS || rightTok.Type == ast.T_MINUS || rightTok.Type == ast.T_LITERAL_CONCAT { // accept plus or minus parser.advance() if rightTerm := parser.ParseTerm(); rightTerm != nil { // XXX: check parenthesis var bexpr = ast.NewBinaryExpr(ast.NewOpWithToken(rightTok), expr, rightTerm, inParenthesis) if val, ok := runtime.ReduceExpr(bexpr, parser.GlobalContext); ok { expr = ast.Expr(val) } else { // wrap the existing expression with the new binary expression object expr = ast.Expr(bexpr) } } else { panic(SyntaxError{ Reason: "Expecting term on the right side", ActualToken: parser.peek(), File: parser.File, }) } rightTok = parser.peek() } return expr }
/* The operator precedence is described here @see http://introcs.cs.princeton.edu/java/11precedence/ */ func (parser *Parser) ParseCondition() ast.Expr { debug("ParseCondition") // Boolean 'Not' if tok := parser.accept(ast.T_LOGICAL_NOT); tok != nil { var logicexpr = parser.ParseLogicExpr() return ast.NewUnaryExpr(ast.NewOpWithToken(tok), logicexpr) } return parser.ParseLogicExpr() }
/* ParseMediaType returns Ident Node or UnaryExpr as ast.Expr */ func (parser *Parser) ParseMediaType() *ast.MediaType { if tok := parser.acceptAnyOf2(ast.T_LOGICAL_NOT, ast.T_ONLY); tok != nil { var mediaType = parser.expect(ast.T_IDENT) return ast.NewMediaType(ast.NewUnaryExpr(ast.NewOpWithToken(tok), mediaType)) } var tok = parser.peek() if tok.Type == ast.T_PAREN_OPEN { // the begining of the media expression return nil } var expr = parser.ParseExpr(false) if expr != nil { return ast.NewMediaType(expr) } // parse media type fail return nil }