예제 #1
0
func TestReduceExprForSolveableExpr(t *testing.T) {
	expr := ast.NewBinaryExpr(ast.NewOp(ast.T_PLUS), ast.NewNumber(10, nil, nil), ast.NewNumber(3, nil, nil), false)
	expr2 := ast.NewBinaryExpr(ast.NewOp(ast.T_PLUS), expr, ast.NewNumber(3, nil, nil), false)
	val, ok := ReduceExpr(expr2, nil)
	assert.True(t, ok)
	assert.NotNil(t, val)

	num, ok := val.(*ast.Number)
	assert.True(t, ok)
	assert.NotNil(t, num)
	assert.Equal(t, 16.0, num.Value)
}
예제 #2
0
파일: rules.go 프로젝트: imjerrybao/c6
/**

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
}
예제 #3
0
파일: rules.go 프로젝트: imjerrybao/c6
/*
This method parses media type first, then expecting more that on media
expressions.

media_query: [[only | not]? <media_type> [ and <expression> ]*]
  | <expression> [ and <expression> ]*
expression: ( <media_feature> [: <value>]? )

Specification: http://dev.w3.org/csswg/mediaqueries-3
*/
func (parser *Parser) ParseMediaQuery() *ast.MediaQuery {

	// the leading media type is optional
	var mediaType = parser.ParseMediaType()
	if mediaType != nil {
		// Check if there is an expression after the media type.
		var tok = parser.peek()
		if tok.Type != ast.T_LOGICAL_AND {
			return ast.NewMediaQuery(mediaType, nil)
		}
		parser.advance() // skip the and operator token
	}

	// parse the media expression after the media type.
	var mediaExpr = parser.ParseMediaQueryExpr()
	if mediaExpr == nil {
		if mediaType == nil {
			return nil
		}
		return ast.NewMediaQuery(mediaType, mediaExpr)
	}

	// @media query only allows AND operator here..
	for tok := parser.accept(ast.T_LOGICAL_AND); tok != nil; tok = parser.accept(ast.T_LOGICAL_AND) {
		// parse another mediq query expression
		var expr2 = parser.ParseMediaQueryExpr()
		mediaExpr = ast.NewBinaryExpr(ast.NewOpWithToken(tok), mediaExpr, expr2, false)
	}
	return ast.NewMediaQuery(mediaType, mediaExpr)
}
예제 #4
0
파일: rules.go 프로젝트: imjerrybao/c6
func (parser *Parser) ParseLogicExpr() ast.Expr {
	debug("ParseLogicExpr")
	var expr = parser.ParseLogicANDExpr()
	for tok := parser.accept(ast.T_LOGICAL_OR); tok != nil; tok = parser.accept(ast.T_LOGICAL_OR) {
		if subexpr := parser.ParseLogicANDExpr(); subexpr != nil {
			expr = ast.NewBinaryExpr(ast.NewOpWithToken(tok), expr, subexpr, false)
		}
	}
	return expr
}
예제 #5
0
파일: rules.go 프로젝트: imjerrybao/c6
func (parser *Parser) ParseComparisonExpr() ast.Expr {
	debug("ParseComparisonExpr")

	var expr ast.Expr = nil
	if parser.accept(ast.T_PAREN_OPEN) != nil {
		expr = parser.ParseLogicExpr()
		parser.expect(ast.T_PAREN_CLOSE)
	} else {
		expr = parser.ParseExpr(false)
	}

	var tok = parser.peek()
	for tok != nil && tok.IsComparisonOperator() {
		parser.advance()
		if subexpr := parser.ParseExpr(false); subexpr != nil {
			expr = ast.NewBinaryExpr(ast.NewOpWithToken(tok), expr, subexpr, false)
		}
		tok = parser.peek()
	}
	return expr
}
예제 #6
0
파일: rules.go 프로젝트: imjerrybao/c6
func (parser *Parser) ParseTerm() ast.Expr {
	var pos = parser.Pos
	var factor = parser.ParseFactor()
	if factor == nil {
		parser.restore(pos)
		return nil
	}

	// see if the next token is '*' or '/'
	if tok := parser.acceptAnyOf2(ast.T_MUL, ast.T_DIV); tok != nil {
		if term := parser.ParseTerm(); term != nil {
			return ast.NewBinaryExpr(ast.NewOpWithToken(tok), factor, term, false)
		} else {
			panic(SyntaxError{
				Reason:      "Expecting term after '*' or '/'",
				ActualToken: parser.peek(),
				File:        parser.File,
			})
		}
	}
	return factor
}
예제 #7
0
func TestReduceCSSSlashExpr(t *testing.T) {
	expr := ast.NewBinaryExpr(ast.NewOp(ast.T_DIV), ast.NewNumber(10, ast.NewUnit(ast.T_UNIT_PX, nil), nil), ast.NewNumber(3, ast.NewUnit(ast.T_UNIT_PX, nil), nil), false)
	ok := CanReduceExpr(expr)
	assert.False(t, ok)
}