// 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 } }
// 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 }
// program : statement* func (p *parser) parseProgram() *ast.Program { result := ast.NewProgram(p.next().Pos, p.next().Line) for p.isStatement() { result.AddStatement(p.parseStatement()) } return result }
// 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 }