Add newline to the parsing grammar to resolve some bugs#56
Add newline to the parsing grammar to resolve some bugs#56jmbeck15 wants to merge 9 commits intoMichael-F-Bryan:masterfrom
Conversation
Was replaced with broken_intra_doc_links.
Fix skip_whitespace test and add respect_newlines test.
Removed part of the test that was simply invalid.
Tweaked it to return the expected newline character.
8d7dfa8 to
c11ad15
Compare
Both fail, and are the basis for a new bug report.
c11ad15 to
2107449
Compare
Michael-F-Bryan
left a comment
There was a problem hiding this comment.
Thanks for making this PR @jmbeck15! I think adding newlines as an explicit token in the language totally makes sense.
Overall I'm pretty happy with the PR, but there were a couple small questions I'd like to get your thoughts on.
| fn tokenize_newline(&mut self) -> Option<Token<'input>> { | ||
| let start = self.current_position; | ||
| let line = self.current_line; | ||
| let value = "\n"; | ||
| self.current_position += 1; | ||
| self.current_line += 1; | ||
| Some(Token { | ||
| kind: TokenType::Newline, | ||
| value, | ||
| span: Span { | ||
| start, | ||
| line, | ||
| end: start + 1, | ||
| }, | ||
| }) | ||
| } |
There was a problem hiding this comment.
If the only way this function can be called is when we're looking at a \n character, would it be enough to add something like debug_assert!(self.rest().starts_with("\n")) and return a Token<'input>?
Otherwise, we should actually check for the newline character and return None if it isn't found.
Either way, I think we should try to use the newline characters from the original stream instead of writing let value = "\n".
There was a problem hiding this comment.
I think what you're getting at is "this code has a weird smell", and I think you're right. 😁 But I'm honestly not sure how to construct this better. If we don't explicitly set value = "\n", we'd have to chomp() or somehow otherwise pull the newline from the string, which is a computational expense that seems superfluous.
As for your suggestion
would it be enough to add something like
debug_assert!(self.rest().starts_with("\n"))and return aToken<'input>
I don't think I understand. The debug_assert is something I could add; seems reasonable. But how would you return the Token<'input>?
| } | ||
|
|
||
| #[test] | ||
| fn two_multi() { |
There was a problem hiding this comment.
It would probably be more readable if we rewrite the test to be something like this:
let expected = vec![
("G", 0),
("0", 0),
("X", 0),
...
];
let actual: Vec<_> = Lexer::new("...")
.map(|tok| (tok.value, tok.span.line))
.collect();
assert_eq!(actual, expected);There was a problem hiding this comment.
For long g-code example tests, that's probably the way to go. Maybe we could create some helper methods that make testing easier. We're really missing these long-form g-code verification tests, so I took this one from the pull request @dr0ps made.
How about we keep this test as is for now, and rework these kinds of tests in the future?
Co-authored-by: Michael Bryan <michaelfbryan@gmail.com>
Co-authored-by: Michael Bryan <michaelfbryan@gmail.com>
|
@Michael-F-Bryan I pushed two more commits, one of which fixes #55. I was going to wait until after this pull request was merged to fix #55, but it turns out very much related to the newline handling. If you prefer these fixes in separate pull requests, just let me know. |
|
Howdy! In case anyone is still out there, I tried using this library and ran into a bug. The library panicked on the gcode generated by DrawingBotV3-Free. Anyways, I am interested to know if this change would fix it. I'm hoping this message will motivate someone to resolve this merge request. |
|
@jpursell if you send me some minimal example code that panics the library, I'll check it out. I'm curious. |
Summary
By adding newline (
\n) to the grammar, this pull request will:It may be easier to review by commit than in bulk.
Description
Newlines are special for GCode; they represent the end of the current command and the start of a new one. This commit makes newlines a first-class token, and parses with them under consideration.
How I tested
I added some tests, un-ignored or fixed other tests, and executed
cargo test.I also ran a bunch of gcode files through the parser as a sanity check. In retrospect, I should have created tests from them, so I may go back and do that if I need to make further changes.