I am getting the error in this code:
$pattern="{[^}]*}";
$this->output = preg_replace($pattern, "", $this->output);
You need to escape the curly bracket:
$pattern="{[^\}]*}";
If your delimiters are { and }.
But I think you miss the regular expression delimiter:
$pattern="/\{[^\}]*\}/";
Related
concatenation in do doesn't work
Can any one explain why
this code work:
do 'begin perform 2; end;';
better say doesn't generate errors
and that:
do 'begin perform '||'2'||'; end;';
generate
ERROR: syntax error at or near "||"
LINE 1: do 'begin perform '||'2'||'; end;';
The argument to DO has to be a string literal.
From the manual:
Parameters (...) code (...) This must be specified as a string literal (...)
An expression concatenating strings isn't a literal.
How to parse single quoted string using Marpa:r2?
In my below code, the single quoted strings appends '\' on parsing.
Code:
use strict;
use Marpa::R2;
use Data::Dumper;
my $grammar = Marpa::R2::Scanless::G->new(
{ default_action => '[values]',
source => \(<<'END_OF_SOURCE'),
lexeme default = latm => 1
:start ::= Expression
# include begin
Expression ::= Param
Param ::= Unquoted
| ('"') Quoted ('"')
| (') Quoted (')
:discard ~ whitespace
whitespace ~ [\s]+
Unquoted ~ [^\s\/\(\),&:\"~]+
Quoted ~ [^\s&:\"~]+
END_OF_SOURCE
});
my $input1 = 'foo';
#my $input2 = '"foo"';
#my $input3 = '\'foo\'';
my $recce = Marpa::R2::Scanless::R->new({ grammar => $grammar });
print "Trying to parse:\n$input1\n\n";
$recce->read(\$input1);
my $value_ref = ${$recce->value};
print "Output:\n".Dumper($value_ref);
Output's:
Trying to parse:
foo
Output:
$VAR1 = [
[
'foo'
]
];
Trying to parse:
"foo"
Output:
$VAR1 = [
[
'foo'
]
];
Trying to parse:
'foo'
Output:
$VAR1 = [
[
'\'foo\''
]
]; (don't want it to be parsed like this)
Above are the outputs of all the inputs, i don't want 3rd one to get appended with the '\' and single quotes.. I want it to be parsed like OUTPUT2. Please advise.
Ideally, it should just pick the content between single quotes according to Param ::= (') Quoted (')
The other answer regarding Data::Dumper output is correct. However, your grammar does not work the way you expect it to.
When you parse the input 'foo', Marpa will consider the three Param alternatives. The predicted lexemes at that position are:
Unquoted ~ [^\s\/\(\),&:\"~]+
'"'
') Quoted ('
Yes, the last is literally ) Quoted (, not anything containing a single quote.
Even if it were ([']) Quoted ([']): Due to longest token matching, the Unquoted lexeme will match the entire input, including the single quote.
What would happen for an input like " foo " (with double quotes)? Now, only the '"' lexeme would match, then any whitespace would be discarded, then the Quoted lexeme matches, then any whitespace is discarded, then closing " is matched.
To prevent this whitespace-skipping behaviour and to prevent the Unquoted rule from being preferred due to LATM, it makes sense to describe quoted strings as lexemes. For example:
Param ::= Unquoted | Quoted
Unquoted ~ [^'"]+
Quoted ~ DQ | SQ
DQ ~ '"' DQ_Body '"' DQ_Body ~ [^"]*
SQ ~ ['] SQ_Body ['] SQ_Body ~ [^']*
These lexemes will then include any quotes and escapes, so you need to post-process the lexeme contents. You can either do this using the event system (which is conceptually clean, but a bit cumbersome to implement), or adding an action that performs this processing during parse evaluation.
Since lexemes cannot have actions, it is usually best to add a proxy production:
Param ::= Unquoted | Quoted
Unquoted ~ [^'"]+
Quoted ::= Quoted_Lexeme action => process_quoted
Quoted_Lexeme ~ DQ | SQ
DQ ~ '"' DQ_Body '"' DQ_Body ~ [^"]*
SQ ~ ['] SQ_Body ['] SQ_Body ~ [^']*
The action could then do something like:
sub process_quoted {
my (undef, $s) = #_;
# remove delimiters from double-quoted string
return $1 if $s =~ /^"(.*)"$/s;
# remove delimiters from single-quoted string
return $1 if $s =~ /^'(.*)'$/s;
die "String was not delimited with single or double quotes";
}
Your result doesn't contain \', it contains '. Dumper merely formats the result like that so it's clear what's inside the string and what isn't.
You can test this behavior for yourself:
use Data::Dumper;
my $tick = chr(39);
my $back = chr(92);
print "Tick Dumper: " . Dumper($tick);
print "Tick Print: " . $tick . "\n";
print "Backslash Dumper: " . Dumper($back);
print "Backslash Print: " . $back . "\n";
You can see a demo here: https://ideone.com/d1V8OE
If you don't want the output to contain single quotes, you'll probably need to remove them from the input yourself.
I am not so familar with Marpa::R2, but could you try to use an action on the Expression rule:
Expression ::= Param action => strip_quotes
Then, implement a simple quote stripper like:
sub MyActions::strip_quotes {
#{$_[1]}[0] =~ s/^'|'$//gr;
}
I have implemented a parser using Marpa::R2. Code appears like below:
I have a large number of test cases in a .t file, which i run to test my parser. So, if any exception arises in any of the input expression, testing shouldn't stop in mid and it should give proper error message for the one which has given an error (using exception handling) and rest of the test cases should run.
I want to do exception handling in this parser. If any sort of exception arrises even while tokenizing the input expression, I want to show appropriate message to the user, saying the position, string etc or any more details to show where the error came. Please help.
use strict;
use Marpa::R2;
use Data::Dumper;
my $grammar = Marpa::R2::Scanless::G->new({
default_action => '[values]',
source => \(<<'END_OF_SOURCE'),
lexeme default = latm => 1
:start ::= expression
expression ::= expression OP expression
expression ::= expression COMMA expression
expression ::= func LPAREN PARAM RPAREN
expression ::= PARAM
PARAM ::= STRING | REGEX_STRING
REGEX_STRING ::= '"' QUOTED_STRING '"'
:discard ~ sp
sp ~ [\s]+
COMMA ~ [,]
STRING ~ [^ \/\(\),&:\"~]+
QUOTED_STRING ~ [^ ,&:\"~]+
OP ~ ' - ' | '&'
LPAREN ~ '('
RPAREN ~ ')'
func ~ 'func'
END_OF_SOURCE
});
my $recce = Marpa::R2::Scanless::R->new({grammar => $grammar});
print "Trying to parse:\n$input\n\n";
$recce->read(\$input);
my $value_ref = ${$recce->value};
print "Output:\n".Dumper($value_ref);
my $input4 = "func(\"foo\")";
I want to do Proper error handling like :http://blogs.perl.org/users/jeffrey_kegler/2012/10/a-marpa-dsl-tutorial-error-reporting-made-easy.html
I dont know how to put all this stuff in place.
Wrap the lines that can fail in an exception handler:
use Try::Tiny;
â‹®
try {
$recce->read(\$input);
my $value_ref = ${$recce->value};
print "Output:\n".Dumper($value_ref);
} catch {
warn $_;
};
The full error message from Marpa will be in $_, it is a single long string with newlines in it. I chose to print it to STDOUT with warn, and the program continues to run. As you can see in an example error message below, it contains the position where the parsing failed:
Error in SLIF parse: No lexeme found at line 1, column 5
* String before error: "fo\s
* The error was at line 1, column 5, and at character 0x006f 'o', ...
* here: o"
Marpa::R2 exception at so49932329.pl line 41.
If you need to, you could reformat it so it looks better to the user.
As the title suggests how could I accomplish this?
I have been following a tutorial, but I get a syntax error:
Bareword found where operator expected at arrays_and_variables.pl line
26, near "$2names"
(Missing operator before names?) syntax error at
arrays_and_variables.pl line 26, near "$2names " Execution of
arrays_and_variables.pl aborted due to compilation errors.
The code I have so far is:
#names = ('james','dylan','max');
# join elements of array into a schalar variable.
$2names = join ('', #names);
print $s2names;
2names is an invalid variable name. Names can't start with a number—they have to begin with a letter or an underscore.
I am trying to implement macro replacement based on this discussion. Basically it works, but seems the ExpandString have some limitatoins:
main.ps1:
$foo = 'foo'
$text = [IO.File]::ReadAllText('in.config')
$ExecutionContext.InvokeCommand.ExpandString($text) | out-file 'out.config'
in.config (OK):
$foo
in.config (Error: "Encountered end of line while processing a string token."):
"
in.config (Error: "Missing ' at end of string."):
'
The documentation states:
Return Value: The expanded string
with all the variable and expression
substitutions done.
What is 'expression substitution' (may be this is my case)?
Is there some workaround?
The error is occurring because quotes (single and double) are special characters to the PowerShell runtime. They indicate a string and if they are to be used as just that character, they need to be escaped.
A possible workaround would be to escape quotes with a backtick, depending on your desired result.
For example if my text file had
'$foo'
The resulting expansion of that string would be
PS>$text = [io.file]::ReadAllText('test.config')
PS>$ExecutionContext.InvokeCommand.ExpandString($text)
$foo
If you wanted to have that variable expanded, you would need to escape those quotes.
`'$foo`'
PS>$text = [io.file]::ReadAllText('test.config')
PS>$ExecutionContext.InvokeCommand.ExpandString($text)
'foo'
or if you were going to have an unpaired single or double quote, you would need to escape it.
You could do a -replace on the string to escape those characters, but you'll have to make sure that is the desired effect across the board.
PS>$single, $double = "'", '"'
PS>$text = [io.file]::ReadAllText('test.config') -replace "($single|$double)", '`$1'
PS>$ExecutionContext.InvokeCommand.ExpandString($text)
NOTE: After you do the ExpandString call, you won't have the backticks hanging around anymore.