Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extending grammar integration tests #6644

Merged
merged 10 commits into from
Apr 29, 2024

Conversation

HanClinto
Copy link
Collaborator

@HanClinto HanClinto commented Apr 12, 2024

As part of the discussion around #6640, I wanted to expand the integration tests to help add end-to-end confirmation of rework around grammar quantifiers (both in that PR and others in the works).

There are two sets of commits here -- the first commit refactors our tests and de-duplicates code.

The later commits extends our tests by adding some new grammars focused on exercising the quantifiers, and provides a structure to (hopefully) make this simple to extend in the future.

The diff is a mess, but hopefully breaking it up into two commits like this can help simplify what's going on.

Copy link
Collaborator

@ochafik ochafik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very neat!

@HanClinto HanClinto force-pushed the grammar-test-cleanup branch from 1b98885 to e875161 Compare April 27, 2024 13:38
@HanClinto
Copy link
Collaborator Author

HanClinto commented Apr 27, 2024

Okay, finally got around to implementing your suggestions, @ochafik. How does this look to you?

I personally like verbose tests, this would make it easier to understand what caused any failure (edit: esp. on CI)

I took this suggestion to heart, and this is now the output one gets from running this test. Is this closer to what you were envisioning?

Running grammar integration tests...
🟢 Testing grammar:
            root ::= expression
            expression ::= term ws (("+"|"-") ws term)*
            term ::= factor ws (("*"|"/") ws factor)*
            factor ::= number | variable | "(" expression ")" | function-call
            number ::= [0-9]+
            variable ::= [a-zA-Z_][a-zA-Z0-9_]*
            function-call ::= variable ws "(" (expression ("," ws expression)*)? ")"
            ws ::= [ \t\n\r]?
  ✅︎ Matched string: "42"
  ✅︎ Matched string: "1*2*3*4*5"
  ✅︎ Matched string: "x"
  ✅︎ Matched string: "x+10"
  ✅︎ Matched string: "x1+y2"
  ✅︎ Matched string: "(a+b)*(c-d)"
  ✅︎ Matched string: "func()"
  ✅︎ Matched string: "func(x,y+2)"
  ✅︎ Matched string: "a*(b+c)-d/e"
  ✅︎ Matched string: "f(g(x),h(y,z))"
  ✅︎ Matched string: "x + 10"
  ✅︎ Matched string: "x1 + y2"
  ✅︎ Matched string: "(a + b) * (c - d)"
  ✅︎ Matched string: "func()"
  ✅︎ Matched string: "func(x, y + 2)"
  ✅︎ Matched string: "a * (b + c) - d / e"
  ✅︎ Matched string: "f(g(x), h(y, z))"
  ✅︎ Matched string: "123+456"
  ✅︎ Matched string: "123*456*789-123/456+789*123"
  ✅︎ Matched string: "123+456*789-123/456+789*123-456/789+123*456-789/123+456*789-123/456+789*123-456"
  ✅︎ Correctly did not match string: "+"
  ✅︎ Correctly did not match string: "/ 3x"
  ✅︎ Correctly did not match string: "x + + y"
  ✅︎ Correctly did not match string: "a * / b"
  ✅︎ Correctly did not match string: "func(,)"
  ✅︎ Correctly did not match string: "func(x y)"
  ✅︎ Correctly did not match string: "(a + b"
  ✅︎ Correctly did not match string: "x + y)"
  ✅︎ Correctly did not match string: "a + b * (c - d"
  ✅︎ Correctly did not match string: "42 +"
  ✅︎ Correctly did not match string: "x +"
  ✅︎ Correctly did not match string: "x + 10 +"
  ✅︎ Correctly did not match string: "(a + b) * (c - d"
  ✅︎ Correctly did not match string: "func("
  ✅︎ Correctly did not match string: "func(x, y + 2"
  ✅︎ Correctly did not match string: "a * (b + c) - d /"
  ✅︎ Correctly did not match string: "f(g(x), h(y, z)"
  ✅︎ Correctly did not match string: "123+456*789-123/456+789*123-456/789+123*456-789/123+456*789-123/456+789*123-456/"
🟢 Testing grammar: root ::= "a"*
  ✅︎ Matched string: ""
  ✅︎ Matched string: "a"
  ✅︎ Matched string: "aaaaa"
  ✅︎ Matched string: "aaaaaaaaaaaaaaaaaa"
  ✅︎ Matched string: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
  ✅︎ Correctly did not match string: "b"
  ✅︎ Correctly did not match string: "ab"
  ✅︎ Correctly did not match string: "aab"
  ✅︎ Correctly did not match string: "ba"
  ✅︎ Correctly did not match string: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab"
🟢 Testing grammar: root ::= "a"+
  ✅︎ Matched string: "a"
  ✅︎ Matched string: "aaaaa"
  ✅︎ Matched string: "aaaaaaaaaaaaaaaaaa"
  ✅︎ Matched string: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
  ✅︎ Correctly did not match string: ""
  ✅︎ Correctly did not match string: "b"
  ✅︎ Correctly did not match string: "ab"
  ✅︎ Correctly did not match string: "aab"
  ✅︎ Correctly did not match string: "ba"
  ✅︎ Correctly did not match string: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab"
🟢 Testing grammar: root ::= "a"?
  ✅︎ Matched string: ""
  ✅︎ Matched string: "a"
  ✅︎ Correctly did not match string: "b"
  ✅︎ Correctly did not match string: "ab"
  ✅︎ Correctly did not match string: "aa"
  ✅︎ Correctly did not match string: "ba"
🟢 Testing grammar:
            root ::= cons+ vowel* cons? (vowel cons)*
            vowel ::= [aeiouy]
            cons ::= [bcdfghjklmnpqrstvwxyz]

  ✅︎ Matched string: "yes"
  ✅︎ Matched string: "no"
  ✅︎ Matched string: "noyes"
  ✅︎ Matched string: "crwth"
  ✅︎ Matched string: "four"
  ✅︎ Matched string: "bryyyy"
  ✅︎ Correctly did not match string: "yess"
  ✅︎ Correctly did not match string: "yesno"
  ✅︎ Correctly did not match string: "forty"
  ✅︎ Correctly did not match string: "catyyy"
🟢 Testing for missing root node:
  ✅︎ Passed
🟢 Testing for missing reference node:
    Expected error:  parse: error parsing grammar: Undefined rule identifier 'numero'
    End of expected error.
  ✅︎ Passed
All tests passed.

In the event of a failure, it will show up like this:

🟢 Testing grammar:
            root ::= expression
            expression ::= term ws (("+"|"-") ws term)*
            term ::= factor ws (("*"|"/") ws factor)*
            factor ::= number | variable | "(" expression ")" | function-call
            number ::= [0-9]+
            variable ::= [a-zA-Z_][a-zA-Z0-9_]*
            function-call ::= variable ws "(" (expression ("," ws expression)*)? ")"
            ws ::= [ \t\n\r]?
  ✅︎ Matched string: "42"
  ✅︎ Matched string: "1*2*3*4*5"
  ✅︎ Matched string: "x"
  ✅︎ Matched string: "x+10"
  ❌ Failed to match string: "/ 3x"
Assertion failed: (matched), function test_grammar, file test-grammar-integration.cpp, line 73.
[1]    89505 abort      ./tests/test-grammar-integration

Edit: Amended to add quotes around test strings to explicitly show whitespace.

Rebased on latest master. Might even be good to expand these tests to include some stress tests, and put some timing information in there -- but I don't want to load down the regular tests too much. Maybe we do that in a separate test file that is only run optionally...?

Copy link
Collaborator

@ochafik ochafik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking great!


auto grammar = build_grammar(grammar_str);

bool matched = match_string("123+456", grammar);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot this one I think :-)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Could still call test_grammar from this one I think

break;
}
if (!matched) {
fprintf(stderr, " ❌ Failed to match string: \"%s\"\n", test_string.c_str());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉 There's nothing like a bit of color to brighten a dreadful grammar debugging session!

Nit: I was wondering if it's possible to write the string before testing it (flushing the output after writing its name). In my clumsy and limited testing I got a few non-catchable segfaults and I struggled to find which strings where causing the failure.

Maybe something like:

⚪️ Testing grammar:
            root ::= expression
            expression ::= term ws (("+"|"-") ws term)*
            term ::= factor ws (("*"|"/") ws factor)*
            factor ::= number | variable | "(" expression ")" | function-call
            number ::= [0-9]+
            variable ::= [a-zA-Z_][a-zA-Z0-9_]*
            function-call ::= variable ws "(" (expression ("," ws expression)*)? ")"
            ws ::= [ \t\n\r]?
  Checking valid strings:
    "42" ✅︎
    "1*2*3*4*5" ✅︎
    "4" ❌ (erroneously rejected)
  Checking *invalid* strings:
    "+" ✅︎
    "/ 3x" ✅︎
    "11111" ❌ (erroneously matched)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea about pre-printing the strings and flushing buffers. I'll implement that! I intend to revisit #6492 soon, so better output on segfaults will come in handy I think.

Thanks for the nits!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what the full test output looks like now:

Running grammar integration tests...
⚪ Testing grammar:
            root ::= expression
            expression ::= term ws (("+"|"-") ws term)*
            term ::= factor ws (("*"|"/") ws factor)*
            factor ::= number | variable | "(" expression ")" | function-call
            number ::= [0-9]+
            variable ::= [a-zA-Z_][a-zA-Z0-9_]*
            function-call ::= variable ws "(" (expression ("," ws expression)*)? ")"
            ws ::= [ \t\n\r]?
  Checking valid strings:
    "42" ✅︎
    "1*2*3*4*5" ✅︎
    "x" ✅︎
    "x+10" ✅︎
    "x1+y2" ✅︎
    "(a+b)*(c-d)" ✅︎
    "func()" ✅︎
    "func(x,y+2)" ✅︎
    "a*(b+c)-d/e" ✅︎
    "f(g(x),h(y,z))" ✅︎
    "x + 10" ✅︎
    "x1 + y2" ✅︎
    "(a + b) * (c - d)" ✅︎
    "func()" ✅︎
    "func(x, y + 2)" ✅︎
    "a * (b + c) - d / e" ✅︎
    "f(g(x), h(y, z))" ✅︎
    "123+456" ✅︎
    "123*456*789-123/456+789*123" ✅︎
    "123+456*789-123/456+789*123-456/789+123*456-789/123+456*789-123/456+789*123-456" ✅︎
  Checking invalid strings:
    "+" ✅︎
    "/ 3x" ✅︎
    "x + + y" ✅︎
    "a * / b" ✅︎
    "func(,)" ✅︎
    "func(x y)" ✅︎
    "(a + b" ✅︎
    "x + y)" ✅︎
    "a + b * (c - d" ✅︎
    "42 +" ✅︎
    "x +" ✅︎
    "x + 10 +" ✅︎
    "(a + b) * (c - d" ✅︎
    "func(" ✅︎
    "func(x, y + 2" ✅︎
    "a * (b + c) - d /" ✅︎
    "f(g(x), h(y, z)" ✅︎
    "123+456*789-123/456+789*123-456/789+123*456-789/123+456*789-123/456+789*123-456/" ✅︎
⚪ Testing grammar: root ::= "a"*
  Checking valid strings:
    "" ✅︎
    "a" ✅︎
    "aaaaa" ✅︎
    "aaaaaaaaaaaaaaaaaa" ✅︎
    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ✅︎
  Checking invalid strings:
    "b" ✅︎
    "ab" ✅︎
    "aab" ✅︎
    "ba" ✅︎
    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab" ✅︎
⚪ Testing grammar: root ::= "a"+
  Checking valid strings:
    "a" ✅︎
    "aaaaa" ✅︎
    "aaaaaaaaaaaaaaaaaa" ✅︎
    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ✅︎
  Checking invalid strings:
    "" ✅︎
    "b" ✅︎
    "ab" ✅︎
    "aab" ✅︎
    "ba" ✅︎
    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab" ✅︎
⚪ Testing grammar: root ::= "a"?
  Checking valid strings:
    "" ✅︎
    "a" ✅︎
  Checking invalid strings:
    "b" ✅︎
    "ab" ✅︎
    "aa" ✅︎
    "ba" ✅︎
⚪ Testing grammar:
            root ::= cons+ vowel* cons? (vowel cons)*
            vowel ::= [aeiouy]
            cons ::= [bcdfghjklmnpqrstvwxyz]

  Checking valid strings:
    "yes" ✅︎
    "no" ✅︎
    "noyes" ✅︎
    "crwth" ✅︎
    "four" ✅︎
    "bryyyy" ✅︎
  Checking invalid strings:
    "yess" ✅︎
    "yesno" ✅︎
    "forty" ✅︎
    "catyyy" ✅︎
🟢 Testing for missing root node:
  ✅︎ Passed
🟢 Testing for missing reference node:
    Expected error:  parse: error parsing grammar: Undefined rule identifier 'numero'
    End of expected error.
  ✅︎ Passed
All tests passed.

And a failure-case:

Running grammar integration tests...
⚪ Testing grammar:
            root ::= expression
            expression ::= term ws (("+"|"-") ws term)*
            term ::= factor ws (("*"|"/") ws factor)*
            factor ::= number | variable | "(" expression ")" | function-call
            number ::= [0-9]+
            variable ::= [a-zA-Z_][a-zA-Z0-9_]*
            function-call ::= variable ws "(" (expression ("," ws expression)*)? ")"
            ws ::= [ \t\n\r]?
  Checking valid strings:
    "42" ✅︎
    "1*2*3*4*5" ✅︎
    "x" ✅︎
    "x+10" ✅︎
    "x1+y2" ✅︎
    "x + + y" ❌ (failed to match)
Assertion failed: (matched), function test_grammar, file test-grammar-integration.cpp, line 79.
[1]    54975 abort      ./tests/test-grammar-integration

Or:

Running grammar integration tests...
⚪ Testing grammar:
            root ::= expression
            expression ::= term ws (("+"|"-") ws term)*
            term ::= factor ws (("*"|"/") ws factor)*
            factor ::= number | variable | "(" expression ")" | function-call
            number ::= [0-9]+
            variable ::= [a-zA-Z_][a-zA-Z0-9_]*
            function-call ::= variable ws "(" (expression ("," ws expression)*)? ")"
            ws ::= [ \t\n\r]?
  Checking valid strings:
    "42" ✅︎
    "1*2*3*4*5" ✅︎
    "x" ✅︎
    "x+10" ✅︎
    "x1+y2" ✅︎
    "(a+b)*(c-d)" ✅︎
    "func()" ✅︎
    "func(x,y+2)" ✅︎
    "a*(b+c)-d/e" ✅︎
    "f(g(x),h(y,z))" ✅︎
    "x + 10" ✅︎
    "x1 + y2" ✅︎
    "(a + b) * (c - d)" ✅︎
    "func()" ✅︎
    "func(x, y + 2)" ✅︎
    "a * (b + c) - d / e" ✅︎
    "f(g(x), h(y, z))" ✅︎
    "123+456" ✅︎
    "123*456*789-123/456+789*123" ✅︎
    "123+456*789-123/456+789*123-456/789+123*456-789/123+456*789-123/456+789*123-456" ✅︎
  Checking invalid strings:
    "+" ✅︎
    "/ 3x" ✅︎
    "x1+y2" ❌ (incorrectly matched)
Assertion failed: (!matched), function test_grammar, file test-grammar-integration.cpp, line 99.
[1]    55489 abort      ./tests/test-grammar-integration

@HanClinto HanClinto force-pushed the grammar-test-cleanup branch from 5d7a459 to 7fe2fb3 Compare April 29, 2024 18:18
@HanClinto
Copy link
Collaborator Author

Rebased and ready for review again.

Copy link
Collaborator

@ochafik ochafik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, thanks @HanClinto !


auto grammar = build_grammar(grammar_str);

bool matched = match_string("123+456", grammar);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Could still call test_grammar from this one I think

…ess. Added comments for more verbose descriptions of what each test is accomplishing.
@HanClinto
Copy link
Collaborator Author

Good call on modifying simple_test to use test_grammar. I think originally I was leaving it that way as a bare-minimum example of how to do the simplest-possible exercise of grammar, but I don't know that it's needed.

I also missed a couple of green circles for white circles, and cleaned up a bit more language -- this is now what it looks like. It's still not as visually pleasing to the eyes as I would like, but I don't know how to make it better. Visually I don't like the checkmarks being at the end of the lines, but I'm not sure I want to put them on a newline, and I like having them afterwards in order to aid in debugging.

Running grammar integration tests...
⚪ Testing simple grammar. Grammar:
            root ::= expr
            expr ::= term ("+" term)*
            term ::= number
            number ::= [0-9]+
  Valid strings:
    "42" ✅︎
    "1+2+3+4+5" ✅︎
    "123+456" ✅︎
  Invalid strings:
    "+" ✅︎
    "/ 3" ✅︎
    "1+2+3+4+5+" ✅︎
    "12a45" ✅︎
⚪ Testing medium complexity grammar. Grammar:
            root ::= expression
            expression ::= term ws (("+"|"-") ws term)*
            term ::= factor ws (("*"|"/") ws factor)*
            factor ::= number | variable | "(" expression ")" | function-call
            number ::= [0-9]+
            variable ::= [a-zA-Z_][a-zA-Z0-9_]*
            function-call ::= variable ws "(" (expression ("," ws expression)*)? ")"
            ws ::= [ \t\n\r]?
  Valid strings:
    "42" ✅︎
    "1*2*3*4*5" ✅︎
    "x" ✅︎
    "x+10" ✅︎
    "x1+y2" ✅︎
    "(a+b)*(c-d)" ✅︎
    "func()" ✅︎
    "func(x,y+2)" ✅︎
    "a*(b+c)-d/e" ✅︎
    "f(g(x),h(y,z))" ✅︎
    "x + 10" ✅︎
    "x1 + y2" ✅︎
    "(a + b) * (c - d)" ✅︎
    "func()" ✅︎
    "func(x, y + 2)" ✅︎
    "a * (b + c) - d / e" ✅︎
    "f(g(x), h(y, z))" ✅︎
    "123+456" ✅︎
    "123*456*789-123/456+789*123" ✅︎
    "123+456*789-123/456+789*123-456/789+123*456-789/123+456*789-123/456+789*123-456" ✅︎
  Invalid strings:
    "+" ✅︎
    "/ 3x" ✅︎
    "x + + y" ✅︎
    "a * / b" ✅︎
    "func(,)" ✅︎
    "func(x y)" ✅︎
    "(a + b" ✅︎
    "x + y)" ✅︎
    "a + b * (c - d" ✅︎
    "42 +" ✅︎
    "x +" ✅︎
    "x + 10 +" ✅︎
    "(a + b) * (c - d" ✅︎
    "func(" ✅︎
    "func(x, y + 2" ✅︎
    "a * (b + c) - d /" ✅︎
    "f(g(x), h(y, z)" ✅︎
    "123+456*789-123/456+789*123-456/789+123*456-789/123+456*789-123/456+789*123-456/" ✅︎
⚪ Testing * quantifier. Grammar: root ::= "a"*
  Valid strings:
    "" ✅︎
    "a" ✅︎
    "aaaaa" ✅︎
    "aaaaaaaaaaaaaaaaaa" ✅︎
    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ✅︎
  Invalid strings:
    "b" ✅︎
    "ab" ✅︎
    "aab" ✅︎
    "ba" ✅︎
    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab" ✅︎
⚪ Testing + quantifier. Grammar: root ::= "a"+
  Valid strings:
    "a" ✅︎
    "aaaaa" ✅︎
    "aaaaaaaaaaaaaaaaaa" ✅︎
    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ✅︎
  Invalid strings:
    "" ✅︎
    "b" ✅︎
    "ab" ✅︎
    "aab" ✅︎
    "ba" ✅︎
    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab" ✅︎
⚪ Testing ? quantifier. Grammar: root ::= "a"?
  Valid strings:
    "" ✅︎
    "a" ✅︎
  Invalid strings:
    "b" ✅︎
    "ab" ✅︎
    "aa" ✅︎
    "ba" ✅︎
⚪ Testing mixed quantifiers. Grammar:
            root ::= cons+ vowel* cons? (vowel cons)*
            vowel ::= [aeiouy]
            cons ::= [bcdfghjklmnpqrstvwxyz]

  Valid strings:
    "yes" ✅︎
    "no" ✅︎
    "noyes" ✅︎
    "crwth" ✅︎
    "four" ✅︎
    "bryyyy" ✅︎
  Invalid strings:
    "yess" ✅︎
    "yesno" ✅︎
    "forty" ✅︎
    "catyyy" ✅︎
⚪ Testing missing root node:
  ✅︎ Passed
⚪ Testing missing reference node:
    Expected error:  parse: error parsing grammar: Undefined rule identifier 'numero'
    End of expected error.
  ✅︎ Passed
All tests passed.

@ochafik
Copy link
Collaborator

ochafik commented Apr 29, 2024

@HanClinto Looks great and very functional, ship it ;-) (looking forward to using it!!)

@HanClinto HanClinto merged commit b8c1476 into ggml-org:master Apr 29, 2024
52 of 57 checks passed
@HanClinto
Copy link
Collaborator Author

@HanClinto Looks great and very functional, ship it ;-)

Thanks for all the help and feedback -- it's much better as a result!

(looking forward to using it!!)

Yeah!! I'm really looking forward to you using this as well! Can hardly wait to wrap {m,n} quantifiers with this puppy. :)

nopperl pushed a commit to nopperl/llama.cpp that referenced this pull request May 5, 2024
* Cleaning up integration tests to share code between tests and make it simpler to add new tests.

* Add tests around quantifiers to ensure both matching and non-matching compliance.

* Add slightly more complex grammar with quantifiers to test references with quantifiers.

* Fixing build when C++17 is not present.

* Separating test calls to give more helpful stack traces on failure. Adding verbose messages to give visibility for what is being tested.

* Adding quotes around strings to explicitly show whitespace

* Removing trailing whitespace.

* Implementing suggestions from @ochafik -- grammars and test strings now print and flush before tests to aid in debugging segfaults and whatnot.

* Cleaning up forgotten symbols. Modifying simple test to use test harness. Added comments for more verbose descriptions of what each test is accomplishing.

* Unicode symbol modifications to hopefully make log easier to parse visually.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants