Skip to content

Convert to PGML: add the ability to parse loadMacros if the arguments are in a qw#1425

Open
pstaabp wants to merge 12 commits into
openwebwork:PG-2.21from
pstaabp:pgml-convert-improvements
Open

Convert to PGML: add the ability to parse loadMacros if the arguments are in a qw#1425
pstaabp wants to merge 12 commits into
openwebwork:PG-2.21from
pstaabp:pgml-convert-improvements

Conversation

@pstaabp

@pstaabp pstaabp commented May 28, 2026

Copy link
Copy Markdown
Member

Add the ability to parse loadMacros if the arguments are in a qw block. Also, removes empty macros and duplicate macros.

In addition, if it appears that the problem is already in PGML mode, then return the file without changes.

This is in response to openwebwork/webwork2#2908

@pstaabp pstaabp changed the title Add the ability to parse loadMacros if the arguments are in a qw Convert to PGML: add the ability to parse loadMacros if the arguments are in a qw May 29, 2026
Comment thread lib/WeBWorK/PG/ConvertToPGML.pm Outdated
@drgrice1

drgrice1 commented Jun 1, 2026

Copy link
Copy Markdown
Member

There are some outlier cases that are doing some weird things with this. These cases probably are not worth putting much effort into, but they could happen, and are valid Perl, and this turns them into invalid Perl.

Either loadMacros(qw{PGstandard.pl MathObjects.pl}, 'draggableProof.pl'); or loadMacros(qw{PGstandard.pl MathObjects.pl draggableProof.pl},); becomes

loadMacros(qw{
	PGstandard.pl
	PGML.pl
	draggableProof.pl
	PGcourse.pl
');

The second case is probably more of an issue, because that is probably not that unlikely.

Closely related and more serious though is the following. loadMacros(qw{PGstandard.pl MathObjects.pl draggableProof.pl} ); becomes

loadMacros(qw{
	PGstandard.pl
	PGML.pl
	draggableProof.pl}
	PGcourse.pl
 );

This needs to handle the possibility of white space between the qw ending and the ending parenthesis.

@pstaabp
pstaabp force-pushed the pgml-convert-improvements branch from 1db3b80 to ba081b2 Compare June 9, 2026 15:50
@pstaabp

pstaabp commented Jun 9, 2026

Copy link
Copy Markdown
Member Author

This addresses the cases of @drgrice1.

I also tried to format the output on a single line if the input was on a single line and multiple lines if the input was that way.

@drgrice1 drgrice1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still needs some more work.

Comment thread lib/WeBWorK/PG/ConvertToPGML.pm Outdated
Comment thread lib/WeBWorK/PG/ConvertToPGML.pm Outdated
Comment thread lib/WeBWorK/PG/ConvertToPGML.pm Outdated
Comment thread lib/WeBWorK/PG/ConvertToPGML.pm Outdated
@pstaabp
pstaabp force-pushed the pgml-convert-improvements branch from ba081b2 to d8f5572 Compare July 7, 2026 18:42
@pstaabp

pstaabp commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

This now checks for some parsing of the loadMacros call.

Additionally, this returns a hash for the output with any parsing errors. I will post a PR for WeBWorK to handle the errors in the PGeditor.

The command line works with no additional code.

@pstaabp

pstaabp commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

Note: there is now updated PGEditor code in openwebwork/webwork2#3046 that handles errors in the PG problem editor.

@drgrice1 drgrice1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something is definitely not working. The example given by @somiaj in issue #2908 doesn't even work. It gives the error PGML conversion errors: The loadMacros command cannot be parsed. In fact, every single file I have tested, regardless of any content that it has, gives that error unless PGML.pl happens to be on the same line as the loadMacros call.

The bin/convert-to-pgml.pl script is really poorly written. There should at the very least be a help option using pod2usage from Pod::Usage. If the script is called with no arguments which are required, then instead of dying with the message that arguments must have a list of files the help should be shown. Also, the SYNOPSIS section in the POD should be updated to show the usual help that is shown with the help option with the pod2usage method that shows the way the script should be called with all options described.

Also, the ConvertToPGML.pm module exports symbols by default. That shouldn't happen. @EXPORT_OK should be used instead of @EXPORT.

I must not have reviewed this well before when you first added this. Those things should not have been allowed.

Comment thread bin/convert-to-pgml.pl Outdated
Comment thread lib/WeBWorK/PG/ConvertToPGML.pm Outdated
# and there are no BEGIN_TEXT, BEGIN_SOLUTION, etc. blocks.

return { pgmlCode => $pg_source }
if ($pg_source =~ /loadMacros\((.*)PGML\.pl(.*)\)/m && $pg_source !~ /BEGIN_(TEXT|HINT|SOLUTION)/);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This extremely naive regular expression check is just not going to work. First, since you do not include the s flag on the regular expression, the . character does not match newlines. So unless PGML.pl is literally on the same line as the loadMacros call, this check will not find it. So this will catch something like loadMacros( #PGML.pl) which it shouldn't, but it will not catch something like

loadMacros(qw{
    PGstandard.pl
    PGML.pl
});

Note that just adding the s flag won't fix this either because then it would still catch the false positive noted above, but would also catch something like

loadMacros('PGstandard.pl');
# (This does not use PGML.pl)

In addition, the second regular expression check will also catch many incorrect things.  For example, if someone mentions `BEGIN_TEXT` in a comment in the file, but does not use it.

@pstaabp pstaabp Jul 13, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had noticed this a few days ago too. I think changing to the /s on the RegEx and then

$pg_source =~ /loadMacros\((.*)PGML\.pl(.*)\)\s*;/s

parses your first example correctly, but not the 2nd one.

I do see that putting BEGIN_TEXT comment will catch it incorrectly. Would

$pg_source !~ /^\s*BEGIN_(TEXT|HINT|SOLUTION)/ms

be sufficient?

My hope was to catch most of the cases that have already been converted.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You will need $pg_source !~ /^\s*BEGIN_(TEXT|HINT|SOLUTION)/m. Remove the s flag for this one. Then this will be pretty much what the translator uses. Note that the s flag makes . match a new line, so the ^ anchor would be nullified if the s flag is added.

The loadMacros check is more complicated. As I said, adding the s flag is not going to be enough. I am not sure what to do for this.

@pstaabp

pstaabp commented Jul 14, 2026

Copy link
Copy Markdown
Member Author

New version of this.

  • Added better documentation of the convert-to-pgml script.
  • Separated the loadMacros to a separate subroutine and perform error handling in the subroutine to better capture possible syntax errors.
  • Also, add a better way to parse the answer blanks in PGML form.

@drgrice1

Copy link
Copy Markdown
Member

This is still not working. Testing with the source

DOCUMENT();

loadMacros(    # PGML.pl)
    qw{
        PGstandard.pl
        MathObjects.pl
        parserPopUp.pl
        PGcourse.pl
    }
);
# (This file does not use PGML.pl.)

$mc = DropDown([ '1.5', '2 ', 3 ], 2);    # Correct answer is 3

BEGIN_TEXT
Problem text.
\{ $mc->ans_rule \}
END_TEXT

ANS($mc->cmp);

ENDDOCUMENT();

gives

DOCUMENT();

loadMacros('PGstandard.pl', 'PGML.pl', 'PGcourse.pl');

# (This file does not use PGML.pl.)

$mc = DropDown([ '1.5', '2 ', 3 ], 2);    # Correct answer is 3

BEGIN_PGML
Problem text.
[_]{$mc}
END_PGML

# ANS($mc->cmp);

ENDDOCUMENT();

It removes the parserPopUp.pl macro.

@pstaabp

pstaabp commented Jul 14, 2026

Copy link
Copy Markdown
Member Author

The newline between the loadMacros( and the qw{ was a problem. Just pushed another fix.

pstaabp added 6 commits July 14, 2026 15:14
block.  Also, removes empty macros and duplicate macros.

In addition, if it appears that the problem is already in PGML mode,
then return the file without changes.
Also, return a hash of the converted code and any errors.
Add better documentation of the convert-to-pgml script.

Separate the loadMacros to a separate subroutine and perform error handling in the subroutine to better capture possible syntax errors.

Also, add a better way to parse the answer blanks in PGML form.
@pstaabp
pstaabp force-pushed the pgml-convert-improvements branch from 245ac50 to 3b91a3d Compare July 14, 2026 19:15
pstaabp added 6 commits July 16, 2026 12:25
block.  Also, removes empty macros and duplicate macros.

In addition, if it appears that the problem is already in PGML mode,
then return the file without changes.
Also, return a hash of the converted code and any errors.
Add better documentation of the convert-to-pgml script.

Separate the loadMacros to a separate subroutine and perform error handling in the subroutine to better capture possible syntax errors.

Also, add a better way to parse the answer blanks in PGML form.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants