Printing Expected Token Type XXX when a parsing error occurs - ragel

I would like to be able to print this error message using Ragel
=> Parsing error found at position line:col, Integer expected instead.
Is that possible with Ragel?
Best regards

I haven't gotten too far into error handling in Ragel just yet, but I would expect that if you use the error action embedding operators as specified in section 3.2.3 of the Ragel 6.9 Guide, that would override the default message.
You can get the line number by incrementing a counter at each newline, and get the column by taking the current position and subtracting the position of the previous newline, something like this:
newline = '\n' %{ ++lineCounter; linePosition = p; }
action ErrorHandler {
column = p - linePosition + 1;
// Print error message here using lineCounter and column
}
main := (allsortsofstuff | newline)* <>err(ErrorHandler);
Of course, the above may require a bit of tweaking based on exactly what you're doing, but at least it's a starting point.

Related

How do I read a line of input from a user, until an EOF is hit, in GNU Prolog?

I have been reading the GNU Prolog documentation to figure out how to read a line of input until an end_of_file atom is reached. Here is my pseudocode for writing such a goal:
read_until_end(Chars, Out):
if peek_char unifies with end_of_file, Out = Chars
otherwise, get the current character, add it to a buffer, and keep reading
I implemented that like this:
read_until_end(Chars, Out) :-
peek_char(end_of_file) -> Out = Chars;
peek_char(C) -> read_until_end([C | Chars], Out).
prompt(Line) :-
write('> '),
read_until_end([], Line).
Here's what happens in the REPL:
| ?- prompt(Line).
> test
Fatal Error: global stack overflow (size: 32768 Kb, reached: 32765 Kb, environment variable used: GLOBALSZ)
If I print out C for the second branch of read_until_end, I can see that peek_char always gives me the same character, 'b'. I think that I need a way to progress some type of input character index or something like that, but I can't find a way to do so in the documentation. If I knew a way, I would probably have to use recursion to progress such a pointer, since I can't have any mutable state, but aside from that, I do not know what to do. Does anyone have any advice?
You are using peek_char/1 to get the next character, but that predicate does not consume the character from the stream (it just "peeks" the stream). Therefore an infinite recursion undergoes in your code that ends with a global stack overflow.
You should use get_char/1 to read and consume the character from the stream, and reverse/2 the list of collected chars:
read_until_end(Chars, Out) :-
get_char(Char),
(
Char = end_of_file -> reverse(Chars, Out)
;
read_until_end([Char | Chars], Out)
).
To avoid the need to reverse the list you may slightly modify your procedures to build the list in order (without using an accumulator):
read_until_end(Output) :-
get_char(Char),
(
Char = end_of_file -> Output=[]
;
(
Output=[Char|NOutput],
read_until_end(NOutput)
)
).
prompt(Line) :-
write('> '),
read_until_end(Line).

Erratic parser. Same grammar, same input, cycles through different results. What am I missing?

I'm writing a basic parser that reads form stdin and prints results to stdout. The problem is that I'm having troubles with this grammar:
%token WORD NUM TERM
%%
stmt: /* empty */
| word word term { printf("[stmt]\n"); }
| word number term { printf("[stmt]\n"); }
| word term
| number term
;
word: WORD { printf("[word]\n"); }
;
number: NUM { printf("[number]\n"); }
;
term: TERM { printf("[term]\n"); /* \n */}
;
%%
When I run the program, I and type: hello world\n The output is (as I expected) [word] [word] [term] [stmt]. So far, so good, but then if I type: hello world\n (again), I get syntax error [word][term].
When I type hello world\n (for the third time) it works, then it fails again, then it works, and so on and do forth.
Am I missing something obvious in here?
(I have some experience on hand rolled compilers, but I've not used lex/yacc et. al.)
This is the main func:
int main() {
do {
yyparse();
} while(!feof(yyin));
return 0;
}
Any help would be appreciated. Thanks!
Your grammar recognises a single stmt. Yacc/bison expect the grammar to describe the entire input, so after the statement is recognised, the parser waits for an end-of-input indication. But it doesn't get one, since you typed a second statement. That causes the parser to report a syntax error. But note that it has now read the first token in the second line.
You are calling yyparse() in a loop and not stopping when you get a syntax error return value. So when you call yyparse() again, it will continue where the last one left off, which is just before the second token in the second line. What remains is just a single word, which it then correctly parses.
What you probably should do is write your parser so that it accepts any number of statements, and perhaps so that it does not die when it hits an error. That would look something like this:
%%
prog: %empty
| prog line
line: stmt '\n' { puts("Got a statement"); }
| error '\n' { yyerrok; /* Simple error recovery */ }
...
Note that I print a message for a statement only after I know that the line was correctly parsed. That usually turns out to be less confusing. But the best solution is not use printf's, but rather to use Bison's trace facility, which is as simple as putting -t on the bison command line and setting the global variable yydebug = 1;. See Tracing your parser

Pharo: how to make Cmd+d ("do it") execute the whole multi-line statement by default instead of just the current line

Suppose I have a multi-line statement like this:
1 to: 5 do: [:i|
Transcript show: i.
Transcript cr].
Currently, when I put a text cursor on some line (without selecting anything) and press Cmd+d, Pharo tries to execute the current line. But it would be more convenient for me if by default (when nothing is selected) Pharo would execute the current statement (i.e. all this three-line statement), not just the current line. Because this is a much more frequent case ("I want to execute the whole statement") than "I want to execute this particular line inside a statement" (which in most cases just doesn't make sense syntactically, as 1st and 3rd lines here). And in these rear occasions (when I need to execute a line inside a statement) I would pre-select this line manually.
How can I achieve this?
To answer your question: Take a look at the text component. It has some method for evaluate-selection-and-do. And if nothing is selected, it tries to select the current line.
You may change this implementation to find the top most statement "scope".
It could be possible if you work with the code AST instead of the text. I worked once with this, to make it smarter for code expressions inside of comments.(that didn't work for all situations because the context for getting the method AST isn't always the same for this text component,in different tools (browser/workspace/and other))
Here is the idea for an algorithm. You will need to improve and complete it.
Define a class ExpressionFinder for finding the proper expression in your text.
In my sketch this class has the following ivars
string:
the complete string in your pane (playground/transcript/whatever)
compiler:
the compiler used by your pane to evaluate text
lines: the collection of associations pos->line, where pos is the position of the line inside string
index: current index to the lines collection used by the algorithm
interval: the output interval if any, otherwise nil
Assume you are given the string, the compiler and the current position of the cursor on string. Do the following:
string: aString position: anInteger compiler: aCompiler
string := aString.
compiler := aCompiler.
self computeLines.
index := lines findLast: [:assoc | assoc key <= anInteger]
Here is how you compute the collection of lines:
computeLines
| reader |
lines := OrderedCollection new.
reader := string readStream.
[reader atEnd]
whileFalse: [lines add: reader position + 1 -> reader nextLine]
With all of this you have everything you need to find the appropriate fragment. Here is a simple idea (which you should improve):
Start at the current line index and find the fragment by adding a line at a time. If found, end. If not, decrease the index and try again from the line above.
Here is the code
find
| i |
i := index.
[
i <= 0 ifTrue: [^self].
assoc := lines at: i.
self findFrom: assoc key]
whileFalse: [i := i - 1]
where
findFrom: start
| i end success |
i := index.
[| assoc fragment |
assoc := lines at: i + 1 ifAbsent: [string size + 1 -> nil].
end := assoc key - 1.
fragment := string copyFrom: start to: end.
success := self canCompile: fragment.
success not and: [end < string size]]
whileTrue: [i := i + 1].
success ifTrue: [interval := start to: end].
^success
The code for canCompile: fragment is dialect-dependent, on the lines of
canCompile: fragment
^(compiler compileExpression: fragment) notNil
If your compiler signals CompilationErrors, you will need to put a handler in canCompile: to avoid them. Also you might take advantage of such errors. For instance, if the compilation error refers to an undeclared variable, you know that you will not find its definition in the lines below, so you should exit the loop in findFrom: so to try with the line above and so on.

Parse error: syntax error, unexpected '"', expecting identifier (T_STRING) or variable (T_VARIABLE) or number (T_NUM_STRING) in C:... on line 22

I want to update a row in a table for my project, I'm copying a syntax I saw somewhere else here however, I think my problem comes when I try updating where ApplicantID is equal to $_SESSION["ID"].
I get this error
Parse error: syntax error, unexpected '"', expecting identifier (T_STRING) or variable (T_VARIABLE) or number (T_NUM_STRING) in C:\xampp\...\InsertPData.php on line 22
here is the php along side the SQL:
<?php
include_once'dbconnect.php';
session_start();
function INSERT()
{
$Name=$_POST['name'];
$Relation=$_POST['Relation'];
$Email=$_POST['Email'];
$Address=$_POST['Address'];
$Postcode=$_POST['Postcode'];
$Mobile_Number=$_POST['Mobile_Number'];
$Home_Number=$_POST['Home_Number'];
$INSERT="UPDATE Applicants
SET ParentName='$Name',
Relationtoapplicant='$Relation',
ParentEmail='$Email',
ParentAddress='$Address',
ParentPostcode='$Postcode',
ParentMobile='$Mobile_Number',
ParentHome='$Home_Number',
WHERE ApplicantID=$_SESSION["ID"] "; #THIS IS LINE 22
$data=mysql_query($INSERT) or die(mysql_error());
if($data)
{
echo "Parents/Gauridan details hav been entered";
}
else print "error";
}
INSERT()
?>
I've already searched for a solution to this but haven't found something where the user is using a session thing. Thank you.
This is why an IDE with syntax highlighting is helpful. StackOverflow uses syntax highlighting on code blocks as well and actually already gives you the answer based on your code:
$INSERT="UPDATE Applicants
WHERE ApplicantID=$_SESSION["ID"] ";
See how ID is suddenly black instead of dark red? That's because you are terminating the string there. The double quotes should either be escaped or replaced with single quotes, like:
$INSERT="UPDATE Applicants
WHERE ApplicantID=$_SESSION[\"ID\"] ";
Or
$INSERT="UPDATE Applicants
WHERE ApplicantID=$_SESSION['ID'] ";
See how the ID bit stays dark red? This is because now your string is not suddenly terminated.
Also, please do not use mysql_ functions anymore. They have been deprecated since 2013 and are currently not even a part of PHP anymore. So if you'd update your PHP to the latest version, this code would not work. On top of that, this code is vulnerable to SQL injection attacks.
Also see Why shouldn't I use mysql_* functions in PHP? and How can I prevent SQL-injection in PHP?.

Parsing an error string in Lua

Lets say I have the following error string:
err = "/mnt/cd4/autorun.lua:43: 'end' expected (to close 'while' at line 1)
near '-eof-'"
How would I parse the file path, line number, and the error message separately from the string?
I have no prior experience in parsing Lua strings, so I thought asking here would be useful. I also tried finding a topic solving the same matter but I could not find one.
Something like this should work:
err = "/mnt/cd4/autorun.lua:43: 'end' expected (to close 'while' at line 1) near '-eof-'"
local file, line, errmsg = err:match('^(.-):(%d+):(.+)')
print(file, line, errmsg)
The pattern says: capture starting at the end of the line (^) a shortest group of zero or more (-) of any symbol (.), followed by :, then a group of one or more digits (%d+), followed by :, and then a group of one of more symbols (.+). You can read about patterns here.