 
 class FixValidations: XCTestCase {
 
-    override func setUp() {
-        super.setUp()
-        // Put setup code here. This method is called before the invocation of each test method in the class.
+    func testTerminalBody(){
+        let source = "This is the body of a string \\\" that ends here\""
+        do {
+            let result = try test(STLRStringTest.terminalBody._rule(), with: source)
+            guard case let .consume(context) = result else {
+                XCTFail("Result should have been success but was \(result)")
+                return
+            }
+            XCTAssertEqual(context.matchedString, String(source.dropLast()))
+        } catch {
+            XCTFail("Match should not have thrown: \(error)")
+        }
     }
     
-    override func tearDown() {
-        // Put teardown code here. This method is called after the invocation of each test method in the class.
-        super.tearDown()
+    func testNotStringCharacter(){
+        let characters = ["\"","\n","\r"]
+        
+        for character in characters {
+            do {
+                _ = try test(STLRStringTest.stringCharacter._rule(), with: character)
+                XCTFail("Match should not have passed for \(character.debugDescription)")
+            } catch {
+            }
+        }
     }
-
+    
+    func testStringCharacter(){
+        let characters = ["\\r","\\n","\\t","\\\"","\\\\"]
+        
+        for character in characters {
+            do {
+                let result = try test(STLRStringTest.stringCharacter._rule(), with: "\\\(character)")
+                guard case .consume(_) = result else {
+                    XCTFail("Result should have been success but was \(result) for \(character)")
+                    continue
+                }
+            } catch {
+                XCTFail("Match should not have thrown for \(character): \(error)")
+            }
+        }
+    }
+    
+    func testStringQuote(){
+        do {
+            let result = try test(STLRStringTest.stringQuote._rule(), with: "\"")
+            guard case let .success(context) = result else {
+                XCTFail("Result should have been success but was \(result)")
+                return
+            }
+            XCTAssertEqual(context.matchedString, "\"")
+        } catch {
+            XCTFail("Match should not have thrown: \(error)")
+        }
+    }
+    
+    func testEscapedCharacter(){
+        let characters = ["r","n","t","\"","\\"]
+        
+        for character in characters {
+            do {
+                let result = try test(STLRStringTest.escapedCharacter._rule(), with: "\\\(character)")
+                guard case let .success(context) = result else {
+                    XCTFail("Result should have been success but was \(result) for \(character)")
+                    return
+                }
+                XCTAssertEqual(context.matchedString, "\\\(character)")
+            } catch {
+                XCTFail("Match should not have thrown for \(character): \(error)")
+            }
+        }
+    }
+    
     //
     // Effect: Rule annotation to report an error on missing terminal string is lost
     //
     func testLostAnnotation(){
 
         do{
-            let _ = try STLRStringTest.parse(source: "\"h")
+            let _ = try STLRStringTest.parse(source: "\"h\n")
             XCTFail("Expected unterminated string error" )
         } catch AbstractSyntaxTreeConstructor.ConstructionError.constructionFailed(let errors) {
-            XCTAssertEqual(errors.count, 2)
-            XCTAssertTrue("\(errors[0])".hasPrefix("Missing terminating quote"))
+            XCTAssertEqual(errors.count, 1)
+            XCTAssertTrue(((errors[0] as? TestErrorType)?.message ?? "").hasPrefix("Missing terminating quote"))
         } catch {
             XCTFail("Unexpected error \(error)")
         }

    
    case _transient = -1, `stringQuote`, `escapedCharacters`, `escapedCharacter`, `stringCharacter`, `terminalBody`, `terminalString`
    
    func _rule(_ annotations: RuleAnnotations = [ : ])->Rule {
        switch self {
        case ._transient:
            return CharacterSet(charactersIn: "").terminal(token: T._transient)
        // stringQuote
        case .stringQuote:
            return "\"".terminal(token: T.stringQuote, annotations: annotations.isEmpty ? [:] : annotations)
        // escapedCharacters
        case .escapedCharacters:
            return [
                T.stringQuote._rule(),
                "r".terminal(token: T._transient),
                "n".terminal(token: T._transient),
                "t".terminal(token: T._transient),
                "\\".terminal(token: T._transient),
                ].oneOf(token: T.escapedCharacters)
        // escapedCharacter
        case .escapedCharacter:
            return [
                "\\".terminal(token: T._transient),
                T.escapedCharacters._rule(),
                ].sequence(token: T.escapedCharacter, annotations: annotations.isEmpty ? [ : ] : annotations)
        // stringCharacter
        case .stringCharacter:
            return [
                T.escapedCharacter._rule(),
                [
                    T.stringQuote._rule(),
                    CharacterSet.newlines.terminal(token: T._transient),
                    ].oneOf(token: T._transient).not(producing: T._transient),
                ].oneOf(token: T.stringCharacter, annotations: [RuleAnnotation.void : RuleAnnotationValue.set])
        // terminalBody
        case .terminalBody:
            return T.stringCharacter._rule([RuleAnnotation.void : RuleAnnotationValue.set]).repeated(min: 1, producing: T.terminalBody, annotations: annotations)
        // terminalString
        case .terminalString:
            return [
                T.stringQuote._rule(),
                T.terminalBody._rule([RuleAnnotation.error : RuleAnnotationValue.string("Terminals must have at least one character")]),
                T.stringQuote._rule([RuleAnnotation.error : RuleAnnotationValue.string("Missing terminating quote")]),
                ].sequence(token: T.terminalString, annotations: annotations.isEmpty ? [ : ] : annotations)
        }
    }
    


import XCTest
@testable import OysterKit
@testable import ExampleLanguages

fileprivate enum STLRStringTest : Int, Token {
    
