elm-tools / parser Goto Github PK
View Code? Open in Web Editor NEWSimple Parser + Nice Error Messages
Home Page: http://package.elm-lang.org/packages/elm-tools/parser/latest
License: BSD 3-Clause "New" or "Revised" License
Simple Parser + Nice Error Messages
Home Page: http://package.elm-lang.org/packages/elm-tools/parser/latest
License: BSD 3-Clause "New" or "Revised" License
intTuple =
succeed (,)
|= int
|. symbol "/"
|= int
crashes in weird ways:
> run intTuple "1/1"
crash
> run intTuple "1/12"
crash
> run intTuple "1/123"
crash
> run intTuple "1/1234"
Ok (1,1) -- this succeeds with wrong result
> run intTuple "1/12345"
Ok (1,12) -- it depends on the length of the second int
> run intTuple "12/12345"
Ok (12,1) -- and on the first int
> run intTuple "123/12345"
crash
So it seems to crash if len(secondInt) - len(firstInt) <= 2
Error: Ran into a `Debug.crash` in module `Parser`
This was caused by the `case` expression between lines 600 and 612.
One of the branches ended with a crash and the following value got through:
Err "could not convert string '' to an Int"
The message provided by the code author is:
The `Parser.int` parser seems to have a bug.
Please report an SSCCE to <https://github.com/elm-tools/parser/issues>.
If I replace int
with float
, it works as expected.
I apologize if this is not really an issue, but I've had no luck figuring out how to do it, or getting ideas on Slack, Reddit, or the Google Group.
If an error condition is detected directly by my code while parsing, then I can use
Parser.fail "my custom error message"
But what if the problem is found not directly in my code, but in elm-tools/parser code that I call? For example,
Parser.list spaces Parser.int
If the current text doesn't look like a list of integers, then Parser.list
will generate a Problem
, with a readable but robotic error message like BadOneOf ([ExpectingSymbol ",",ExpectingSymbol "]"])
. But suppose I want to output a custom error message instead of simply reporting the error message contained in the Problem
generated by Parser.list
. I can't see how to do this.
It's analogous to (in imperative languages with exceptions) catching an exception thrown by a called function and throwing a new, more informative exception based on the calling context.
The closest workaround I can tell (and a very ugly one) is to put lots of information into the context String
:
(Parser.inContext "section_3.2.4.3" <| Parser.list spaces Parser.int)
and then to use a big if
or case
statement after calling Parser.run
to check the context to see what part of the parser caused the problem, substituting the custom error message there:
if context.description == "section_1.1.1.1" then
...
else if context.description == "section_1.1.1.2" then
...
else if context.description == "section_3.2.4.3" then
"my custom error message"
else ...
SSCCE:
Parser.run Parser.float "-1"
Output:
Error: Ran into a `Debug.crash` in module `Parser`
This was caused by the `case` expression between lines 695 and 707.
One of the branches ended with a crash and the following value got through:
Err "could not convert string '' to a Float"
The message provided by the code author is:
The `Parser.float` parser seems to have a bug.
Please report an SSCCE to <https://github.com/elm-tools/parser/issues>.
run float "e1"
Error: Ran into a Debug.crash
in module Parser
This was caused by the case
expression between lines 733 and 745.
One of the branches ended with a crash and the following value got through:
Err "could not convert string 'e1' to a Float"
The message provided by the code author is:
The `Parser.float` parser seems to have a bug.
Hi
While trying out the parser, I ran into the above error with this code. I tried to make it short, it's still kind of lengthy, but this reproduces it, only when Identifier
and Option
are in the oneOf
, and only when there is two levels of lists as with Expression and Term.
import Test exposing (..)
import Expect
import Parser exposing (..)
import Parser.LanguageKit exposing (..)
import Set
all : Test
all =
describe "Parser Test"
[ test "Parse identifier should pass" <|
\() ->
case run identifier "ABC" of
Ok res ->
Expect.equal res (Identifier "ABC")
Err err ->
Expect.fail <| toString err
]
type Expression
= Expression (List Term)
type Term
= Term (List Factor)
type Factor
= Identifier String
| Option Expression
expression : Parser Expression
expression =
succeed Expression
|= repeat zeroOrMore term
term : Parser Term
term =
succeed Term
|= repeat zeroOrMore factor
factor : Parser Factor
factor =
oneOf [ identifier, opt ]
opt : Parser Factor
opt =
succeed Option |. symbol "[" |. spaces |= (lazy (\_ -> expression)) |. spaces |. symbol "]"
identifier : Parser Factor
identifier =
succeed Identifier |= variable isLetter isCharacter Set.empty
isLetter : Char -> Bool
isLetter c =
List.member c letters
isDigit : Char -> Bool
isDigit c =
List.member c digits
isSymbol : Char -> Bool
isSymbol c =
List.member c symbols
isCharacter : Char -> Bool
isCharacter c =
isLetter c || isDigit c || isSymbol c || c == '_'
isLetterOrDigitOrUnderscore : Char -> Bool
isLetterOrDigitOrUnderscore c =
List.member c letters
|| List.member c digits
|| (c == '_')
letters : List Char
letters =
[ 'A', 'B', 'C' ]
digits : List Char
digits =
[ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ]
symbols : List Char
symbols =
[ '[', ']', '{', '}', '(', ')', '<', '>', '"', '\'', '=', ',', '.', ',', ';' ]
spaces : Parser ()
spaces =
ignore zeroOrMore (\c -> c == ' ')
"dependencies": {
"elm-community/json-extra": "2.0.0 <= v < 3.0.0",
"elm-lang/html": "2.0.0 <= v < 3.0.0",
"mgold/elm-random-pcg": "4.0.2 <= v < 5.0.0",
"elm-lang/core": "5.0.0 <= v < 6.0.0",
"elm-community/elm-test": "3.0.0 <= v < 4.0.0",
"rtfeldman/node-test-runner": "3.0.0 <= v < 4.0.0",
"elm-tools/parser": "2.0.1 <= v < 3.0.0"
},
"elm-version": "0.18.0 <= v < 0.19.0"
I created a regex-based parser (included below) that I have found to be incredibly useful. It is often significantly shorter/easier to represent some productions in the regex-based parser than using the built-in parsers, and it can also support things that are extremely difficult/complex (perhaps not impossible, but I couldn't work out how to do them).
This is unsurprising, as parsers often use regex as tokenizers, and regex is of course a means of specifying parsers for "regular languages".
Some examples of things that a regex parser primitive would allow:
I want to support the JS number syntax. I found it on stackoverflow and fairly trivially translated it for Elm's regex library: "[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?"
. I think this is possible in the parser, but is awkward (optional
is a missing parser that would make this easier). This compares well to the 100ish lines to handle Ints in the current implementation.
In general, it is much easier to find a well-known regex for things on StackOverflow, rather than having to (possibly erroneously) handwrite one (with tons of tests!).
I want to allow "function names" to be built according to this regex: "[a-zA-Z:!@#%&\\*\\-_\\+\\|/\\?><]+"
. I think I would struggle to do that in less than 20 lines using existing parsers. A parser that would make this simpler would be "match any char in this string".
"\"(?:[^\"\\\\]|\\\\.)*\""
is the elm string version of a regex to match a quoted string, allowing an escaped string inside the string. I couldn't figure out how to do this at all, though I expect it is possible. This regex isn't pretty (mostly due to the need to escape things a lot), but it's a lot prettier than I think this would come out building it the manual way.
Regexes can be case-insensitive: "true"
(with case-insensitivity) is a useful way of supporting [tT][rR][uU][eE]
. A case-insensitive parsing primitive would allow this feature.
Regex would also support a range of things that aren't currently supported but are supported by regexes. Examples include a range of repeats (would solve #20), character-set negation ([^abc]), greedyness, lookahead, etc. These aren't all great features necessarily, but they can help in a pinch.
Regex also has very mature implementations in browsers, and this would likely avoid the problems in #14, #16 and #12.
Here's my homemade implementation:
token : String -> (String -> a) -> String -> Parser a
token name ctor re = token_ name ctor ("^" ++ re |> Regex.regex)
tokenCI : String -> (String -> a) -> String -> Parser a
tokenCI name ctor re = token_ name ctor ("^" ++ re |> Regex.regex |> Regex.caseInsensitive)
token_ : String -> (String -> a) -> Regex.Regex -> Parser a
token_ name ctor re =
PInternal.Parser <| \({ source, offset, indent, context, row, col } as state) ->
let substring = String.dropLeft offset source in
case Regex.find (Regex.AtMost 1) re substring of
[{match}] -> Good (ctor match) { state | offset = offset + String.length match
, col = col + String.length match}
[] -> Bad (Parser.Parser.Fail <| "Regex " ++ name ++ " not matched: /" ++ toString re ++ "/") state
_ -> Debug.crash <| "Should never get more than 1 match for regex: " ++ name
Hi, Really nice library, enjoying using it!
I noticed the whitespace
function only works with allowTabs = False
. When set to True
, it looks like there's an infinite recursion somewhere.
See REPL session below based on the example from the documentation comments.
I'm using v2.0.1 of the library with Elm 0.18.
$ elm repl
---- elm-repl 0.18.0 -----------------------------------------------------------
:help for help, :exit to exit, more at <https://github.com/elm-lang/elm-repl>
--------------------------------------------------------------------------------
> import Parser exposing (..)
> import Parser.LanguageKit exposing (..)
> jsWhitespace = whitespace { allowTabs = True, lineComment = LineComment "//", multiComment = UnnestableComment "/*" "*/" }
Parser <function> : Parser.Parser ()
> run jsWhitespace ""
RangeError: Maximum call stack size exceeded
> noTabsWhitespace = whitespace { allowTabs = False, lineComment = LineComment "//", multiComment = UnnestableComment "/*" "*/" }
Parser <function> : Parser.Parser ()
> run noTabsWhitespace ""
Ok () : Result.Result Parser.Error ()
>
tl;dr: can't debug parsers well, here's some things I tried.
I have a relatively straightforward parser that is currently about 170 lines, and it isn't working. It is already extremely difficult to figure out why my parser isn't working. A feature around this (or a guide explaining how to do this if you already have known good techniques) would be extremely useful.
Here are some things I've tried:
myInt = succeed (MyInt >> debug)
|= ...
|. ...
This showed me when something matched, which was slightly useful.
(parse state)
printContext : String -> (State -> Step a) -> State -> Step a
printContext msg parse state =
let outputStrFn msg con = List.map (\c -> c.description ++ " (" ++ msg ++ "): " ++ (toString c.row) ++ ", " ++ (toString c.col)) con |> String.join "\n"
outputFn c = let _ = Debug.log (outputStrFn msg c) () in c
result = parse { state | context = (outputFn state.context)}
in
case result of
Good _ _ -> let _ = Debug.log ("GOOD (" ++ msg ++ ")") (state.context |> List.head |> Maybe.map .description) in result
Bad _ _ -> let _ = Debug.log ("BAD (" ++ msg ++ ")") (state.context |> List.head |> Maybe.map .description) in result
{-| Run a parser *and then* run another parser!
-}
andThen : (a -> Parser b) -> Parser a -> Parser b
andThen callback (Parser parseA) =
Parser <| \state1 ->
case printContext "andThen2" parseA state1 of -- <===== HERE
Bad x state2 ->
Bad x state2
Good a state2 ->
let
(Parser parseB) =
callback a
in
printContext "andThen2" parseB state2 -- <===== ALSO HERE
This does show me how my parsers behave and give me a rough structure of what's happening. Indeed this shows me that some of my parsers in my oneOf aren't being called, but I'm still not sure what's going on.
I think this tells me that I need to see what's happening in my pipelines too. My best hypothesis right now is that oneOf
is broken, but I still don't have enough info to have any conviction in that.
---- elm-repl 0.18.0 -----------------------------------------------------------
:help for help, :exit to exit, more at <https://github.com/elm-lang/elm-repl>
--------------------------------------------------------------------------------
> import Parser
> Parser.run Parser.float "."
Error: Ran into a `Debug.crash` in module `Parser`
This was caused by the `case` expression between lines 733 and 745.
One of the branches ended with a crash and the following value got through:
Err "could not convert string '.' to a Float"
The message provided by the code author is:
The `Parser.float` parser seems to have a bug.
Please report an SSCCE to <https://github.com/elm-tools/parser/issues>.
>
I'm using elm-tools/parser
2.0.1. Presumably this is a similar issue to #1?
Pretty much as the title says. If you try to do something like
Parser.run Parser.float "-3.2"
This results in an error whereas it should give the float -3.2.
I've found a particular combination of parsers that, when combined, overflow the stack.
import Char
import Html exposing (..)
import Parser exposing (..)
main =
text <| toString <| run root "a/b/c"
root =
zeroOrMore (element |. optional separator)
element =
mapWithSource always (ignoreWhile Char.isLower)
optional p =
oneOf [ p, succeed () ]
separator =
symbol "/"
I can't seem to get it any smaller, unfortunately. The two important parts: ignoreWhile Char.isLower
and optional
. If either of those are removed from the execution path (by dropping optional
or using ignore 1 Char.isLower
), the parser works.
Right now you can compose parsers, but you can't create new ones from scratch. I believe this would require at least Parser.Internal.Parser
, Parser.Internal.Good
, and Parser.Internal.Bad
. Those aren't exposed, and AFAICT I can't access unexposed functions from another module.
Workaround: I vendored the parser so I could access them.
I'm using elm-tools/parser
to try to parse large machine-generated files in STEP format. To get good parsing performance I've had to use a bunch of tricks like stripping out whitespace using regular expressions as a preprocessing step so that the 'actual' parsing can disregard whitespace. I've also avoided using any of the Char -> Bool
predicate-based parsers since they seem quite slow compared to String
-based ones like symbol
and ignoreUntil
.
It would be useful for performance (and perhaps convenience in some cases) to have Regex
-based parsers like
regex : Regex -> Parser String
ignoreUntilRegex : Regex -> Parser ()
For example, right now replicating a hypothetical Parser.regex (Regex.regex "[A-Z_][A-Z_0-9]")
is possible using the Parser
module but involves a lot of use of character predicates and is quite slow as a result. Would it be possible to implement one or both of the above without sacrificing too much error message quality? (I'm not as concerned about error message quality myself since the text I care about is machine generated, but I agree that's an extremely important goal in general.)
TL;DR: I need something like keepOne : (Bool -> Char) -> Parser Char
.
Context: I'm parsing commonmark markdown. The spec for thematic breaks specifies that while ---
and the like are valid thematic breaks, a mix of characters is not. So I need to disallow *-*
and other mixes of valid thematic break characters. I do this now by doing something like this:
initial : Parser Char
initial =
keep (Exactly 1) anyBreakChar
|> map (String.toList >> List.head >> Maybe.withDefault ' ')
This gives me the behavior I want, but allocates a string, a list, and a maybe (plus maybe some more stuff.) This is not terrible, but it's a big dance and results in unclear code (throwing the ' '
away, for example.)
I don't know the specifics that cause this error, but it consistently happens when I try to parse a large file for my obj file parser.
This could very well be because I wrote my parser somehow wrong.
I managed to reproduce this on runelm, here:
https://runelm.io/c/23z
If you change the url from the 'small file' to the 'big file' it will crash.
My actual code is very similar to the provided snippet.
I'm using chrome on linux .
run float ""
Error: Ran into a `Debug.crash` in module `Parser`
This was caused by the `case` expression between lines 695 and 707.
One of the branches ended with a crash and the following value got through:
Err "could not convert string '' to a Float"
The message provided by the code author is:
The `Parser.float` parser seems to have a bug.
commonmark has a bunch of block-level elements. The first one I implemented was thematic breaks (---
, ***
, but not mixed) I took care of that like this:
thematicBreak : Parser Block
thematicBreak =
let
anyBreakChar : Char -> Bool
anyBreakChar c =
c == '*' || c == '-' || c == '_'
initial : Parser String
initial =
succeed identity
|= keep (Exactly 1) anyBreakChar
|. ignore zeroOrMore whitespace
subsequent : String -> Parser ()
subsequent breakChar =
symbol breakChar |. ignore zeroOrMore whitespace
in
inContext "thematic break"
(succeed ThematicBreak
|. oneToThreeSpaces
|. (initial |> andThen (\c -> repeat (AtLeast 2) (subsequent c)))
|. eol
)
When I implemented the next block level element, I realized this commits too early. "No problem," I thought, "I'll just use delayedCommit
". But if there's a way to get both andThen
and delayedCommit
working on the same parser, I don't see it! I ended up with this:
thematicBreak : Parser Block
thematicBreak =
let
single : Char -> Parser ()
single breakChar =
ignore (Exactly 1) ((==) breakChar)
|. ignore zeroOrMore whitespace
lineOf : Char -> Parser ()
lineOf breakChar =
delayedCommit
(oneToThreeSpaces |. single breakChar)
(repeat (AtLeast 2) (single breakChar) |> map (always ()))
in
inContext "thematic break" <|
succeed ThematicBreak
|. oneOf
[ lineOf '*'
, lineOf '-'
, lineOf '_'
]
|. eol
This works, but it doesn't feel as good to me. I don't like repeating myself!
Edit: this is unclear, and a lot of text. Sorry! Concretely: the part that matters for indicating commitment is up to three spaces and then *
, -
, or _
.
---- elm-repl 0.18.0 -----------------------------------------------------------
:help for help, :exit to exit, more at <https://github.com/elm-lang/elm-repl>
--------------------------------------------------------------------------------
> import Parser
> import Parser.LanguageKit
> parser = Parser.LanguageKit.list (Parser.symbol "") Parser.int
Parser <function> : Parser.Parser (List Int)
> Parser.run parser "[1,2,3,4,5]"
Ok [1,2,3,4,5] : Result.Result Parser.Error (List Int)
> longList = "[" ++ (List.range 1 5000 |> List.map toString |> String.join ",") ++ "]"
"[1,2,3,...<elided>...,4998,4999,5000]" : String
> Parser.run parser longList
RangeError: Maximum call stack size exceeded
I'm running Elm 0.18 on Windows 10 64-bit.
EDIT: My workaround for now, for anyone else encountering the same issue, is to use a custom list parsing function like this (although more complex, since this version doesn't support whitespace or empty lists):
list =
Parser.succeed (\first rest -> first :: rest)
|. Parser.symbol "["
|= Parser.int
|= (Parser.repeat Parser.zeroOrMore
(Parser.succeed identity
|. Parser.symbol ","
|= Parser.int
)
)
|. Parser.symbol "]"
I'm guessing this will have lower-quality error messages than Parser.LanguageKit.list
, but in my particular case I'm parsing machine-generated text so high-quality error messages are not quite as important.
How is this repo related to https://github.com/elm/parser ? If the other one supersedes this one, should this one be archived?
I have two productions with overlapping rules:
(consider the string 4 + 5
, being matched with oneOf [number, binOpExpr]
where binOpExpr
references number
as well.)
I wrote them the naive way, and discovered that one would commit, preventing the other from running because of the oneOf
they were in. There was no ordering that would allow them succeed.
I think there is definitely a way of writing a parser in this framework to support the language, so the issue is that I didn't know how to do it. I think it would be useful to have one of these two things:
control over when to commit and when not to commit, as well as guidance for how to think about committing. I ended up hacking oneOf
, to ignore committed parsers and keep going.
a guide to an idiomatic way to write parsers using this framework.
Thanks!
Most of the block-level constructs in commonmark allow up to three characters of space before the start of the element. For example, ···#·hello
is still <h1>hello</h1>
. This is specifically 3 because 4 or more is the start of a code element. (····hello
== <pre><code>hello</pre></code>
)
To parse this, I have the following:
{-| Most of the CommonMark block elements allow one to three spaces before the
beginning of the block. So, helper parser!
-}
oneToThreeSpaces : Parser ()
oneToThreeSpaces =
oneOf
[ symbol " "
, symbol " "
, symbol " "
, succeed ()
]
But it's kind of awkward to write like that. I'd rather write something like this:
{-| Most of the CommonMark block elements allow one to three spaces before the
beginning of the block. So, helper parser!
-}
oneToThreeSpaces : Parser ()
oneToThreeSpaces =
ignore (AtMost 3) ((==) ' ')
Parser.float accepts floats with leading zeros even if they are not immediately before the dot, but parses the result to zero. E.g.
> Parser.run Parser.float "00.23"
Ok 0 : Result.Result Parser.Error Float
> Parser.run Parser.float "01"
Ok 0 : Result.Result Parser.Error Float
I was parsing the following string where it contained an integer prefixed with zero and received an unexpected error when using the int
parser. I expected the same behaviour as String.toInt
to return Ok 0
, but instead got and error for BadInt
. I suspect that it parses the 0
and then continues to check if it hex, thus expecting a x
and fails.
Here an example:
> import Parser exposing (..)
> parser = succeed (,) |= int
Parser <function> : Parser.Parser (a -> ( Int, a ))
> run parser "00"
Err { row = 1, col = 2, source = "00", problem = BadInt, context = [] }
: Result.Result Parser.Error (a -> ( Int, a ))
> run parser "01"
Err { row = 1, col = 2, source = "01", problem = BadInt, context = [] }
: Result.Result Parser.Error (a -> ( Int, a ))
The following is executed in elm-repl v0.18. The first two calls with allowTabs=False
terminate as expected (although I'm confused as to why "\t"
has a positive match when allowTabs=False
), but the next two calls with allowTabs=True
cause what is apparently an infinite recursion:
> import Parser exposing (..)
> import Parser.LanguageKit exposing (..)
> run (whitespace { allowTabs=False, lineComment=NoLineComment, multiComment=NoMultiComment } ) " "
Ok () : Result.Result Parser.Error ()
> run (whitespace { allowTabs=False, lineComment=NoLineComment, multiComment=NoMultiComment } ) "\t"
Ok () : Result.Result Parser.Error ()
> run (whitespace { allowTabs=True, lineComment=NoLineComment, multiComment=NoMultiComment } ) " "
RangeError: Maximum call stack size exceeded
> run (whitespace { allowTabs=True, lineComment=NoLineComment, multiComment=NoMultiComment } ) "\t"
RangeError: Maximum call stack size exceeded
I'm sure this is a permutation of some other error. There may be others like it, but this one is mine: https://ellie-app.com/XKBHwsdJyWa1/1
If you inline the function causing the error, i.e. by changing:
compare = exprType [ "=", "!=", "<", ">", "<=", ">=" ]
math = exprType [ "*", "/", "+", "-" ]
to
compare = oneOf (List.map toParser [ "=", "!=", "<", ">", "<=", ">=" ])
math = oneOf (List.map toParser [ "*", "/", "+", "-" ])
...then you get TypeError: f is not a function
. Like things I've seen reported other places, the issue seems to be that the function gets invoked before it's defined. Unlike things I've seen reported other places, juggling definition orders in Elm doesn't seem to have an effect.
While writing (well, attempting to write) this parser, I've also busted the call stack without the use of repeat
or zeroOrMore
, and I spent about a day and a half playing thunk roulette with Cannot read property '_0' of undefined
, so if you're looking for runtime errors, let me know. I've got plenty.
Same issue as #14
Parser.run Parser.int "-3"
This results in an error whereas it should give the int -3.
Per http://package.elm-lang.org/packages/elm-tools/parser/2.0.1/Parser, run int "0123"
is supposed to Err
.
My use-case is that I want to parse ISO8601 strings which have can have the form "2017-01-01"
where the "01" components are zero-padded.
@evancz pointed out that a leading zero can indicate an octal number, so that's a complication.
example 1
Parser.run (Parser.succeed identity |. Parser.symbol "R" |= Parser.int) "R1"
example 2
Parser.run (Parser.succeed identity |. Parser.ignoreUntilAfter "R" |= Parser.int) "R1"
Error: Ran into a `Debug.crash` in module `Parser`
This was caused by the `case` expression between lines 600 and 612.
One of the branches ended with a crash and the following value got through:
Err "could not convert string '' to an Int"
The message provided by the code author is:
The `Parser.int` parser seems to have a bug.
Please report an SSCCE to <https://github.com/elm-tools/parser/issues>.
Maybe I'm not supposed to use Parser.symbol for a letter such as "R"? But I didn't see any warnings about this and the error message give doesn't make it clearer.
Issue #33 reported the following behavior:
run float "00.23" == Ok 0
run float "01" == Ok 0
Need to test with newer implementation
module Main exposing (..)
import Html exposing (Html, text)
import Parser exposing (andThen, keyword, oneOf, run)
main =
view (createBigFile 10000)
createBigFile n =
String.repeat n "1"
crashWithLotsOfText =
oneOf
[ keyword "1"
|> andThen (\_ -> crashWithLotsOfText)
, Parser.end
]
view txt =
run crashWithLotsOfText txt
|> Result.mapError (always "")
|> Result.map (always "")
|> (toString >> text)
Changing 10000 to 1000 compiles fine.
Uncaught RangeError: Maximum call stack size exceeded
My code:
> parser = Parser.succeed (,) |= Parser.int |. Parser.symbol "x" |= Parser.int
> Parser.run parser "1x1"
Expected output:
( 1, 1 ) : ( Int, Int )
Actual ouput:
Err { row = 1, col = 2, source = "1x1", problem = BadInt, context = [] }
: Result.Result Parser.Error ( Int, Int )
I'm getting an error in the compiled code when I use a lazy parser. Here it is as an Ellie: https://ellie-app.com/dtBXJdLSTa1/0
When minimized, my code looks like this:
fnCall : Parser String
fnCall =
succeed (always "")
|= repeat oneOrMore fnArg
fnArg : Parser String
fnArg =
lazy (\_ -> fnCall)
This causes the following error:
elm.js:18405 Uncaught TypeError: Cannot read property '_0' of undefined
at Function.func (elm.js:18405)
at A2 (elm.js:92)
at elm.js:20657
at elm.js:23710
(anonymous) @ elm.js:18405
A2 @ elm.js:92
(anonymous) @ elm.js:20657
(anonymous) @ elm.js:23710
ui:1108 Elm threw when called with {}
ui:1109 Uncaught ReferenceError: Elm is not defined
at ui:1109
which corresponds to this (I vendor Parser into my app, but I only change the module names)
var _user$project$Parser_Parser$repeat = F2(
function (count, _p56) {
var _p57 = _p56;
var _p59 = _p57._0; // <------------------------HERE
var _p58 = count;
if (_p58.ctor === 'Exactly') {
return _user$project$Parser_Parser_Internal$Parser(
function (state) {
return A4(
_user$project$Parser_Parser$repeatExactly,
_p58._0,
_p59,
{ctor: '[]'},
state);
});
} else {
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.