ACTION differs from manual action wrapping

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

ACTION differs from manual action wrapping

Sirat
Hi,

I've tried to extend the stack methods (parboiled for Java) and encountered the following problem: If I have a different class that uses the value stacks push()-Method and if this is called via explicit action expressions (ACTION), I get a "Unwrapped action expression"-Error. If I call the same method via an inner Action class, the program works.

Minimal example:

public class TestParser extends BaseParser {
       
        StackOperations stack = new StackOperations(this);
       
        Rule A() {
                return Sequence(
                        ACTION(stack.push("A")),
                        // WORKING ALTERNATIVE:
                        //new Action() {
                        // public boolean run(Context context) {
                        // return stack.push("A");
                        // }
                        //},
                        "GREETINGS"
                );
        }
               
        public static void main(String[] args) {
                TestParser parser = Parboiled.createParser(TestParser.class);
                new ReportingParseRunner(parser.A()).run("GREETINGS WORLD");
        }
       
}

class StackOperations {
       
        BaseParser parser;
               
        StackOperations(BaseParser parser) {
                this.parser = parser;
        }
       
        boolean push(Object node) {
                parser.push(node);
                return true;
        }
       
}

The problems seems only to occur, if the push-Method (or perhaps also other stack methods?) are called, and only if a different class is used in the call.
 
So I wonder, what's happening here?

  Finn
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: ACTION differs from manual action wrapping

mathias
Administrator
Hi Sirat,

thanks for your report.
This indeed looks strange.
You shouldn't actually need the "ACTION(...)" wrapper, since parboiled is usually able to figure out by itself that `stack.push("A")` is a parser action.

If I comment out the `parser.push(node); ` line in the StackOperations class everything works flawlessly.
Just uncommenting the line breaks action wrapping.
The stange thing is that the change happens in a class that is not actually looked at during parser extension (the StackOperations class)...

I will definitely have to look into this, I created a github issue (https://github.com/sirthias/parboiled/issues/21) to track it.

As work around just use delegation methods in the parser class itself.

Thanks again for the report!

Cheers,
Mathias

---
[hidden email]
http://www.parboiled.org

On 15.05.2011, at 12:56, Sirat [via parboiled users] wrote:

> Hi,
>
> I've tried to extend the stack methods (parboiled for Java) and encountered the following problem: If I have a different class that uses the value stacks push()-Method and if this is called via explicit action expressions (ACTION), I get a "Unwrapped action expression"-Error. If I call the same method via an inner Action class, the program works.
>
> Minimal example:
>
> public class TestParser extends BaseParser {
>        
>         StackOperations stack = new StackOperations(this);
>        
>         Rule A() {
>                 return Sequence(
>                         ACTION(stack.push("A")),
>                         // WORKING ALTERNATIVE:
>                         //new Action() {
>                         // public boolean run(Context context) {
>                         // return stack.push("A");
>                         // }
>                         //},
>                         "GREETINGS"
>                 );
>         }
>                
>         public static void main(String[] args) {
>                 TestParser parser = Parboiled.createParser(TestParser.class);
>                 new ReportingParseRunner(parser.A()).run("GREETINGS WORLD");
>         }
>        
> }
>
> class StackOperations {
>        
>         BaseParser parser;
>                
>         StackOperations(BaseParser parser) {
>                 this.parser = parser;
>         }
>        
>         boolean push(Object node) {
>                 parser.push(node);
>                 return true;
>         }
>        
> }
>
> The problems seems only to occur, if the push-Method (or perhaps also other stack methods?) are called, and only if a different class is used in the call.
>  
> So I wonder, what's happening here?
>
>   Finn
>
> If you reply to this email, your message will be added to the discussion below:
> http://users.parboiled.org/ACTION-differs-from-manual-action-wrapping-tp2943035p2943035.html
> To start a new topic under parboiled users, email [hidden email]
> To unsubscribe from parboiled users, click here.

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: ACTION differs from manual action wrapping

mathias
Administrator
In reply to this post by Sirat
Sirat,

after looking again at the stack trace it's now clear to me, where the problem is.
Action wrapping is working fine, the problem is something different:

The BaseParser.push method is nothing but a convenience wrapper.
This is its implementation:

    public boolean push(int down, V value) {
        check();
        context.getValueStack().push(down, value);
        return true;
    }

It just delegated to the the current contexts valuestack.
In order to be able to do this it needs to know what the current Context is.
As is explained here (https://github.com/sirthias/parboiled/wiki/Parser-Action-Expressions) the class containing parser action methods should implement the ContextAware interface to get a hold of the current Context.

If you fix your code as follows everything works fine:

static class Parser extends BaseParser<Object> {

        StackOperations stack = new StackOperations();

        Rule A() {
            return Sequence(
                    ACTION(stack.push("A")),
                    // WORKING ALTERNATIVE:
                    //new Action() {
                    // public boolean run(Context context) {
                    // return stack.push("A");
                    // }
                    //},
                    "GREETINGS"
            );
        }

    }

    static class StackOperations implements ContextAware<Object> {

        private Context<Object> context;

        @Override
        public void setContext(Context<Object> context) {

            this.context = context;
        }

        boolean push(Object node) {
            context.getValueStack().push(node);
            return true;
        }

    }

Cheers,
Mathias

---
[hidden email]
http://www.parboiled.org

On 15.05.2011, at 12:56, Sirat [via parboiled users] wrote:

> Hi,
>
> I've tried to extend the stack methods (parboiled for Java) and encountered the following problem: If I have a different class that uses the value stacks push()-Method and if this is called via explicit action expressions (ACTION), I get a "Unwrapped action expression"-Error. If I call the same method via an inner Action class, the program works.
>
> Minimal example:
>
> public class TestParser extends BaseParser {
>        
>         StackOperations stack = new StackOperations(this);
>        
>         Rule A() {
>                 return Sequence(
>                         ACTION(stack.push("A")),
>                         // WORKING ALTERNATIVE:
>                         //new Action() {
>                         // public boolean run(Context context) {
>                         // return stack.push("A");
>                         // }
>                         //},
>                         "GREETINGS"
>                 );
>         }
>                
>         public static void main(String[] args) {
>                 TestParser parser = Parboiled.createParser(TestParser.class);
>                 new ReportingParseRunner(parser.A()).run("GREETINGS WORLD");
>         }
>        
> }
>
> class StackOperations {
>        
>         BaseParser parser;
>                
>         StackOperations(BaseParser parser) {
>                 this.parser = parser;
>         }
>        
>         boolean push(Object node) {
>                 parser.push(node);
>                 return true;
>         }
>        
> }
>
> The problems seems only to occur, if the push-Method (or perhaps also other stack methods?) are called, and only if a different class is used in the call.
>  
> So I wonder, what's happening here?
>
>   Finn
>
> If you reply to this email, your message will be added to the discussion below:
> http://users.parboiled.org/ACTION-differs-from-manual-action-wrapping-tp2943035p2943035.html
> To start a new topic under parboiled users, email [hidden email]
> To unsubscribe from parboiled users, click here.

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: ACTION differs from manual action wrapping

Sirat
Mathias,

thanks for your rapid help. This works fine for me now.

  Finn
Loading...