I'm writing a program in lex, and it gives me the following error:
LexInput.l:12: unrecognized rule
Line 12 is: \"([^\042\134]|"\"(.|[\n]))*\" printf("string : %s\n", yytext);
Here's my code:
%{
#include <stdio.h>
%}
L [a-zA-Z]
D [0-9]
%%
{L}({L}|{D})* printf("id : %s\n", yytext);
[a-zA-Z_][a-zA-Z0-9_]* printf("C id : %s\n", yytext);
[+-]?[0-9]+ printf("integer : %s\n", yytext);
[0-9]+"."[0-9]+(e[+-]?[0-9]+)? printf("real : %s\n", yytext);
\"([^\042\134]|"\"(.|[\n]))*\" printf("string : %s\n", yytext);
"/*"([^*]|"*"+[^*)])*"*"+"/" printf("text comment : /* ... */\n");
"//".* printf("line comment : // ... \n");
"\n" |
. ;
%%
int yywrap()
{
return 1;
}
void main()
{
yylex();
}
The line in question has an unclosed double quote, although it is written in such an obfuscated manner that it is not at all obvious.
Here's the pattern from the line:
\"([^\042\134]|"\"(.|[\n]))*\"
What you meant to write was:
\"([^\042\134]|"\\"(.|[\n]))*\"
The way it was written, the quoted string starting just after the | was never closed, because the closing " was backslash-escaped. However, there is no need to enclose backslash-escaped characters in quotes, since they are already quoted by the backslash.
So here's a possibly more readable version:
["]([^"\\]|\\(.|\n))*["]
Inside [], quote characters are not special, which is why I prefer using ["] to represent a literal double-quote. Also, you can just write \n; there is no need to enclose it in any other punctuation.
Related
I am using this function.
Everything works fine but When i enter item title like : "Example - A digital product" it shows me in url slug example---a-digital-product..Here after word example there are 3 hiphen continuous. Please help to resolve it.
public function item_slug($string){
$slug=preg_replace(array('/[^A-Za-z0-9 -]+/','/[ -]+/'), array('',''),$string);
return $slug;
}
You could use a hyphen in the second replacement to replace 1 or more occurrences of a space or hyphen you match with [ -]+ with a single hyphen.
Example code:
function item_slug($string){
return preg_replace(array('/[^A-Za-z0-9 -]+/','/[ -]+/'), array('','-'),$string);
}
$strings = [
"example---a-digital-product..",
"Example - A digital product"
];
foreach ($strings as $str) {
echo item_slug($str) . PHP_EOL;
}
Output
example-a-digital-product
Example-A-digital-product
Php demo
Traditionally I can perfectly print this:
char str[] = "▄█▀█████";
printf(str);
However, under ncurses I cannot print this string neither with:
mvprintw(0, 0, str);
nor with:
mvaddwstr(0,0, L"▄█▀█████");
What's my mistake?
Whooh, this was quick... I already solved it; dear nowox:
You forgot to configure your locales:
#include <locale.h>
setlocale(LC_ALL, "");
I have a TCL proc like this, & want to add a line after the start of the proc, the puts "puts " entered myproc" " line
proc myproc { {filename "input.txt"}
{var1 "x"}
{var2 "y"}
{var3 "z"}
{var4 ""}
{var5 "0"}
{var6 "0"}
{var7 0}
} {
puts " entered myproc"
Can you help?
& it should also work for
proc myproc2 { N val } {
puts " entered myproc"
# comment line
set ret {} for { set i 0 } { $i < $N } { incr i } { lappend ret $val }
return $ret
}
If all you want to do is get an execution trace of your code, such as a call stack dump etc, then you don't need to modify your source code at all. You can use tcl itself to do it for you.
Tcl has no reserved keywords, none at all. Not even proc is reserved. You can therefore redefine it:
rename proc _proc
# Now proc no longer exists but we have _proc instead.
# Use it to redefine "proc":
_proc proc {name arguments body} {
set body "puts \"entered $name\";$body"
_proc $name $arguments $body
}
Just do that before running any of your own code and you'll find that every proc prints out when it's being entered on each call.
This is how a lot of tcl debuggers and profilers work - using tcl to redifine itself.
From your comments it looks like you're trying to also print how deep the stack is with each call. To do that you need to add more code to each proc definition. The most straightforward way is of course something like this:
_proc proc {name arguments body} {
set preamble"set dist2top \[info level\];puts \"\$dist2top entered $name\""
set body "$preamble;$body"
_proc $name $arguments $body
}
But as you can see, writing code inside strings can quickly become unmanagable. There are several tricks you can use to make it more manageable. One of the more common is to split $body by line and use list commands to manipulate code. It should reduce at least one level of quoting hell. My favorite is to use a templating technique similar to how you'd write html templates in MVC frameworks. I usually use string map for this:
_proc proc {name arguments body} {
_proc $name $arguments [string map [list %NAME% $name %BODY% $body] {
set dist2top [info level]
puts "$dist2top entered: %NAME%"
%BODY%
}]
}
The last argument in the _proc definition is just a string but it looks like a code block which makes it easier to read. No nasty quoting hell with this technique.
Using awk you can do:
awk '/^ *proc/ {$0 = $0 "\nputs \" entered myproc\""} 1' RS= proc-file.tcl
Gives this file:
proc myproc { {filename "input.txt"}
{var1 "x"}
{var2 "y"}
{var3 "z"}
{var4 ""}
{var5 "0"}
{var6 "0"}
{var7 0}
} {
puts " entered myproc"
Assuming that i need to tokenize and parse only multiline comments, how will i do that using Parse::Lex. When using flex-bison, the default action for any pattern in the rules section of the lex file used to be 'skip'.
%%
.* ;
%%
How to do this here ?
[EDIT] Well, i tried that, i'm still missing something - here is my code - and result. Where have i gone wrong ??
my simplified lex file:
use Parse::Lex;
use Regexp::Common;
use YParser;
my $lexer;
my #token = (
qw|esp:TA abcdefgh|,
qw(esp:REST .|\n),
);
Parse::Lex->trace;
Parse::Lex->exclusive('esp');
$lexer = Parse::Lex->new(#token);
$lexer->from(\*STDIN);
$lexer->skip(qr! [ \t]+ | $RE{balanced}{-begin=>'/*'}{-end=>'*/'} !xms);
$lexer->start('esp');
my $j = YParser->new();
$j->YYParse(yylex => \&lex);
sub lex {
my $token = $lexer->next;
return ('', undef) if $lexer->eoi;
if ($token->name eq 'TA' || $token->name eq 'REST') {
return ($token->name, {LINENO => $lexer->line, TEXT => $token->text});
}
}
my simplified grammar file
% token TA REST
%%
Program: Element
| Program Element
;
Element: TA
| REST
;
%%
Input file:
abcdefgh
/*sdf*/
Result:
perl lexfile.pl < inputfile
Trace is ON in class Parse::Lex
Can't call method "name" on an undefined value at qnlex.pl line 26, <STDIN> line 1.
Use the skip setting, shown here using Regexp::Common to help construct a regexp matching balanced pairs of comment delimiters. I've assumed /* */ as the comment delimiters, but they could be anything.
$lexer->skip(qr! [ \t]+ | $RE{balanced}{-begin=>'/*'}{-end=>'*/'} !xms);
The [ \t]+ alternative is left in place since that's the default.
Well, i figured this out :) Very simple - all i have to do is make the lex get the next token when encountering tokens i want to skip. Below is code to skip passing the token 'REST' to the parser.
sub lex {
my $token;
NEXTTOKEN:
$token = $lexer->next;
return ('', undef) if $lexer->eoi;
if ($token->name eq 'TA') {
return ($token->name, {LINENO => $lexer->line, TEXT => $token->text});
}
elsif ($token->name eq 'REST') {
goto NEXTTOKEN;
}
}
I have recently started programming in Perl (I'll skip the long story) but I've stumbled upon a few errors that I can't seem to understand:
syntax error at /usr/sbin/test.pl line 238, near ") {"
syntax error at /usr/sbin/test.pl line 247, near "} else"
syntax error at /usr/sbin/test.pl line 258, near ") {"
syntax error at /usr/sbin/test.pl line 276, near ") {"
syntax error at /usr/sbin/test.pl line 304, near "}"
syntax error at /usr/sbin/test.pl line 308, near "}"
syntax error at /usr/sbin/test.pl line 323, near "}"
it seems to be something to do with the brackets surrounding if and else
I'm experienced in C, C#, Java, PHP, Lua, and others so I'm a bit embaressed to get stuck on syntax errors..
I've pasted a sample of code that generates a syntax error:
if (substr(ToString($buffer),0,4) == 'HELO') {
$contype = 'smtp';
send($client,'250 Welcome',0);
} elsif (substr(ToString($buffer),0,4) == 'EHLO') {
$contype = 'esmtp';
send($client,'250-$hostname Welcome',0);
send($client,'250 SIZE $msgmaxsize',0);
}
do {
recv($client,$buffer,1024,0);
} while (ToString($buffer) != 'QUIT') {
if (substr(ToString($buffer),0,10) == 'MAIL FROM:')
{
$sender = ToString($buffer);
$sender =~ m/<(.*?)>/;
send($client,'250 OK',0);
} else {
send($client,'503 I was expecting MAIL FROM',0);
send($client,'221 Bye',0);
break;
}
}
unfortunately I can not show the entire program.
Perl version 5.10.1
This makes no sense:
...
do {
recv($client,$buffer,1024,0);
} while (ToString($buffer) != 'QUIT') {
if (substr(ToString($buffer),0,10) == 'MAIL FROM:')
...
You're combining a statement modifier (do {..} while...; with a while () {} loop. It's either or.
So write something like:
...
while ( recv($client,$buffer,1024,0) ) {
last if ToString($buffer) eq 'QUIT';
if (substr(ToString($buffer),0,10) eq 'MAIL FROM:') {
...
}
}
etc.
Besides the mistake of using == and != (which are number-comparison operators) instead of eq and ne for string comparisons, you are missing a semi-colon after the while's test. That is, you have
do { ...; } while (...) { if (...) { ... } else {...}}
Note that Perl, like C, supports both forms
while (expr) { stuff }
and
do { stuff } while (expr)
and I'm supposing you meant to use the latter form.
If the above accounts for the error at line 238, then it's possible that the error at line 247 might go away when you correct it, if it somehow causes a dangling else; but without compiling the code, I don't quite see how.