Kento Okura: 1 DRAFT: Improve parser/lexer 13 files changed, 1251 insertions(+), 216 deletions(-)
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~jonsterling/forester-devel/patches/55546/mbox | git am -3Learn more about email & git
This patch includes various improvements to the parser/lexer. Rough edges abound. Will require revising after applying the logseq patch... More of my thoughts are in various comments in the code. I can confirm that golden-forest builds successfully. In a nutshell: - feature: Add Grammar.messages file for declarative error messages - feature? Add Comment to parse tree. Doesn't get parsed yet, haven't mucked around with the lexer and parser. - feature: better error reporting during the lexing phase, and a fatal bug was fixed: failure to close the verbatim block is now handled gracefully, and a helpful message is provided. - FEATURE! The reported range upon encountering an unmatched delimiter now includes everthing including that delimiter. --- lib/compiler/Code.ml | 1 + lib/compiler/Expand.ml | 2 + lib/compiler/Grammar.messages | 1010 +++++++++++++++++++++++++++++++++ lib/compiler/Grammar.mly | 1 + lib/compiler/Lexer.mll | 60 +- lib/compiler/Parse.ml | 320 ++++++----- lib/compiler/Parse.mli | 5 - lib/compiler/dune | 6 + lib/frontend/Forester.ml | 18 +- lib/frontend/Import_graph.ml | 2 +- test/dune | 4 +- test/parse.expected | 13 - test/parse.ml | 25 - 13 files changed, 1251 insertions(+), 216 deletions(-) create mode 100644 lib/compiler/Grammar.messages delete mode 100644 lib/compiler/Parse.mli delete mode 100644 test/parse.expected delete mode 100644 test/parse.ml diff --git a/lib/compiler/Code.ml b/lib/compiler/Code.ml index af3e6e0..5c18de5 100644 --- a/lib/compiler/Code.ml +++ b/lib/compiler/Code.ml @@ -37,6 +37,7 @@ type node = | Decl_xmlns of string * string | Alloc of Trie.path | Namespace of Trie.path * t + | Comment of string [@@deriving show, repr] and t = node Range.located list diff --git a/lib/compiler/Expand.ml b/lib/compiler/Expand.ml index 5f9caca..2cb145d 100644 --- a/lib/compiler/Expand.ml +++ b/lib/compiler/Expand.ml @@ -172,6 +172,8 @@ let rec expand : Code.t -> Syn.t = function let symbol = Symbol.named path in Sc.include_singleton path @@ Term [Range.locate_opt loc (Syn.Sym symbol)]; expand rest + | { value = Comment _; loc } :: rest -> + expand rest and expand_method (key, body) = key, expand body diff --git a/lib/compiler/Grammar.messages b/lib/compiler/Grammar.messages new file mode 100644 index 0000000..f9ba540 --- /dev/null +++ b/lib/compiler/Grammar.messages @@ -0,0 +1,1010 @@ +main: TEXT +## +## Ends in an error in state: 0. +## +## main' -> . main [ # ] +## +## The known suffix of the stack is as follows: +## +## + +<YOUR 11 ERROR MESSAGE HERE> + +main: SUBTREE XML_ELT_IDENT +## +## Ends in an error in state: 4. +## +## head_node -> SUBTREE . option(squares(wstext)) LBRACE ws_list(locate(head_node)) RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## SUBTREE +## + +<YOUR 23 ERROR MESSAGE HERE> + +main: SUBTREE LSQUARE XML_ELT_IDENT +## +## Ends in an error in state: 5. +## +## option(squares(wstext)) -> LSQUARE . wstext RSQUARE [ LBRACE ] +## +## The known suffix of the stack is as follows: +## LSQUARE +## + +<YOUR 35 ERROR MESSAGE HERE> + +main: SUBTREE LSQUARE TEXT RBRACE +## +## Ends in an error in state: 8. +## +## option(squares(wstext)) -> LSQUARE wstext . RSQUARE [ LBRACE ] +## +## The known suffix of the stack is as follows: +## LSQUARE wstext +## +## WARNING: This example involves spurious reductions. +## This implies that, although the LR(1) items shown above provide an +## accurate view of the past (what has been recognized so far), they +## may provide an INCOMPLETE view of the future (what was expected next). +## In state 10, spurious reduction of production list(ws_or_text) -> +## In state 11, spurious reduction of production list(ws_or_text) -> ws_or_text list(ws_or_text) +## In state 12, spurious reduction of production wstext -> list(ws_or_text) +## + +<YOUR 55 ERROR MESSAGE HERE> + +main: DECL_XMLNS LBRACE TEXT XML_ELT_IDENT +## +## Ends in an error in state: 10. +## +## list(ws_or_text) -> ws_or_text . list(ws_or_text) [ RSQUARE RBRACE ] +## +## The known suffix of the stack is as follows: +## ws_or_text +## + +<YOUR 67 ERROR MESSAGE HERE> + +main: SUBTREE LSQUARE RSQUARE XML_ELT_IDENT +## +## Ends in an error in state: 13. +## +## head_node -> SUBTREE option(squares(wstext)) . LBRACE ws_list(locate(head_node)) RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## SUBTREE option(squares(wstext)) +## + +<YOUR 79 ERROR MESSAGE HERE> + +main: SUBTREE LBRACE TEXT +## +## Ends in an error in state: 14. +## +## head_node -> SUBTREE option(squares(wstext)) LBRACE . ws_list(locate(head_node)) RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## SUBTREE option(squares(wstext)) LBRACE +## + +<YOUR 91 ERROR MESSAGE HERE> + +main: SCOPE XML_ELT_IDENT +## +## Ends in an error in state: 15. +## +## head_node -> SCOPE . arg [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## SCOPE +## + +<YOUR 103 ERROR MESSAGE HERE> + +main: SCOPE LBRACE RSQUARE +## +## Ends in an error in state: 17. +## +## arg -> LBRACE . list(locate(textual_node)) RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## LBRACE +## + +<YOUR 115 ERROR MESSAGE HERE> + +main: PUT XML_ELT_IDENT +## +## Ends in an error in state: 20. +## +## head_node -> PUT . ident arg [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## PUT +## + +<YOUR 127 ERROR MESSAGE HERE> + +main: PUT IDENT XML_ELT_IDENT +## +## Ends in an error in state: 22. +## +## head_node -> PUT ident . arg [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## PUT ident +## + +<YOUR 139 ERROR MESSAGE HERE> + +main: PATCH XML_ELT_IDENT +## +## Ends in an error in state: 24. +## +## head_node -> PATCH . LBRACE ws_list(locate(head_node)) RBRACE option(squares(bvar)) LBRACE ws_list(method_decl) RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## PATCH +## + +<YOUR 151 ERROR MESSAGE HERE> + +main: PATCH LBRACE TEXT +## +## Ends in an error in state: 25. +## +## head_node -> PATCH LBRACE . ws_list(locate(head_node)) RBRACE option(squares(bvar)) LBRACE ws_list(method_decl) RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## PATCH LBRACE +## + +<YOUR 163 ERROR MESSAGE HERE> + +main: OPEN XML_ELT_IDENT +## +## Ends in an error in state: 26. +## +## head_node -> OPEN . ident [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## OPEN +## + +<YOUR 175 ERROR MESSAGE HERE> + +main: OBJECT XML_ELT_IDENT +## +## Ends in an error in state: 28. +## +## head_node -> OBJECT . option(squares(bvar)) LBRACE ws_list(method_decl) RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## OBJECT +## + +<YOUR 187 ERROR MESSAGE HERE> + +main: OBJECT LSQUARE XML_ELT_IDENT +## +## Ends in an error in state: 29. +## +## option(squares(bvar)) -> LSQUARE . bvar RSQUARE [ LBRACE ] +## +## The known suffix of the stack is as follows: +## LSQUARE +## + +<YOUR 199 ERROR MESSAGE HERE> + +main: OBJECT LSQUARE TEXT XML_ELT_IDENT +## +## Ends in an error in state: 31. +## +## option(squares(bvar)) -> LSQUARE bvar . RSQUARE [ LBRACE ] +## +## The known suffix of the stack is as follows: +## LSQUARE bvar +## + +<YOUR 211 ERROR MESSAGE HERE> + +main: OBJECT LSQUARE TEXT RSQUARE XML_ELT_IDENT +## +## Ends in an error in state: 33. +## +## head_node -> OBJECT option(squares(bvar)) . LBRACE ws_list(method_decl) RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## OBJECT option(squares(bvar)) +## + +<YOUR 223 ERROR MESSAGE HERE> + +main: OBJECT LBRACE XML_ELT_IDENT +## +## Ends in an error in state: 34. +## +## head_node -> OBJECT option(squares(bvar)) LBRACE . ws_list(method_decl) RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## OBJECT option(squares(bvar)) LBRACE +## + +<YOUR 235 ERROR MESSAGE HERE> + +main: OBJECT LBRACE LSQUARE XML_ELT_IDENT +## +## Ends in an error in state: 36. +## +## method_decl -> LSQUARE . TEXT RSQUARE list(WHITESPACE) arg [ WHITESPACE RBRACE LSQUARE ] +## +## The known suffix of the stack is as follows: +## LSQUARE +## + +<YOUR 247 ERROR MESSAGE HERE> + +main: OBJECT LBRACE LSQUARE TEXT XML_ELT_IDENT +## +## Ends in an error in state: 37. +## +## method_decl -> LSQUARE TEXT . RSQUARE list(WHITESPACE) arg [ WHITESPACE RBRACE LSQUARE ] +## +## The known suffix of the stack is as follows: +## LSQUARE TEXT +## + +<YOUR 259 ERROR MESSAGE HERE> + +main: OBJECT LBRACE LSQUARE TEXT RSQUARE XML_ELT_IDENT +## +## Ends in an error in state: 38. +## +## method_decl -> LSQUARE TEXT RSQUARE . list(WHITESPACE) arg [ WHITESPACE RBRACE LSQUARE ] +## +## The known suffix of the stack is as follows: +## LSQUARE TEXT RSQUARE +## + +<YOUR 271 ERROR MESSAGE HERE> + +main: OBJECT LBRACE LSQUARE TEXT RSQUARE WHITESPACE XML_ELT_IDENT +## +## Ends in an error in state: 39. +## +## list(WHITESPACE) -> WHITESPACE . list(WHITESPACE) [ VERBATIM LBRACE ] +## +## The known suffix of the stack is as follows: +## WHITESPACE +## + +<YOUR 283 ERROR MESSAGE HERE> + +main: OBJECT LBRACE WHITESPACE XML_ELT_IDENT +## +## Ends in an error in state: 43. +## +## list(ws_or(method_decl)) -> ws_or(method_decl) . list(ws_or(method_decl)) [ RBRACE ] +## +## The known suffix of the stack is as follows: +## ws_or(method_decl) +## + +<YOUR 295 ERROR MESSAGE HERE> + +main: NAMESPACE XML_ELT_IDENT +## +## Ends in an error in state: 49. +## +## head_node -> NAMESPACE . ident LBRACE ws_list(locate(head_node)) RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## NAMESPACE +## + +<YOUR 307 ERROR MESSAGE HERE> + +main: NAMESPACE IDENT XML_ELT_IDENT +## +## Ends in an error in state: 50. +## +## head_node -> NAMESPACE ident . LBRACE ws_list(locate(head_node)) RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## NAMESPACE ident +## + +<YOUR 319 ERROR MESSAGE HERE> + +main: NAMESPACE IDENT LBRACE TEXT +## +## Ends in an error in state: 51. +## +## head_node -> NAMESPACE ident LBRACE . ws_list(locate(head_node)) RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## NAMESPACE ident LBRACE +## + +<YOUR 331 ERROR MESSAGE HERE> + +main: LSQUARE RPAREN +## +## Ends in an error in state: 52. +## +## head_node -> LSQUARE . list(locate(textual_node)) RSQUARE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## LSQUARE +## + +<YOUR 343 ERROR MESSAGE HERE> + +main: LPAREN RSQUARE +## +## Ends in an error in state: 53. +## +## head_node -> LPAREN . list(locate(textual_node)) RPAREN [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## LPAREN +## + +<YOUR 355 ERROR MESSAGE HERE> + +main: LET XML_ELT_IDENT +## +## Ends in an error in state: 54. +## +## head_node -> LET . ident list(squares(bvar_with_strictness)) arg [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## LET +## + +<YOUR 367 ERROR MESSAGE HERE> + +main: LET IDENT XML_ELT_IDENT +## +## Ends in an error in state: 55. +## +## head_node -> LET ident . list(squares(bvar_with_strictness)) arg [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## LET ident +## + +<YOUR 379 ERROR MESSAGE HERE> + +main: FUN LSQUARE XML_ELT_IDENT +## +## Ends in an error in state: 56. +## +## list(squares(bvar_with_strictness)) -> LSQUARE . bvar_with_strictness RSQUARE list(squares(bvar_with_strictness)) [ VERBATIM LBRACE ] +## +## The known suffix of the stack is as follows: +## LSQUARE +## + +<YOUR 391 ERROR MESSAGE HERE> + +main: FUN LSQUARE TEXT XML_ELT_IDENT +## +## Ends in an error in state: 58. +## +## list(squares(bvar_with_strictness)) -> LSQUARE bvar_with_strictness . RSQUARE list(squares(bvar_with_strictness)) [ VERBATIM LBRACE ] +## +## The known suffix of the stack is as follows: +## LSQUARE bvar_with_strictness +## + +<YOUR 403 ERROR MESSAGE HERE> + +main: FUN LSQUARE TEXT RSQUARE XML_ELT_IDENT +## +## Ends in an error in state: 59. +## +## list(squares(bvar_with_strictness)) -> LSQUARE bvar_with_strictness RSQUARE . list(squares(bvar_with_strictness)) [ VERBATIM LBRACE ] +## +## The known suffix of the stack is as follows: +## LSQUARE bvar_with_strictness RSQUARE +## + +<YOUR 415 ERROR MESSAGE HERE> + +main: LBRACE RSQUARE +## +## Ends in an error in state: 63. +## +## head_node -> LBRACE . list(locate(textual_node)) RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## LBRACE +## + +<YOUR 427 ERROR MESSAGE HERE> + +main: IMPORT XML_ELT_IDENT +## +## Ends in an error in state: 64. +## +## head_node -> IMPORT . LBRACE wstext RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## IMPORT +## + +<YOUR 439 ERROR MESSAGE HERE> + +main: IMPORT LBRACE XML_ELT_IDENT +## +## Ends in an error in state: 65. +## +## head_node -> IMPORT LBRACE . wstext RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## IMPORT LBRACE +## + +<YOUR 451 ERROR MESSAGE HERE> + +main: IMPORT LBRACE TEXT RSQUARE +## +## Ends in an error in state: 66. +## +## head_node -> IMPORT LBRACE wstext . RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## IMPORT LBRACE wstext +## +## WARNING: This example involves spurious reductions. +## This implies that, although the LR(1) items shown above provide an +## accurate view of the past (what has been recognized so far), they +## may provide an INCOMPLETE view of the future (what was expected next). +## In state 10, spurious reduction of production list(ws_or_text) -> +## In state 11, spurious reduction of production list(ws_or_text) -> ws_or_text list(ws_or_text) +## In state 12, spurious reduction of production wstext -> list(ws_or_text) +## + +<YOUR 471 ERROR MESSAGE HERE> + +main: HASH_LBRACE RSQUARE +## +## Ends in an error in state: 68. +## +## head_node -> HASH_LBRACE . list(locate(textual_node)) RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## HASH_LBRACE +## + +<YOUR 483 ERROR MESSAGE HERE> + +main: HASH_HASH_LBRACE RSQUARE +## +## Ends in an error in state: 70. +## +## head_node -> HASH_HASH_LBRACE . list(locate(textual_node)) RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## HASH_HASH_LBRACE +## + +<YOUR 495 ERROR MESSAGE HERE> + +main: GET XML_ELT_IDENT +## +## Ends in an error in state: 71. +## +## head_node -> GET . ident [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## GET +## + +<YOUR 507 ERROR MESSAGE HERE> + +main: FUN XML_ELT_IDENT +## +## Ends in an error in state: 73. +## +## head_node -> FUN . list(squares(bvar_with_strictness)) arg [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## FUN +## + +<YOUR 519 ERROR MESSAGE HERE> + +main: EXPORT XML_ELT_IDENT +## +## Ends in an error in state: 76. +## +## head_node -> EXPORT . LBRACE wstext RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## EXPORT +## + +<YOUR 531 ERROR MESSAGE HERE> + +main: EXPORT LBRACE XML_ELT_IDENT +## +## Ends in an error in state: 77. +## +## head_node -> EXPORT LBRACE . wstext RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## EXPORT LBRACE +## + +<YOUR 543 ERROR MESSAGE HERE> + +main: EXPORT LBRACE TEXT RSQUARE +## +## Ends in an error in state: 78. +## +## head_node -> EXPORT LBRACE wstext . RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## EXPORT LBRACE wstext +## +## WARNING: This example involves spurious reductions. +## This implies that, although the LR(1) items shown above provide an +## accurate view of the past (what has been recognized so far), they +## may provide an INCOMPLETE view of the future (what was expected next). +## In state 10, spurious reduction of production list(ws_or_text) -> +## In state 11, spurious reduction of production list(ws_or_text) -> ws_or_text list(ws_or_text) +## In state 12, spurious reduction of production wstext -> list(ws_or_text) +## + +<YOUR 563 ERROR MESSAGE HERE> + +main: DEFAULT XML_ELT_IDENT +## +## Ends in an error in state: 80. +## +## head_node -> DEFAULT . ident arg [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## DEFAULT +## + +<YOUR 575 ERROR MESSAGE HERE> + +main: DEFAULT IDENT XML_ELT_IDENT +## +## Ends in an error in state: 81. +## +## head_node -> DEFAULT ident . arg [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## DEFAULT ident +## + +<YOUR 587 ERROR MESSAGE HERE> + +main: DEF XML_ELT_IDENT +## +## Ends in an error in state: 83. +## +## head_node -> DEF . ident list(squares(bvar_with_strictness)) arg [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## DEF +## + +<YOUR 599 ERROR MESSAGE HERE> + +main: DEF IDENT XML_ELT_IDENT +## +## Ends in an error in state: 84. +## +## head_node -> DEF ident . list(squares(bvar_with_strictness)) arg [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## DEF ident +## + +<YOUR 611 ERROR MESSAGE HERE> + +main: DECL_XMLNS XML_ELT_IDENT +## +## Ends in an error in state: 87. +## +## head_node -> DECL_XMLNS . LBRACE wstext RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## DECL_XMLNS +## + +<YOUR 623 ERROR MESSAGE HERE> + +main: DECL_XMLNS LBRACE XML_ELT_IDENT +## +## Ends in an error in state: 88. +## +## head_node -> DECL_XMLNS LBRACE . wstext RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## DECL_XMLNS LBRACE +## + +<YOUR 635 ERROR MESSAGE HERE> + +main: DECL_XMLNS LBRACE TEXT RSQUARE +## +## Ends in an error in state: 89. +## +## head_node -> DECL_XMLNS LBRACE wstext . RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## DECL_XMLNS LBRACE wstext +## +## WARNING: This example involves spurious reductions. +## This implies that, although the LR(1) items shown above provide an +## accurate view of the past (what has been recognized so far), they +## may provide an INCOMPLETE view of the future (what was expected next). +## In state 10, spurious reduction of production list(ws_or_text) -> +## In state 11, spurious reduction of production list(ws_or_text) -> ws_or_text list(ws_or_text) +## In state 12, spurious reduction of production wstext -> list(ws_or_text) +## + +<YOUR 655 ERROR MESSAGE HERE> + +main: CALL XML_ELT_IDENT +## +## Ends in an error in state: 91. +## +## head_node -> CALL . LBRACE ws_list(locate(head_node)) RBRACE LBRACE wstext RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## CALL +## + +<YOUR 667 ERROR MESSAGE HERE> + +main: CALL LBRACE TEXT +## +## Ends in an error in state: 92. +## +## head_node -> CALL LBRACE . ws_list(locate(head_node)) RBRACE LBRACE wstext RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## CALL LBRACE +## + +<YOUR 679 ERROR MESSAGE HERE> + +main: ALLOC XML_ELT_IDENT +## +## Ends in an error in state: 93. +## +## head_node -> ALLOC . ident [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## ALLOC +## + +<YOUR 691 ERROR MESSAGE HERE> + +main: IDENT TEXT +## +## Ends in an error in state: 95. +## +## list(ws_or(locate(head_node))) -> ws_or(locate(head_node)) . list(ws_or(locate(head_node))) [ RBRACE EOF ] +## +## The known suffix of the stack is as follows: +## ws_or(locate(head_node)) +## + +<YOUR 703 ERROR MESSAGE HERE> + +main: CALL LBRACE IDENT EOF +## +## Ends in an error in state: 99. +## +## head_node -> CALL LBRACE ws_list(locate(head_node)) . RBRACE LBRACE wstext RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## CALL LBRACE ws_list(locate(head_node)) +## +## WARNING: This example involves spurious reductions. +## This implies that, although the LR(1) items shown above provide an +## accurate view of the past (what has been recognized so far), they +## may provide an INCOMPLETE view of the future (what was expected next). +## In state 95, spurious reduction of production list(ws_or(locate(head_node))) -> +## In state 96, spurious reduction of production list(ws_or(locate(head_node))) -> ws_or(locate(head_node)) list(ws_or(locate(head_node))) +## In state 104, spurious reduction of production ws_list(locate(head_node)) -> list(ws_or(locate(head_node))) +## + +<YOUR 723 ERROR MESSAGE HERE> + +main: CALL LBRACE RBRACE XML_ELT_IDENT +## +## Ends in an error in state: 100. +## +## head_node -> CALL LBRACE ws_list(locate(head_node)) RBRACE . LBRACE wstext RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## CALL LBRACE ws_list(locate(head_node)) RBRACE +## + +<YOUR 735 ERROR MESSAGE HERE> + +main: CALL LBRACE RBRACE LBRACE XML_ELT_IDENT +## +## Ends in an error in state: 101. +## +## head_node -> CALL LBRACE ws_list(locate(head_node)) RBRACE LBRACE . wstext RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## CALL LBRACE ws_list(locate(head_node)) RBRACE LBRACE +## + +<YOUR 747 ERROR MESSAGE HERE> + +main: CALL LBRACE RBRACE LBRACE TEXT RSQUARE +## +## Ends in an error in state: 102. +## +## head_node -> CALL LBRACE ws_list(locate(head_node)) RBRACE LBRACE wstext . RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## CALL LBRACE ws_list(locate(head_node)) RBRACE LBRACE wstext +## +## WARNING: This example involves spurious reductions. +## This implies that, although the LR(1) items shown above provide an +## accurate view of the past (what has been recognized so far), they +## may provide an INCOMPLETE view of the future (what was expected next). +## In state 10, spurious reduction of production list(ws_or_text) -> +## In state 11, spurious reduction of production list(ws_or_text) -> ws_or_text list(ws_or_text) +## In state 12, spurious reduction of production wstext -> list(ws_or_text) +## + +<YOUR 767 ERROR MESSAGE HERE> + +main: HASH_HASH_LBRACE IDENT EOF +## +## Ends in an error in state: 105. +## +## list(locate(textual_node)) -> textual_node . list(locate(textual_node)) [ RSQUARE RPAREN RBRACE ] +## +## The known suffix of the stack is as follows: +## textual_node +## + +Did you forget to a closing brace? + +main: HASH_HASH_LBRACE IDENT RSQUARE +## +## Ends in an error in state: 108. +## +## head_node -> HASH_HASH_LBRACE list(locate(textual_node)) . RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## HASH_HASH_LBRACE list(locate(textual_node)) +## +## WARNING: This example involves spurious reductions. +## This implies that, although the LR(1) items shown above provide an +## accurate view of the past (what has been recognized so far), they +## may provide an INCOMPLETE view of the future (what was expected next). +## In state 105, spurious reduction of production list(locate(textual_node)) -> +## In state 106, spurious reduction of production list(locate(textual_node)) -> textual_node list(locate(textual_node)) +## + +<YOUR 798 ERROR MESSAGE HERE> + +main: HASH_LBRACE IDENT RSQUARE +## +## Ends in an error in state: 110. +## +## head_node -> HASH_LBRACE list(locate(textual_node)) . RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## HASH_LBRACE list(locate(textual_node)) +## +## WARNING: This example involves spurious reductions. +## This implies that, although the LR(1) items shown above provide an +## accurate view of the past (what has been recognized so far), they +## may provide an INCOMPLETE view of the future (what was expected next). +## In state 105, spurious reduction of production list(locate(textual_node)) -> +## In state 106, spurious reduction of production list(locate(textual_node)) -> textual_node list(locate(textual_node)) +## + +<YOUR 817 ERROR MESSAGE HERE> + +main: LBRACE IDENT RSQUARE +## +## Ends in an error in state: 112. +## +## head_node -> LBRACE list(locate(textual_node)) . RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## LBRACE list(locate(textual_node)) +## +## WARNING: This example involves spurious reductions. +## This implies that, although the LR(1) items shown above provide an +## accurate view of the past (what has been recognized so far), they +## may provide an INCOMPLETE view of the future (what was expected next). +## In state 105, spurious reduction of production list(locate(textual_node)) -> +## In state 106, spurious reduction of production list(locate(textual_node)) -> textual_node list(locate(textual_node)) +## + +<YOUR 836 ERROR MESSAGE HERE> + +main: LPAREN IDENT RSQUARE +## +## Ends in an error in state: 114. +## +## head_node -> LPAREN list(locate(textual_node)) . RPAREN [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## LPAREN list(locate(textual_node)) +## +## WARNING: This example involves spurious reductions. +## This implies that, although the LR(1) items shown above provide an +## accurate view of the past (what has been recognized so far), they +## may provide an INCOMPLETE view of the future (what was expected next). +## In state 105, spurious reduction of production list(locate(textual_node)) -> +## In state 106, spurious reduction of production list(locate(textual_node)) -> textual_node list(locate(textual_node)) +## + +<YOUR 855 ERROR MESSAGE HERE> + +main: LSQUARE IDENT RPAREN +## +## Ends in an error in state: 116. +## +## head_node -> LSQUARE list(locate(textual_node)) . RSQUARE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## LSQUARE list(locate(textual_node)) +## +## WARNING: This example involves spurious reductions. +## This implies that, although the LR(1) items shown above provide an +## accurate view of the past (what has been recognized so far), they +## may provide an INCOMPLETE view of the future (what was expected next). +## In state 105, spurious reduction of production list(locate(textual_node)) -> +## In state 106, spurious reduction of production list(locate(textual_node)) -> textual_node list(locate(textual_node)) +## + +<YOUR 874 ERROR MESSAGE HERE> + +main: NAMESPACE IDENT LBRACE IDENT EOF +## +## Ends in an error in state: 118. +## +## head_node -> NAMESPACE ident LBRACE ws_list(locate(head_node)) . RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## NAMESPACE ident LBRACE ws_list(locate(head_node)) +## +## WARNING: This example involves spurious reductions. +## This implies that, although the LR(1) items shown above provide an +## accurate view of the past (what has been recognized so far), they +## may provide an INCOMPLETE view of the future (what was expected next). +## In state 95, spurious reduction of production list(ws_or(locate(head_node))) -> +## In state 96, spurious reduction of production list(ws_or(locate(head_node))) -> ws_or(locate(head_node)) list(ws_or(locate(head_node))) +## In state 104, spurious reduction of production ws_list(locate(head_node)) -> list(ws_or(locate(head_node))) +## + +<YOUR 894 ERROR MESSAGE HERE> + +main: PATCH LBRACE IDENT EOF +## +## Ends in an error in state: 120. +## +## head_node -> PATCH LBRACE ws_list(locate(head_node)) . RBRACE option(squares(bvar)) LBRACE ws_list(method_decl) RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## PATCH LBRACE ws_list(locate(head_node)) +## +## WARNING: This example involves spurious reductions. +## This implies that, although the LR(1) items shown above provide an +## accurate view of the past (what has been recognized so far), they +## may provide an INCOMPLETE view of the future (what was expected next). +## In state 95, spurious reduction of production list(ws_or(locate(head_node))) -> +## In state 96, spurious reduction of production list(ws_or(locate(head_node))) -> ws_or(locate(head_node)) list(ws_or(locate(head_node))) +## In state 104, spurious reduction of production ws_list(locate(head_node)) -> list(ws_or(locate(head_node))) +## + +<YOUR 914 ERROR MESSAGE HERE> + +main: PATCH LBRACE RBRACE XML_ELT_IDENT +## +## Ends in an error in state: 121. +## +## head_node -> PATCH LBRACE ws_list(locate(head_node)) RBRACE . option(squares(bvar)) LBRACE ws_list(method_decl) RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## PATCH LBRACE ws_list(locate(head_node)) RBRACE +## + +<YOUR 926 ERROR MESSAGE HERE> + +main: PATCH LBRACE RBRACE LSQUARE TEXT RSQUARE XML_ELT_IDENT +## +## Ends in an error in state: 122. +## +## head_node -> PATCH LBRACE ws_list(locate(head_node)) RBRACE option(squares(bvar)) . LBRACE ws_list(method_decl) RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## PATCH LBRACE ws_list(locate(head_node)) RBRACE option(squares(bvar)) +## + +<YOUR 938 ERROR MESSAGE HERE> + +main: PATCH LBRACE RBRACE LBRACE XML_ELT_IDENT +## +## Ends in an error in state: 123. +## +## head_node -> PATCH LBRACE ws_list(locate(head_node)) RBRACE option(squares(bvar)) LBRACE . ws_list(method_decl) RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## PATCH LBRACE ws_list(locate(head_node)) RBRACE option(squares(bvar)) LBRACE +## + +<YOUR 950 ERROR MESSAGE HERE> + +main: SCOPE LBRACE IDENT RSQUARE +## +## Ends in an error in state: 126. +## +## arg -> LBRACE list(locate(textual_node)) . RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## LBRACE list(locate(textual_node)) +## +## WARNING: This example involves spurious reductions. +## This implies that, although the LR(1) items shown above provide an +## accurate view of the past (what has been recognized so far), they +## may provide an INCOMPLETE view of the future (what was expected next). +## In state 105, spurious reduction of production list(locate(textual_node)) -> +## In state 106, spurious reduction of production list(locate(textual_node)) -> textual_node list(locate(textual_node)) +## + +<YOUR 969 ERROR MESSAGE HERE> + +main: SUBTREE LBRACE IDENT EOF +## +## Ends in an error in state: 129. +## +## head_node -> SUBTREE option(squares(wstext)) LBRACE ws_list(locate(head_node)) . RBRACE [ XML_ELT_IDENT WHITESPACE VERBATIM TEXT SUBTREE SCOPE RSQUARE RPAREN RBRACE PUT PATCH OPEN OBJECT NAMESPACE LSQUARE LPAREN LET LBRACE IMPORT IDENT HASH_LBRACE HASH_IDENT HASH_HASH_LBRACE GET FUN EXPORT EOF DEFAULT DEF DECL_XMLNS CALL ALLOC ] +## +## The known suffix of the stack is as follows: +## SUBTREE option(squares(wstext)) LBRACE ws_list(locate(head_node)) +## +## WARNING: This example involves spurious reductions. +## This implies that, although the LR(1) items shown above provide an +## accurate view of the past (what has been recognized so far), they +## may provide an INCOMPLETE view of the future (what was expected next). +## In state 95, spurious reduction of production list(ws_or(locate(head_node))) -> +## In state 96, spurious reduction of production list(ws_or(locate(head_node))) -> ws_or(locate(head_node)) list(ws_or(locate(head_node))) +## In state 104, spurious reduction of production ws_list(locate(head_node)) -> list(ws_or(locate(head_node))) +## + +<YOUR 989 ERROR MESSAGE HERE> + +main: IDENT RBRACE +## +## Ends in an error in state: 131. +## +## main -> ws_list(locate(head_node)) . EOF [ # ] +## +## The known suffix of the stack is as follows: +## ws_list(locate(head_node)) +## +## WARNING: This example involves spurious reductions. +## This implies that, although the LR(1) items shown above provide an +## accurate view of the past (what has been recognized so far), they +## may provide an INCOMPLETE view of the future (what was expected next). +## In state 95, spurious reduction of production list(ws_or(locate(head_node))) -> +## In state 96, spurious reduction of production list(ws_or(locate(head_node))) -> ws_or(locate(head_node)) list(ws_or(locate(head_node))) +## In state 104, spurious reduction of production ws_list(locate(head_node)) -> list(ws_or(locate(head_node))) +## + +This brace is unmatched. + diff --git a/lib/compiler/Grammar.mly b/lib/compiler/Grammar.mly index 612f9b2..512686f 100644 --- a/lib/compiler/Grammar.mly +++ b/lib/compiler/Grammar.mly @@ -6,6 +6,7 @@ %token <string> XML_ELT_IDENT %token <string> DECL_XMLNS %token <string> TEXT VERBATIM +%token <string> COMMENT %token <string> WHITESPACE %token <string> IDENT %token <string> HASH_IDENT diff --git a/lib/compiler/Lexer.mll b/lib/compiler/Lexer.mll index 1818243..451894f 100644 --- a/lib/compiler/Lexer.mll +++ b/lib/compiler/Lexer.mll @@ -1,10 +1,14 @@ { open Forester_prelude let drop_sigil c str = 1 |> List.nth @@ String.split_on_char c str - let raise_err lexbuf = + exception Lex_err of (Lexing.lexbuf * string option) + + let raise_err lexbuf ?msg = let loc = Asai.Range.of_lexbuf lexbuf in - Forester_core.Reporter.fatalf ~loc Forester_core.Reporter.Message.Parse_error "unrecognized token `%s`" @@ - String.escaped @@ Lexing.lexeme lexbuf + Forester_core.Reporter.fatalf + ~loc + Forester_core.Reporter.Message.Parse_error + "unrecognized token `%s`.@ %a" (String.escaped @@ Lexing.lexeme lexbuf) Format.(pp_print_option pp_print_string) msg } let digit = ['0'-'9'] @@ -24,6 +28,7 @@ let verbatim_herald_sep = '|' rule token = parse | "\\%" { Grammar.TEXT "%" } + (* I added comments to the syntax tree, but how to proceed here? *) | "%" { comment lexbuf } | "##{" { Grammar.HASH_HASH_LBRACE } | "#{" { Grammar.HASH_LBRACE } @@ -79,7 +84,7 @@ rule token = parse | wschar+ { Grammar.WHITESPACE (Lexing.lexeme lexbuf) } | newline { Lexing.new_line lexbuf; Grammar.WHITESPACE (Lexing.lexeme lexbuf) } | eof { Grammar.EOF } - | _ { raise_err lexbuf } + | _ { raise_err lexbuf ?msg:None} and comment = parse | newline_followed_by_ws { Lexing.new_line lexbuf; token lexbuf } @@ -88,13 +93,13 @@ and comment = parse and custom_verbatim_herald = parse | verbatim_herald as herald { eat_verbatim_herald_sep (custom_verbatim herald (Buffer.create 2000)) lexbuf } - | newline { Lexing.new_line lexbuf; raise_err lexbuf } - | _ { raise_err lexbuf } + | newline { Lexing.new_line lexbuf; raise_err lexbuf ?msg:None } + | _ { raise_err lexbuf ?msg:None } and eat_verbatim_herald_sep kont = parse | verbatim_herald_sep { kont lexbuf } - | newline { Lexing.new_line lexbuf; raise_err lexbuf } - | _ { raise_err lexbuf } + | newline { Lexing.new_line lexbuf; raise_err ~msg:"Did you forget to start the verbatim block with `|`?" lexbuf } + | _ { raise_err ?msg:None lexbuf } and custom_verbatim herald buffer = parse | newline as c @@ -106,31 +111,34 @@ and custom_verbatim herald buffer = parse | _ as c { Buffer.add_char buffer c; - let buff_len = Buffer.length buffer in - let herald_len = String.length herald in - let offset = buff_len - herald_len in - if offset >= 0 && Buffer.sub buffer offset herald_len = herald then - let text = - String_util.trim_trailing_whitespace @@ - String_util.trim_newlines @@ - Buffer.sub buffer 0 offset - in - Grammar.VERBATIM text - else - custom_verbatim herald buffer lexbuf + try + let buff_len = Buffer.length buffer in + let herald_len = String.length herald in + let offset = buff_len - herald_len in + if offset >= 0 && Buffer.sub buffer offset herald_len = herald then + let text = + String_util.trim_trailing_whitespace @@ + String_util.trim_newlines @@ + Buffer.sub buffer 0 offset + in + Grammar.VERBATIM text + else + custom_verbatim herald buffer lexbuf + (* How can we report the location where the verbatim block was opened?*) + with _ -> raise_err lexbuf ~msg:(Format.sprintf "Did you forget to close the verbatim block with `%s`?" herald); } and xml_qname = parse | xml_qname as qname { qname } - | newline { Lexing.new_line lexbuf; raise_err lexbuf } - | _ { raise_err lexbuf } + | newline { Lexing.new_line lexbuf; raise_err ?msg:None lexbuf } + | _ { raise_err ?msg:None lexbuf } and xml_base_ident = parse | xml_base_ident as x { x } - | newline { Lexing.new_line lexbuf; raise_err lexbuf } - | _ { raise_err lexbuf } + | newline { Lexing.new_line lexbuf; raise_err ?msg:None lexbuf } + | _ { raise_err ?msg:None lexbuf } and rangle = parse | ">" { () } - | newline { Lexing.new_line lexbuf; raise_err lexbuf } - | _ { raise_err lexbuf } + | newline { Lexing.new_line lexbuf; raise_err ?msg:None lexbuf } + | _ { raise_err ?msg:None lexbuf } diff --git a/lib/compiler/Parse.ml b/lib/compiler/Parse.ml index e5f276c..d821cea 100644 --- a/lib/compiler/Parse.ml +++ b/lib/compiler/Parse.ml @@ -4,155 +4,197 @@ open Lexing module I = Grammar.MenhirInterpreter -(* debugging helpers *) -let _string_of_token token = - match token with - | Grammar.LBRACE -> "LBRACE" - | Grammar.RBRACE -> "RBRACE" - | Grammar.LSQUARE -> "LSQUARE" - | Grammar.RSQUARE -> "RSQUARE" - | Grammar.LPAREN -> "LPAREN" - | Grammar.RPAREN -> "RPAREN" - | Grammar.HASH_LBRACE -> "HASH_LBRACE" - | Grammar.HASH_HASH_LBRACE -> "HASH_HASH_LBRACE" - | Grammar.WHITESPACE w -> w - | Grammar.TEXT s -> s - | Grammar.EOF -> "EOF" - | Grammar.IDENT s -> Format.sprintf "IDENT(%s)" s - | _ -> "<unimplemented>" +(* NOTE: + I am unsure if we should ever fail during lexing. I propose: We should + introduce an `Error` syntax node so that the parse tree is capable of + representing arbitrary erroneous input. We never want this during batch + compilation, but always want this for the IDE. Depending on the context in + which the parser is running, we can immediately fail when encountering + such a node, or continue. This is what the `I.AboutToReduce` state is for. + *) -let _char_of_token token = - match token with - | Grammar.LBRACE -> '{' - | Grammar.RBRACE -> '}' - | Grammar.LSQUARE -> '[' - | Grammar.RSQUARE -> ']' - | Grammar.LPAREN -> '(' - | Grammar.RPAREN -> ')' - | Grammar.HASH_LBRACE -> '#' - | Grammar.HASH_HASH_LBRACE -> '#' - | _ -> 'x' +(* NOTE: Menhir generates a .messages file with one message per possible + error state. The incremental API associates a number to each state, + which we use to look up the custom parse error + *) +let get_parse_error env = + match I.stack env with + | lazy(Nil) -> "Invalid syntax" + | lazy(Cons (I.Element (state, _, _, _), _)) -> + try + let msg = (Grammar_messages.message (I.number state)) in + (* HACK: messages are currently placeholders that start with '<'. We want + to hide those "in production". During development, remove this check. + Whenever you encounter a parse error, the number in the returned + message will tell you the line number where it is defined in the + `Grammar.messages` file. You can then write a more helpful message. + *) + match msg.[0] with + | '<' -> "" + | _ -> msg + with + | Not_found -> "invalid syntax (no specific message for this eror)" -(* drive the parser to the next InputNeeded checkpoint *) -let rec resumes checkpoint = - match checkpoint with - | I.InputNeeded env -> I.input_needed env - | I.Shifting _ | I.AboutToReduce _ -> resumes @@ I.resume checkpoint - | _ -> assert false +let get_range : I.element option -> (position * position) option = fun el -> + match el with + | Some (I.Element (_, _, start_pos, end_pos)) -> + Some (start_pos, end_pos) + | None -> None -(* strategy: whenever we hit an unexpected closing delimiter, we look for a matching opening delimiter in the past - if we find one, close all intermediate (hanging) delimiters and then continue parsing - otherwise just continue parsing - if we hit a premature EOF, try to close all delimiters, and if that fails return the last good parse - (on each token, we test if the ending here would have produced a valid parse) *) -let try_parse lexbuf = - let rec fail bracketing last_token last_accept before supplier chkpt = - match chkpt with - | I.HandlingError _ -> - let loc = Asai.Range.of_lexbuf lexbuf in - Reporter.emitf ~loc Parse_error "syntax error, unexpected `%s`\n" (Lexing.lexeme lexbuf); - begin - match last_token with - | Grammar.RPAREN - | Grammar.RSQUARE - | Grammar.RBRACE -> - begin - match List.find_index (fun c -> c = last_token) bracketing with - | Some i -> - (* try to find a small enclosing scope *) - let consume = List.to_seq bracketing |> Seq.take (i + 1) in - let remaining = List.to_seq bracketing |> Seq.drop i |> List.of_seq in - let continue = Seq.fold_left (fun acc t -> resumes @@ I.offer acc (t, lexbuf.lex_curr_p, lexbuf.lex_curr_p)) before consume in - run remaining last_token last_accept before supplier continue - | None -> - (* ignore this token and move on *) - run bracketing Grammar.EOF last_accept before supplier before - end - | Grammar.EOF -> - if not @@ List.is_empty bracketing then - (* have hanging delimiters to close *) - let continue = List.fold_left (fun acc t -> resumes @@ I.offer acc (t, lexbuf.lex_curr_p, lexbuf.lex_curr_p)) before bracketing in - run [] last_token last_accept before supplier continue - else - (* can't continue, give up and use last_accept *) - run [] last_token last_accept before supplier last_accept - | _ -> - (* ignore this token and move on *) - run bracketing Grammar.EOF last_accept before supplier before - end - | _ -> Reporter.fatal Parse_error "unreachable parser state" +(* This is an attempt to create a function that better illustrates the + range in which an error occurs, but it turns out this is not really + the right design, and we probably need to use the full flexibility + of the incremental api, like in `incr_parse`. - and run bracketing last_token last_accept last_input_needed supplier checkpoint = - match checkpoint with - | I.InputNeeded _ -> - (* last_token has been accepted, update bracketing *) - let bracketing = - match last_token with - | Grammar.RPAREN - | Grammar.RSQUARE - | Grammar.RBRACE -> - assert (List.hd bracketing = last_token); List.tl bracketing - | _ -> bracketing - in - (* get new token *) - let token, start, end_ = supplier () in - let bracketing = - match token with - | Grammar.LPAREN -> Grammar.RPAREN :: bracketing - | Grammar.LSQUARE -> Grammar.RSQUARE :: bracketing - | Grammar.LBRACE - | Grammar.HASH_LBRACE - | Grammar.HASH_HASH_LBRACE -> - Grammar.RBRACE :: bracketing - | _ -> bracketing - in - (* check if it's possible to end parsing here, update last_accept *) - let la = - if I.acceptable checkpoint Grammar.EOF start then checkpoint - else last_accept - in - run bracketing token la checkpoint supplier @@ I.offer checkpoint (token, start, end_) - | I.Accepted v -> v - | I.Rejected - | I.HandlingError _ -> - fail bracketing last_token last_accept last_input_needed supplier checkpoint - | I.Shifting _ - | I.AboutToReduce _ -> - run bracketing last_token last_accept last_input_needed supplier @@ I.resume checkpoint - in - let checkpoint = Grammar.Incremental.main lexbuf.lex_curr_p in - let supplier = I.lexer_lexbuf_to_supplier Lexer.token lexbuf in - run [] Grammar.EOF checkpoint checkpoint supplier checkpoint -let maybe_with_errors (f : unit -> 'a) : ('a, 'a * 'b list) result = - let errors = ref Bwd.Emp in - let result = - let@ () = - Reporter.map_diagnostic @@ - fun d -> - errors := Bwd.snoc !errors d; - d + The motivation is to report things like + ``` + \foo{ + ^ this brace is unmatched + ``` + The problem here is that the opening brace and the point at which the + parser realizes that it is not getting closed might be arbitrarily far + apart. It might happen on EOF, or when an outer delimiter is closed, + like this: + ``` + {foo bar ] + ``` + + The function `loop_handle_undo` thus does not provide us with enough + context to compute the location of the unmatched brace. + *) + +let parse lexbuf = + I.loop_handle_undo + Result.ok + ( + fun last_successful_checkpt first_error_checkpt -> + match last_successful_checkpt, first_error_checkpt with + | I.InputNeeded succ_env, I.HandlingError err_env -> + let success_range = get_range @@ I.top succ_env in + let failure_range = get_range @@ I.top err_env in + let loc = + match success_range, failure_range with + | (Some (s, _), Some (_, e)) + | (_, Some (s, e)) + | (Some (s, e), _) -> + Option.some @@ Range.of_lex_range (s, e) + | None, None -> None + in + let message = get_parse_error err_env in + let diagnostic = + Reporter.diagnostic ?loc ~severity: Error Parse_error message + in + Error diagnostic + (*This should never ever happen. Report a bug at menhir!*) + | _, _ -> assert false + ) + (I.lexer_lexbuf_to_supplier Lexer.token lexbuf) + (Grammar.Incremental.main lexbuf.lex_curr_p) + +let closed_by c o = + match (o, c) with + | (Grammar.LSQUARE, Grammar.RSQUARE) + | (Grammar.LPAREN, Grammar.RPAREN) + | (Grammar.LBRACE, Grammar.RBRACE) + | (Grammar.HASH_LBRACE, Grammar.RBRACE) + | (Grammar.HASH_HASH_LBRACE, Grammar.RBRACE) -> + true + | _ -> false + +let is_opening_delim = function + | Grammar.LSQUARE + | Grammar.LPAREN + | Grammar.LBRACE + | Grammar.HASH_LBRACE + | Grammar.HASH_HASH_LBRACE -> + true + | _ -> false + +let is_closing_delim = function + | Grammar.RSQUARE + | Grammar.RPAREN + | Grammar.RBRACE -> + true + | _ -> false + +let incr_parse + : lexbuf -> + (Code.t, Reporter.Message.t Asai.Diagnostic.t) Result.t + = fun lexbuf -> + let delim_stack = Stack.create () in + let supplier = I.lexer_lexbuf_to_supplier (Lexer.token) lexbuf in + (* The idea is simple: push opening delimiters onto the stack, pop them + once they are closed. Upon encountering an error, the reported range + includes the last unclosed delimiter. + *) + let initial_checkpoint = (Grammar.Incremental.main lexbuf.lex_curr_p) in + let rec run + : _ I.checkpoint -> + (Code.t, Reporter.Message.t Asai.Diagnostic.t) Result.t + = fun checkpoint -> + match checkpoint with + | I.InputNeeded _env -> + (* In this phase we push and pop delimiters onto the stack.*) + let token = Lexer.token lexbuf in + let start_position = lexbuf.lex_start_p in + let end_position = lexbuf.lex_curr_p in + if is_opening_delim token then + let range = Range.of_lex_range (start_position, end_position) in + Stack.push (token, range) delim_stack; ; + let range_of_last_opening_delim = + if is_closing_delim token then + match Stack.top_opt delim_stack with + | Some (open_delim, range) -> + if (open_delim |> closed_by token) then + Option.map snd @@ Stack.pop_opt delim_stack + else None + | None -> None + else None + in + let checkpoint = I.offer checkpoint (token, start_position, end_position) in + run checkpoint + | I.Shifting((_, _, _): Code.t I.env * Code.t I.env * bool) -> + let checkpoint = I.resume checkpoint ~strategy: `Simplified in + run checkpoint + | I.AboutToReduce (_, production) -> + let checkpoint = I.resume checkpoint ~strategy: `Simplified in + run checkpoint + | I.HandlingError env -> + let err = get_parse_error env in + let range_of_last_unclosed = + match Stack.top_opt delim_stack with + | Some (token, range) -> + Some range + | None -> None + in + let loc = + match Option.map Range.view range_of_last_unclosed with + | Some (`Range (start_pos, end_pos)) -> + Range.make + (start_pos, Range.of_lex_position @@ Lexing.lexeme_start_p lexbuf) + | Some (`End_of_file _) -> Range.of_lexbuf lexbuf + | None -> Range.of_lexbuf lexbuf + in + Reporter.fatalf ~loc Parse_error "syntax error, unexpected `%s`. %s" (Lexing.lexeme lexbuf) err + | I.Accepted code -> Ok code + | I.Rejected -> + assert false in - f () - in - match !errors with - | Emp -> Result.ok result - | errs -> Result.error (result, Bwd.prepend errs []) + run initial_checkpoint let parse_channel filename ch = - let@ () = Reporter.tracef "when parsing file `%s`" filename in let lexbuf = Lexing.from_channel ch in lexbuf.lex_curr_p <- { lexbuf.lex_curr_p with pos_fname = filename }; - let@ () = maybe_with_errors in - try_parse lexbuf + try + incr_parse lexbuf + with + | Grammar.Error -> + Reporter.fatalf ~loc: (Range.of_lexbuf lexbuf) Parse_error "failed to parse" + | exn -> raise exn let parse_file filename = let ch = open_in filename in - let@ () = Fun.protect ~finally: (fun _ -> close_in ch) in - parse_channel filename ch - -let parse_string str = - let@ () = Reporter.tracef "when parsing string" in - let lexbuf = Lexing.from_string str in - let@ () = maybe_with_errors in - try_parse lexbuf + Fun.protect ~finally: (fun _ -> close_in ch) @@ + fun _ -> + parse_channel filename ch diff --git a/lib/compiler/Parse.mli b/lib/compiler/Parse.mli deleted file mode 100644 index 1a0a374..0000000 --- a/lib/compiler/Parse.mli @@ -1,5 +0,0 @@ -open Forester_core - -val parse_file : string -> (Code.t, Code.t * Reporter.Message.t Asai.Diagnostic.t list) result - -val parse_string : string -> (Code.t, Code.t * Reporter.Message.t Asai.Diagnostic.t list) result diff --git a/lib/compiler/dune b/lib/compiler/dune index 1d38bc8..12742b5 100644 --- a/lib/compiler/dune +++ b/lib/compiler/dune @@ -5,6 +5,12 @@ (explain true) (flags --inspection --table --dump)) +; The target for saving menhir's stdout to Grammar_messages.ml +(rule + (targets Grammar_messages.ml) + (deps Grammar.messages Grammar.mly) + (action (with-stdout-to %{targets} (run menhir --compile-errors %{deps})))) + (library (name Forester_compiler) (preprocess diff --git a/lib/frontend/Forester.ml b/lib/frontend/Forester.ml index 002a5bf..cdb1232 100644 --- a/lib/frontend/Forester.ml +++ b/lib/frontend/Forester.ml @@ -118,11 +118,19 @@ let parse_trees_in_dirs ~dev ?(ignore_malformed = false) dirs = let addr = Filename.chop_extension basename in let native = EP.native_exn fp in let source_path = if dev then Some (Unix.realpath native) else None in - match Parse.parse_file native with - | Result.Ok code -> Some Code.{ source_path; addr = Some addr; code } - | Result.Error _ -> None - | exception exn -> - if ignore_malformed then None else raise exn + try + match Parse.parse_file native with + | Ok code -> Some Code.{ source_path; addr = Some addr; code } + | Error diagnostic -> + if ignore_malformed then None + else + begin + Reporter.Tty.display diagnostic; + None + end + with + | exn -> + if ignore_malformed then None else raise exn let plant_forest_from_dirs ~env ~host ~dev ~tree_dirs ~asset_dirs : unit = let parsed_trees = parse_trees_in_dirs ~dev tree_dirs in diff --git a/lib/frontend/Import_graph.ml b/lib/frontend/Import_graph.ml index 42dee1a..cd1d42c 100644 --- a/lib/frontend/Import_graph.ml +++ b/lib/frontend/Import_graph.ml @@ -34,7 +34,7 @@ let build (trees : Code.tree list) = | Object { methods; _ } | Patch { methods; _ } -> let@ _, code = List.iter @~ methods in analyse_code roots code - | Text _ | Hash_ident _ | Angle_ident _ | Verbatim _ | Ident _ | Open _ | Put _ | Default _ | Get _ | Decl_xmlns _ | Call _ | Alloc _ -> () + | Text _ | Hash_ident _ | Angle_ident _ | Verbatim _ | Ident _ | Open _ | Put _ | Default _ | Get _ | Decl_xmlns _ | Call _ | Alloc _ | Comment _ -> () in begin let@ tree = List.iter @~ trees in diff --git a/test/dune b/test/dune index 7db3d0d..f14d778 100644 --- a/test/dune +++ b/test/dune @@ -1,5 +1,5 @@ -(tests - (names parse dsl) +(test + (name dsl) (preprocess (pps ppx_deriving.show)) (libraries diff --git a/test/parse.expected b/test/parse.expected deleted file mode 100644 index 5cbb180..0000000 --- a/test/parse.expected @@ -1,13 +0,0 @@ -parse_good_result: -[(Code.Ident title); (Code.Group (Base.Braces, [(Code.Text "Good")])); - (Code.Ident taxon); (Code.Group (Base.Braces, [(Code.Text "Test")])); - (Code.Ident author); (Code.Group (Base.Braces, [(Code.Text "Testy")])); - (Code.Ident p); - (Code.Group (Base.Braces, - [(Code.Text "\n"); (Code.Text " "); (Code.Text "This"); - (Code.Text " "); (Code.Text "should"); (Code.Text " "); - (Code.Text "parse"); (Code.Text " "); (Code.Text "correctly."); - (Code.Text "\n"); (Code.Text " ")] - )) - ] - diff --git a/test/parse.ml b/test/parse.ml deleted file mode 100644 index 862167c..0000000 --- a/test/parse.ml @@ -1,25 +0,0 @@ -open Forester_core -open Forester_compiler - -let emit _ = () (* ignore *) - -let fatal _ = exit 1 - -let _ = - Reporter.run ~emit ~fatal @@ - fun () -> - let good = - Result.get_ok @@ - Parse.parse_string - {| - \title{Good} - \taxon{Test} - \author{Testy} - - \p{ - This should parse correctly. - } - |} - in - Format.printf "parse_good_result:\n%s\n\n" (Code.show good) - -- 2.46.0