I've been making a 2009 script builder for a few hours now, and I can't figure out how to make it print errors. If I do print(loadstring("a")) it prints into the roblox output nil [string "s"]:1: '=' expected near '<eof>', which == nil. What I want to get is the error it reports at the end : '=' expected near '<eof>', type type is nil, so I have no idea how to get it. If anyone could help that would be greatly appreciated!
Refer to the Lua 5.1 manual, which will point you to the documentation for load:
If there [are] errors, ... returns nil plus the error message.
It's typical for Lua to return error messages as a second return value:
local f, err = loadstring(mycode)
if not f then
print("There was an error: `" .. err .. "`")
end
This err begins with where the error happened, which unhelpfully quotes the input to loadstring.
For example, for the input code "hello there", the error is
[string "hello there"]:1: '=' expected near 'there'
Lua appears to cut the quote off at the first newline or 63 character, whichever is less:
For "hello\there" the error is
[string "hello..."]:2: '=' expected near 'there'
For "helloooooooooooooooooooooooooooooooooooooooooooooooooooooo there" the error is
[string "helloooooooooooooooooooooooooooooooooooooooooooooooooooooo ther..."]:1: '=' expected near 'there'
If you're sure there's no "]: in the first 63 characters/first line of your script, you can just search for that sequence to find where it stops:
local location, message = err:match('^(%[string ".*"%]:%d+:%s+)(.*)$')
This won't be right if your code is, for example, "hello\"]:1: there", which you may want to address.
The simplest way to address it would be to take user control away from the first line that is quoted: prepend the code with your own first line that is nice (and make sure to adjust the line number of the error if you display it to the user:)
local f, err = loadstring("--code\n" .. mycode)
print(err)
Now the error message should always begin
[string "--code..."]:
Related
As as exercise of the Haskell Book written by bitemyapp I need to make a parser which can parse the given log.
So I made this : https://gist.github.com/RoelofWobben/79058b1a6a5c24f08a495045c7a685f9
but when I test it with : ` parseString parseMultipleDays myLog I see this error message :
Failure (ErrInfo {_errDoc = (interactive):3:1: error: expected: new-line
# 2025-02-05
^ , _errDeltas = [Lines 2 0 20 0]})
anyone who can give me a hint where the bug is. When needed I can make a repo of the code I have with some tests.
I use trifecta because that one is explained in the chapter
string "--" *> manyTill anyChar newline *> newline
manyTill already consumes the terminator, so the above defines a comment to be "--", followed by anything, followed by two newlines.
Your input only contains one newline after the comment, so you get an error telling you that the parser expected a second newline instead of the #.
So I'm starting to Learn Lua, my problem is that in a tutorial that teaches you to create Guess My Number Game starts with this line:
name = "John"
print<name>
So in the tutorial shows that prints the name but in mine gives this error:
stdin:1: '=' expected near '<'
Please, what am I getting this?
Thank you for all your help.
Functions use parentheses to enclose their arguments, so the second line should be
print (name)
Does any one knows if there is an ErrorStrategy on Antlr4.4 to continue parsing after an error is found, i need to show all the errors found in the program but Antlr stop parsing after the first error is found, im using the DefaultErrorStrategy.
This is my input, I should get error ond line 2 3 and 6 but it only reports the error on line 2.
class Program {
bool
bool test
int prueba ;
int prueba ;
int test;
bool prueba
}
The error is:
line 2:1 mismatched input 'bool' expecting {'boolean', 'int', 'void', '}'}
bool
^^^^
Antlr 4's parser error strategy is to drop tokens from the input until it can detect a sane state and then it continues parsing. Looking at your example, while trying to recover maybe it never reaches a sane state before EOF.
Seems like antlr can't recover if there are 2 contiguous error in the program. If the errors are not contiguous it works fine. Thank you very much for your help.
I need help turning off this feature if possible from the interactive mode or I'm going to go mad. The REPL insists on an equal sign before every expression if you want the value. I find this very irritating and unintuitive. To make matters worse, if you mistakenly forget the equal sign, it takes you to this secondary prompt which can only be exited by
typing an expression that'll cause an error.
*** str="This is some string"
*** str
>>
>>
>> =
>>
>> =str
stdin:6: unexpected symbol near '='
*** =str
This is some string
*** #str
stdin:1: unexpected symbol near '#'
*** =#str
19
***
*** 545+8
stdin:1: unexpected symbol near '545'
*** =545+8
553
***
I need a lesson in using the REPL:
Is there a way to get rid of the equal sign so that it behaves like other REPLs?
How do you exit from the secondary prompt without doing what I did?
Everything you enter in standalone Lua is treated as a statement, as opposed to an expression. The statements are evaluated, and their results, if any, are printed to the terminal. This is why you need to prepend = (really shorthand for return) to the expressions you gave as example to get them to display properly without error.
The "secondary prompt" you are seeing is what happens when you enter an incomplete statement.
In interactive mode, if you write an incomplete statement, the interpreter waits for its completion by issuing a different prompt.
You exit from it by completing the statement.
However, it's not too difficult to make your own REPL that does what you want. Of course, you lose the ability to progressively build statements from incomplete chunks this way, but maybe you don't need that.
local function print_results(...)
-- This function takes care of nils at the end of results and such.
if select('#', ...) > 1 then
print(select(2, ...))
end
end
repeat -- REPL
io.write'> '
io.stdout:flush()
local s = io.read()
if s == 'exit' then break end
local f, err = load(s, 'stdin')
if err then -- Maybe it's an expression.
-- This is a bad hack, but it might work well enough.
f = load('return (' .. s .. ')', 'stdin')
end
if f then
print_results(pcall(f))
else
print(err)
end
until false
Since Lua 5.3, you don't need the =, because Lua first tries to interpret it as an expression now.
From the reference manual:
In interactive mode, Lua repeatedly prompts and waits for a line. After reading a line, Lua first try to interpret the line as an expression. If it succeeds, it prints its value. Otherwise, it interprets the line as a statement. If you write an incomplete statement, the interpreter waits for its completion by issuing a different prompt.
A little test:
Lua 5.3.0 Copyright (C) 1994-2014 Lua.org, PUC-Rio
> str = 'hello' .. ' Lua'
> str
hello Lua
> 1 + 2
3
>
PEG-based parser generators usually provide limited error reporting on invalid inputs. From what I read, the parse dialect of rebol is inspired by PEG grammars extended with regular expressions.
For example, typing the following in JavaScript:
d8> function () {}
gives the following error, because no identifier was provided in declaring a global function:
(d8):1: SyntaxError: Unexpected token (
function () {}
^
The parser is able to pinpoint exactly the position during parsing where an expected token is missing. The character position of the expected token is used to position the arrow in the error message.
Does the parse dialect in rebol provides built-in facilities to report the line and column errors on invalid inputs?
Otherwise, are there examples out there of custom rolled out parse rules that provide such error reporting?
I've done very advanced Rebol parsers which manage live and mission-critical TCP servers, and doing proper error reporting was a requirement. So this is important!
Probably one of the most unique aspects of Rebol's PARSE is that you can include direct evaluation within the rules. So you can set variables to track the parse position, or the error messages, etc. (It's very easy because the nature of Rebol is that mixing code and data as the same thing is a core idea.)
So here's the way I did it. Before each match rule is attempted, I save the parse position into "here" (by writing here:) and then also save an error into a variable using code execution (by putting (error: {some error string}) in parentheses so that the parse dialect runs it). If the match rule succeeds, we don't need to use the error or position...and we just go on to the next rule. But if it fails we will have the last state we set to report after the failure.
Thus the pattern in the parse dialect is simply:
; use PARSE dialect handling of "set-word!" instances to save parse
; position into variable named "here"
here:
; escape out of the parse dialect using parentheses, and into the DO
; dialect to run arbitrary code. Here we run code that saves an error
; message string into a variable named "error"
(error: "<some error message relating to rule that follows>")
; back into the PARSE dialect again, express whatever your rule is,
; and if it fails then we will have the above to use in error reporting
what: (ever your) [rule | {is}]
That's basically what you need to do. Here is an example for phone numbers:
digit: charset "012345689"
phone-number-rule: [
here:
(error: "invalid area code")
["514" | "800" | "888" | "916" "877"]
here:
(error: "expecting dash")
"-"
here:
(error: "expecting 3 digits")
3 digit
here:
(error: "expecting dash")
"-"
here:
(error: "expecting 4 digits")
4 digit
(error: none)
]
Then you can see it in action. Notice that we set error to none if we reach the end of the parse rules. PARSE will return false if there is still more input to process, so if we notice there is no error set but PARSE returns false anyway... we failed because there was too much extra input:
input: "800-22r2-3333"
if not parse input phone-number-rule [
if none? error [
error: "too much data for phone number"
]
]
either error [
column: length? copy/part input here newline
print rejoin ["error at position:" space column]
print error
print input
print rejoin [head insert/dup "" space column "^^"}
print newline
][
print {all good}
]
The above will print the following:
error at position: 4
expecting 3 digits
800-22r2-3333
^
Obviously, you could do much more potent stuff, since whatever you put in parens will be evaluated just like normal Rebol source code. It's really flexible. I even have parsers which update progress bars while loading huge datasets... :-)
Here is a simple example of finding the position during parsing a string which could be used to do what you ask.
Let us say that our code is only valid if it contains a and b characters, anything else would be illegal input.
code-rule: [
some [
"a" |
"b"
]
[ end | mark: (print [ "Failed at position" index? mark ]) ]
]
Let's check that with some valid code
>> parse "aaaabbabb" code-rule
== true
Now we can try again with some invalid input
>> parse "aaaabbXabb" code-rule
Failed at position 7
== false
This is a rather simplified example language, but it should be easy to extend to more a complex example.