示例#1
0
// inverseChain : openInverseChain program inverseChain?
//              | inverseAndProgram
func (p *parser) parseInverseChain() *ast.Program {
	if p.isInverse() {
		// inverseAndProgram
		return p.parseInverseAndProgram()
	} else {
		result := ast.NewProgram(p.lex.Pos(), p.lex.Line())

		// openInverseChain
		block, blockParams := p.parseOpenBlock()

		// program
		program := p.parseProgram()

		program.BlockParams = blockParams
		block.Program = program

		// inverseChain?
		if p.isInverseChain() {
			block.Inverse = p.parseInverseChain()
		}

		setBlockInverseStrip(block)

		result.Chained = true
		result.AddStatement(block)

		return result
	}
}
示例#2
0
// program : statement*
func (p *parser) parseProgram() *ast.Program {
	result := ast.NewProgram(p.lex.Pos(), p.lex.Line())

	for p.isStatement() {
		result.AddStatement(p.parseStatement())
	}

	return result
}
示例#3
0
// rawBlock : openRawBlock content endRawBlock
// openRawBlock : OPEN_RAW_BLOCK helperName param* hash? CLOSE_RAW_BLOCK
// endRawBlock : OPEN_END_RAW_BLOCK helperName CLOSE_RAW_BLOCK
func (p *parser) parseRawBlock() *ast.BlockStatement {
	// OPEN_RAW_BLOCK
	tok := p.shift()

	result := ast.NewBlockStatement(tok.Pos, tok.Line)

	// helperName param* hash?
	result.Expression = p.parseExpression(tok)

	openName := result.Expression.Canonical()

	// CLOSE_RAW_BLOCK
	tok = p.shift()
	if tok.Kind != lexer.TokenCloseRawBlock {
		errExpected(lexer.TokenCloseRawBlock, tok)
	}

	// content
	// @todo Is content mandatory in a raw block ?
	content := p.parseContent()

	program := ast.NewProgram(tok.Pos, tok.Line)
	program.AddStatement(content)

	result.Program = program

	// OPEN_END_RAW_BLOCK
	tok = p.shift()
	if tok.Kind != lexer.TokenOpenEndRawBlock {
		// should never happen as it is caught by lexer
		errExpected(lexer.TokenOpenEndRawBlock, tok)
	}

	// helperName
	endId := p.parseHelperName()

	closeName, ok := ast.HelperNameStr(endId)
	if !ok {
		errNode(endId, "Erroneous closing expression")
	}

	if openName != closeName {
		errNode(endId, fmt.Sprintf("%s doesn't match %s", openName, closeName))
	}

	// CLOSE_RAW_BLOCK
	tok = p.shift()
	if tok.Kind != lexer.TokenCloseRawBlock {
		errExpected(lexer.TokenCloseRawBlock, tok)
	}

	return result
}