Quantcast

Matching a set of rules only once (in Java)

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

Matching a set of rules only once (in Java)

fge
Hello list,

I am writing a CSS grammar using parboiled, and have a difficulty...

For the "font" keyword, for instance, you can specify size, family, etc etc. Let's call these rules r1, r2, r3, ... rn. To complicate matters, some of them are compulsory. We suppose here that the rules are disjoint, so for any x and y, it is guaranteed that rx will not match what ry matches, and vice versa. And a rule cannot be matched more than once.

The way I'd like to solve the problem is to declare two sets of rules, "all" and "compulsory", the first containing all rules, the other containing only the compulsory rules:

* when a rule is matched, if "all" does not contain it, failure; otherwise remove it from "all";
* when the input is consumed, check that "compulsory.removeAll(all)" returns false.

But I don't know how to achieve this: it would need to store the sets in the parsing context somehow, I just can't figure out how even after reading the Javadoc (and examples) for quite some time... And I'm not that fluent with Java either. My experiments all failed, causing various exceptions etc...

Do you have a solution for this? Meanwhile, I'll continue searching...
fge
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Matching a set of rules only once (in Java)

fge

Well, answer to self again... I have a solution which works. The question is, will it always work? Advice wanted...

Next step is to generalize it!

// Note: Expression is an abstract class of mine which just defines "protected abstract Rule Expression();"
// and extends BaseParser
public class RuleSet
    extends Expression
{
    protected final List rules = new ArrayList();
    protected final Set used = new HashSet();
    protected final Set compulsory = new HashSet();

    public RuleSet()
    {
        rules.add(Rule1());
        rules.add(Rule2());
        compulsory.add(Rule1());
    }

    Rule Rule1()
    {
        return String("1");
    }

    Rule Rule2()
    {
        return String("2");
    }

    Rule buildRule()
    {
        // The trick is in the ACTION(): the Set's .add() method returns false if the element is already there
        // What I am afraid of is, can parboiled change the reference beyond me?
        final List l = new ArrayList();
        for (final Rule rule: rules)
            l.add(Sequence(rule, ACTION(used.add(rule))));

        return FirstOf(l.toArray());
    }

     Action beforeRun()
    {
        return new Action()
        {
            @Override
            public boolean run(final Context context)
            {
                used.clear();
                return true;
            }
        };
    }

     Action finalCheck()
    {
        return new Action()
        {
            @Override
            public boolean run(final Context context)
            {
                return used.containsAll(compulsory);
            }
        };
    }

    @Override
    public Rule Expression()
    {
        return Sequence(beforeRun(), OneOrMore(buildRule()), finalCheck());
    }
}



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

Re: Matching a set of rules only once (in Java)

macdonald.rich
I would create a special Java "builder" class, push it to the Context
when the <font> rule is started, and pop it when the <font> rule is
ended. All of the size, family, etc, rules would peek that Object,
check for duplication (not more than once), then add their result to
that object. When this class is finally popped, examine it to check
whether all the compulsory child rules have been encountered and
added. If everything checks out, return that the <font> rule
succeeded. Otherwise return false (it wasn't a <font>), or exit
entirely because a <font> was encountered and it had an error

On Sat, Dec 31, 2011 at 10:54 AM, fge [via parboiled users]
<[hidden email]> wrote:
> Well, answer to self again... I have a solution which works. The question
> is, will it always work? Advice wanted...
>
> Next step is to generalize it!
>
> // Note: Expression is an abstract class of mine which just defines
> "protected abstract Rule Expression();"
> // and extends BaseParser
fge
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Matching a set of rules only once (in Java)

fge
macdonald.rich wrote
I would create a special Java "builder" class, push it to the Context
when the  rule is started, and pop it when the  rule is
ended. All of the size, family, etc, rules would peek that Object,
check for duplication (not more than once), then add their result to
that object. When this class is finally popped, examine it to check
whether all the compulsory child rules have been encountered and
added. If everything checks out, return that the  rule
succeeded. Otherwise return false (it wasn't a ), or exit
entirely because a  was encountered and it had an error
Is there sample code somewhere to achieve this? There is no such thing that I can see in the examples... Maybe in one of the forks on github?
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Matching a set of rules only once (in Java)

macdonald.rich
I am afraid I am away from my code for a few days. However, look for
the "Value Stack" in the documentation. Also check the example code.
The "Calculators" in particular use the Stack, irc.

My solution IS a java solution. You're using parboiled to parse the
string and manage the stack/context, but the logic and validation
about is or is not allowed would be moved to this new object you have
to write.

The folllowing pseudo-code off the top of my head, so forgive any errors.

Rule Font(){
   return Sequence{
      push(new MyFontBuilder()),
      FontChildren(),
      ((MyFontBuilder)peek).validate()
  );
)
Rule FontChildren(){
   return OneOrMore{
      FontSize(),
      FontFamily(),
      ...etc...
  );
)
Rule FontSize(){
  MyFontBuilder fontBuilder = (MyFontBuilder) peek();
  ///here you need to process the contents to get the value of the size.
  int size = Integer.parse(match()); ///you'll need to do more here.
This isn't correct
 return fontBuilder.validateSize(size);
)

class MyFontBuilder {
   public Integer size;
   public boolean validateSize(int size){
      //check that we only do this once
      if (size != null){
          ///handle global exception because we set size twice
          return false;
      }
      this.size = size;
      return true;
   }
   public boolean validate(){
      //this is where construction is complete, so make sure
everything is correct
     return size != null & ...
}


On Sat, Dec 31, 2011 at 1:09 PM, fge [via parboiled users]
<[hidden email]> wrote:

> macdonald.rich wrote
> I would create a special Java "builder" class, push it to the Context
> when the  rule is started, and pop it when the  rule is
> ended. All of the size, family, etc, rules would peek that Object,
> check for duplication (not more than once), then add their result to
> that object. When this class is finally popped, examine it to check
> whether all the compulsory child rules have been encountered and
> added. If everything checks out, return that the  rule
> succeeded. Otherwise return false (it wasn't a ), or exit
> entirely because a  was encountered and it had an error
>
> Is there sample code somewhere to achieve this? There is no such thing that
> I can see in the examples... Maybe in one of the forks on github?
>
> ________________________________
> If you reply to this email, your message will be added to the discussion
> below:
> http://users.parboiled.org/Matching-a-set-of-rules-only-once-in-Java-tp3623090p3623722.html
> To start a new topic under parboiled users, email
> [hidden email]
> To unsubscribe from parboiled users, click here.
> NAML
fge
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Matching a set of rules only once (in Java)

fge
Well, I'll have a look at this code and try and understand how it works, since I have another problem: I need to find the longest match as well...

For instance, the font size property has "small" in it. But font-variant has "small-caps"... And I want font-variant to match :/
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Matching a set of rules only once (in Java)

mathias
Administrator
Gentlemen,

I'm sorry for my non-responsiveness, I'm on vacation and very offline until the 9th ...
Will try to support you as much as I can as soon as I'm back online.

Cheers and Happy New Year,
Mathias

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

On 01.01.2012, at 01:06, fge [via parboiled users] wrote:

> Well, I'll have a look at this code and try and understand how it works, since I have another problem: I need to find the longest match as well...
>
> For instance, the font size property has "small" in it. But font-variant has "small-caps"... And I want font-variant to match :/
>
>
> If you reply to this email, your message will be added to the discussion below:
> http://users.parboiled.org/Matching-a-set-of-rules-only-once-in-Java-tp3623090p3623846.html
> To start a new topic under parboiled users, email [hidden email]
> To unsubscribe from parboiled users, click here.
> NAML

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

Re: Matching a set of rules only once (in Java)

mathias
Administrator
In reply to this post by fge
I think the key here is again to not try to do everything in the parser layer!
The parser has the responsibility to translate syntax into some kind of higher-level structure (like an AST) that is then processed further by another application layer.

So, in your example you should accept syntactically correct CSS, like:

        font: bold bold 15px 15px;

and then fail in the semantic validation check later on...

If you take a look at this CSS grammar here: http://www.w3.org/TR/CSS2/grammar.html
you'll see that, on the syntactic level, the parser doesn't even know about things like a "font" property.

When building a CSS parser in parboiled I'd probably go for a one-to-one translation of this CSS grammar... nothing more.

Cheers,
Mathias

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

On 31.12.2011, at 13:29, fge [via parboiled users] wrote:

> Hello list,
>
> I am writing a CSS grammar using parboiled, and have a difficulty...
>
> For the "font" keyword, for instance, you can specify size, family, etc etc. Let's call these rules r1, r2, r3, ... rn. To complicate matters, some of them are compulsory. We suppose here that the rules are disjoint, so for any x and y, it is guaranteed that rx will not match what ry matches, and vice versa. And a rule cannot be matched more than once.
>
> The way I'd like to solve the problem is to declare two sets of rules, "all" and "compulsory", the first containing all rules, the other containing only the compulsory rules:
>
> * when a rule is matched, if "all" does not contain it, failure; otherwise remove it from "all";
> * when the input is consumed, check that "compulsory.removeAll(all)" returns false.
>
> But I don't know how to achieve this: it would need to store the sets in the parsing context somehow, I just can't figure out how even after reading the Javadoc (and examples) for quite some time... And I'm not that fluent with Java either. My experiments all failed, causing various exceptions etc...
>
> Do you have a solution for this? Meanwhile, I'll continue searching...
>
>
> If you reply to this email, your message will be added to the discussion below:
> http://users.parboiled.org/Matching-a-set-of-rules-only-once-in-Java-tp3623090p3623090.html
> To start a new topic under parboiled users, email [hidden email]
> To unsubscribe from parboiled users, click here.
> NAML

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

Re: Matching a set of rules only once (in Java)

fge
On Tue, Jan 24, 2012 at 10:51, mathias [via parboiled users]
<[hidden email]> wrote:

> I think the key here is again to not try to do everything in the parser
> layer!
> The parser has the responsibility to translate syntax into some kind of
> higher-level structure (like an AST) that is then processed further by
> another application layer.
>
> So, in your example you should accept syntactically correct CSS, like:
>
>         font: bold bold 15px 15px;
>
> and then fail in the semantic validation check later on...
>
> If you take a look at this CSS grammar here:
> http://www.w3.org/TR/CSS2/grammar.html
> you'll see that, on the syntactic level, the parser doesn't even know about
> things like a "font" property.
>
> When building a CSS parser in parboiled I'd probably go for a one-to-one
> translation of this CSS grammar... nothing more.
>

That would mean creating objects and filling them while parsing the
tree... Which I just don't know how to do. I need to learn.

How would you go, for example, about injecting (overly simplified example):

p {
    font: arial bold
}

into a class like:

public class Foo {
    private String selector;
    private Map<String,String> decls;
    // constructor/getters/setters/etc
}

?

Help appreciated, I cannot make sense of the Calculator examples at all...

--
Francis Galiegue, [hidden email]
"It seems obvious [...] that at least some 'business intelligence'
tools invest so much intelligence on the business side that they have
nothing left for generating SQL queries" (Stéphane Faroult, in "The
Art of SQL", ISBN 0-596-00894-5)
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Matching a set of rules only once (in Java)

mathias
Administrator
Francis,
have you read the documentation under parboiled.org ?
Especially (but not only) the "Concepts" chapters?

What exactly is it that you have trouble with?

Cheers,
Mathias

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

On 24.01.2012, at 11:06, fge [via parboiled users] wrote:

> On Tue, Jan 24, 2012 at 10:51, mathias [via parboiled users]
> <[hidden email]> wrote:
>
> > I think the key here is again to not try to do everything in the parser
> > layer!
> > The parser has the responsibility to translate syntax into some kind of
> > higher-level structure (like an AST) that is then processed further by
> > another application layer.
> >
> > So, in your example you should accept syntactically correct CSS, like:
> >
> >         font: bold bold 15px 15px;
> >
> > and then fail in the semantic validation check later on...
> >
> > If you take a look at this CSS grammar here:
> > http://www.w3.org/TR/CSS2/grammar.html
> > you'll see that, on the syntactic level, the parser doesn't even know about
> > things like a "font" property.
> >
> > When building a CSS parser in parboiled I'd probably go for a one-to-one
> > translation of this CSS grammar... nothing more.
> >
>
> That would mean creating objects and filling them while parsing the
> tree... Which I just don't know how to do. I need to learn.
>
> How would you go, for example, about injecting (overly simplified example):
>
> p {
>     font: arial bold
> }
>
> into a class like:
>
> public class Foo {
>     private String selector;
>     private Map<String,String> decls;
>     // constructor/getters/setters/etc
> }
>
> ?
>
> Help appreciated, I cannot make sense of the Calculator examples at all...
>
> --
> Francis Galiegue, [hidden email]
> "It seems obvious [...] that at least some 'business intelligence'
> tools invest so much intelligence on the business side that they have
> nothing left for generating SQL queries" (Stéphane Faroult, in "The
> Art of SQL", ISBN 0-596-00894-5)
>
>
> If you reply to this email, your message will be added to the discussion below:
> http://users.parboiled.org/Matching-a-set-of-rules-only-once-in-Java-tp3623090p3684205.html
> To start a new topic under parboiled users, email [hidden email]
> To unsubscribe from parboiled users, click here.
> NAML

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

Re: Matching a set of rules only once (in Java)

fge
On Tue, Jan 24, 2012 at 11:10, mathias [via parboiled users]
<[hidden email]> wrote:
> Francis,
> have you read the documentation under parboiled.org ?
> Especially (but not only) the "Concepts" chapters?
>
> What exactly is it that you have trouble with?
>

I didn't read all of it, I was probably too impatient to start ;)

I guess what I am really looking for is a tutorial... I can write
rules just fine, actions too, but more than that I have trouble with.

And hey, I can already validate pretty much all of CSS Zen Garden's
CSS files so that's a good start... It is "materializing" it into
objects which is the hard part for me.

--
Francis Galiegue, [hidden email]
"It seems obvious [...] that at least some 'business intelligence'
tools invest so much intelligence on the business side that they have
nothing left for generating SQL queries" (Stéphane Faroult, in "The
Art of SQL", ISBN 0-596-00894-5)
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Matching a set of rules only once (in Java)

tsuckow
> It is "materializing" it into objects which is the hard part for me.

I wouldn't think of it as "materializing." I think of it as calling a
constructor at the right time and then passing it to the constructor
of the appropriate parent in the tree.

I must also admit this is similar to Google Guice in how it injects
dependencies.  I started using it about a week ago and my first
reaction was that "magic happened."

I would link to my code and say we should learn together, but I am in
the middle of a MAJOR refactor of my parsing code. It is most
certainly not ready for using as an example of anything.

Best of luck ^_^

--
Thomas
Loading...