<commit_before>//
//  ExpressionTests.swift
//  SwiftParsec
//
//  Created by <NAME> on 2015-10-30.
//  Copyright © 2015 <NAME>. All rights reserved.
//

import XCTest
@testable import SwiftParsec

class ExpressionTests: XCTestCase {
    
    func testExpr() {
        
        let power: (Int, Int) -> Int = { base, exp in
            
            Int(pow(Double(base), Double(exp)))
        
        }
        
        let opTable: OperatorTable<String, (), Int> = [
            
            [
                prefix("-", function: -),
                prefix("+", function: { $0 })
            ],
            [
                postfix("²", function: { $0 * $0 })
            ],
            [
                binary(">>", function: >>, assoc: .None),
                binary("<<", function: <<, assoc: .None)
            ],
            [
                binary("^", function: power, assoc: .Right)
            ],
            [
                binary("*", function: *, assoc: .Left),
                binary("/", function: /, assoc: .Left)
            ],
            [
                binary("+", function: +, assoc: .Left),
                binary("-", function: -, assoc: .Left)
            ]
        
        ]
        
        let openingParen = StringParser.character("(")
        let closingParen = StringParser.character(")")
        let decimal = GenericTokenParser<()>.decimal
        
        let expr = opTable.expressionParser { expr in
            
            expr.between(openingParen, closingParen) <|> decimal
            
        }
        
        let matching = ["1+2*4-8+((3-12)/8)+(-71)+2^2^3", "(+3-3)+5", "3²", "4>>2", "4<<2"]
        
        var expected = [1+2*4-8+((3-12)/8)+(-71)+power(2, power(2, 3))]
        expected.append((+3-3)+5)
        expected.append(3*3)
        expected.append(4>>2)
        expected.append(4<<2)
        
        var index = 0
        
        let errorMessage = "OperatorTable.expressionParser did not succeed."
        
        testStringParserSuccess(expr, inputs: matching) { input, result in
            
            defer { index += 1 }
            XCTAssertEqual(expected[index], result, self.formatErrorMessage(errorMessage, input: input, result: result))
            
        }
        
    }
    
    func binary(name: String, function: (Int, Int) -> Int, assoc: Associativity) -> Operator<String, (), Int> {
        
        let opParser = StringParser.string(name) *> GenericParser(result: function)
        return .Infix(opParser, assoc)
        
    }
    
    func prefix(name: String, function: Int -> Int) -> Operator<String, (), Int> {
        
        let opParser = StringParser.string(name) *> GenericParser(result: function)
        return .Prefix(opParser)
        
    }
    
    func postfix(name: String, function: Int -> Int) -> Operator<String, (), Int> {
        
        let opParser = StringParser.string(name) *> GenericParser(result: function)
        return .Postfix(opParser.attempt)
        
    }
    
}<commit_msg>Improve tests code coverate for expression parser<commit_after>//
//  ExpressionTests.swift
//  SwiftParsec
//
//  Created by <NAME> on 2015-10-30.
//  Copyright © 2015 <NAME>. All rights reserved.
//

import XCTest
@testable import SwiftParsec

class ExpressionTests: XCTestCase {
    
    func testExpr() {
        
        let power: (Int, Int) -> Int = { base, exp in
            
            Int(pow(Double(base), Double(exp)))
        
        }
        
        let opTable: OperatorTable<String, (), Int> = [
            
            [
                prefix("-", function: -),
                prefix("+", function: { $0 })
            ],
            [
                postfix("²", function: { $0 * $0 })
            ],
            [
                binary(">>", function: >>, assoc: .None),
                binary("<<", function: <<, assoc: .None)
            ],
            [
                binary("^", function: power, assoc: .Right)
            ],
            [
                binary("*", function: *, assoc: .Left),
                binary("/", function: /, assoc: .Left)
            ],
            [
                binary("+", function: +, assoc: .Left),
                binary("-", function: -, assoc: .Left)
            ]
        
        ]
        
        let openingParen = StringParser.character("(")
        let closingParen = StringParser.character(")")
        let decimal = GenericTokenParser<()>.decimal
        
        let expr = opTable.expressionParser { expr in
            
            expr.between(openingParen, closingParen) <|> decimal
            
        }
        
        let matching = ["1+2*4-8+((3-12)/8)+(-71)+2^2^3", "(+3-3)+5", "3²", "4>>2", "4<<2"]
        
        var expected = [1+2*4-8+((3-12)/8)+(-71)+power(2, power(2, 3))]
        expected.append((+3-3)+5)
        expected.append(3*3)
        expected.append(4>>2)
        expected.append(4<<2)
        
        var index = 0
        
        let errorMessage = "OperatorTable.expressionParser did not succeed."
        
        testStringParserSuccess(expr, inputs: matching) { input, result in
            
            defer { index += 1 }
            XCTAssertEqual(expected[index], result, self.formatErrorMessage(errorMessage, input: input, result: result))
            
        }
        
    }
    
    func testReplaceRange() {
        
        var opTable = OperatorTable<String, (), Int>()
        
        opTable.append([
            prefix("-", function: -),
            prefix("+", function: { $0 })
        ])
        
        opTable.append([
            binary("*", function: *, assoc: .Left),
            binary("/", function: /, assoc: .Left)
        ])
        
        XCTAssertEqual(opTable.count, 2)
        
        opTable.replaceRange(0...0, with: [])
        
        XCTAssertEqual(opTable.count, 1)
        
    }
    
    func binary(name: String, function: (Int, Int) -> Int, assoc: Associativity) -> Operator<String, (), Int> {
        
        let opParser = StringParser.string(name) *> GenericParser(result: function)
        return .Infix(opParser, assoc)
        
    }
    
    func prefix(name: String, function: Int -> Int) -> Operator<String, (), Int> {
        
        let opParser = StringParser.string(name) *> GenericParser(result: function)
        return .Prefix(opParser)
        
    }
    
    func postfix(name: String, function: Int -> Int) -> Operator<String, (), Int> {
        
        let opParser = StringParser.string(name) *> GenericParser(result: function)
        return .Postfix(opParser.attempt)
        
    }
    
}
{'fraction_non_alphanumeric': 0.14573855019714893, 'fraction_numerical': 0.018956627236882014, 'mean_word_length': 1.5171755725190839, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 56, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5434963', 'n_tokens_mistral': 1978, 'n_tokens_neox': 1890, 'n_words': 401}