Changeset 4069 in josm


Ignore:
Timestamp:
2011-05-02T23:47:19+02:00 (14 years ago)
Author:
bastiK
Message:

mapcss: add role based selection (collaborative work by Gubaer and me)

Location:
trunk
Files:
9 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/mappaint/Environment.java

    r4011 r4069  
    22package org.openstreetmap.josm.gui.mappaint;
    33
    4 import java.util.Collection;
    5 import java.util.List;
    6 
    74import org.openstreetmap.josm.data.osm.OsmPrimitive;
    8 import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction;
     5import org.openstreetmap.josm.data.osm.Relation;
     6import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context;
     7import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.LinkSelector;
     8import org.openstreetmap.josm.tools.CheckParameterUtil;
    99
    1010public class Environment {
    1111
    1212    public OsmPrimitive osm;
     13
    1314    public MultiCascade mc;
    1415    public String layer;
    1516    public StyleSource source;
     17    private Context context = Context.PRIMITIVE;
    1618
    1719    /**
    18      * <p>When matching a child selector, the matching referrers will be stored.
    19      * They can be accessed in {@link Instruction#execute(Environment)} to access
    20      * tags from parent objects.</p>
     20     * If not null, this is the matching parent object if an condition or an expression
     21     * is evaluated in a {@link LinkSelector} (within a child selector)
    2122     */
    22     private List<OsmPrimitive> matchingReferrers = null;
     23    public OsmPrimitive parent;
     24    /**
     25     * The same for parent selector. Only one of the 2 fields (parent or child) is not null in any environment.
     26     */
     27    public OsmPrimitive child;
     28
     29    /**
     30     * index of node in parent way or member in parent relation. Must be != null in LINK context.
     31     */
     32    public Integer index = null;
     33
     34    /**
     35     * Creates a new uninitialized environment
     36     */
     37    public Environment() {}
    2338
    2439    public Environment(OsmPrimitive osm, MultiCascade mc, String layer, StyleSource source) {
     
    2944    }
    3045
    31     public Collection<OsmPrimitive> getMatchingReferrers() {
    32         return matchingReferrers;
     46    /**
     47     * Creates a clone of the environment {@code other}
     48     *
     49     * @param other the other environment. Must not be null.
     50     */
     51    public Environment(Environment other) throws IllegalArgumentException{
     52        CheckParameterUtil.ensureParameterNotNull(other);
     53        this.osm = other.osm;
     54        this.mc = other.mc;
     55        this.layer = other.layer;
     56        this.parent = other.parent;
     57        this.child = other.child;
     58        this.source = other.source;
     59        this.index = other.index;
     60        this.context = other.getContext();
    3361    }
    3462
    35     public void setMatchingReferrers(List<OsmPrimitive> refs) {
    36         matchingReferrers = refs;
     63    public Environment withPrimitive(OsmPrimitive osm) {
     64        Environment e = new Environment(this);
     65        e.osm = osm;
     66        return e;
    3767    }
    3868
    39     public void clearMatchingReferrers() {
    40         matchingReferrers = null;
     69    public Environment withParent(OsmPrimitive parent) {
     70        Environment e = new Environment(this);
     71        e.parent = parent;
     72        return e;
     73    }
     74
     75    public Environment withChild(OsmPrimitive child) {
     76        Environment e = new Environment(this);
     77        e.child = child;
     78        return e;
     79    }
     80
     81    public Environment withIndex(int index) {
     82        Environment e = new Environment(this);
     83        e.index = index;
     84        return e;
     85    }
     86
     87    public Environment withContext(Context context) {
     88        Environment e = new Environment(this);
     89        e.context = context == null ? Context.PRIMITIVE : context;
     90        return e;
     91    }
     92
     93    public Environment withLinkContext() {
     94        Environment e = new Environment(this);
     95        e.context = Context.LINK;
     96        return e;
     97    }
     98
     99    public boolean isLinkContext() {
     100        return Context.LINK.equals(context);
     101    }
     102
     103    public boolean hasParentRelation() {
     104        return parent != null && parent instanceof Relation;
     105    }
     106
     107    /**
     108     * Replies the current context.
     109     *
     110     * @return the current context
     111     */
     112    public Context getContext() {
     113        return context == null ? Context.PRIMITIVE : context;
     114    }
     115
     116    public String getRole() {
     117        if (getContext().equals(Context.PRIMITIVE))
     118            return null;
     119
     120        if (parent != null && parent instanceof Relation)
     121            return ((Relation) parent).getMember(index).getRole();
     122        if (child != null && osm instanceof Relation)
     123            return ((Relation) osm).getMember(index).getRole();
     124        return null;
     125    }
     126
     127    public void clearSelectorMatchingInformation() {
     128        parent = null;
     129        child = null;
     130        index = null;
    41131    }
    42132}
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java

    r3980 r4069  
    44import static org.openstreetmap.josm.tools.Utils.equal;
    55
     6import java.text.MessageFormat;
    67import java.util.EnumSet;
    78import java.util.regex.Matcher;
     
    1415import org.openstreetmap.josm.gui.mappaint.Cascade;
    1516import org.openstreetmap.josm.gui.mappaint.Environment;
    16 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Op;
     17import org.openstreetmap.josm.tools.Utils;
    1718
    1819abstract public class Condition {
     
    2021    abstract public boolean applies(Environment e);
    2122
    22     public static enum Op { EQ, NEQ, GREATER_OR_EQUAL, GREATER, LESS_OR_EQUAL, LESS,
    23         REGEX, ONE_OF, BEGINS_WITH, ENDS_WITH, CONTAINS }
     23    public static Condition create(String k, String v, Op op, Context context) {
     24        switch (context) {
     25        case PRIMITIVE:
     26            return new KeyValueCondition(k, v, op);
     27        case LINK:
     28            if ("role".equalsIgnoreCase(k))
     29                return new RoleCondition(v, op);
     30            else if ("index".equalsIgnoreCase(k))
     31                return new IndexCondition(v, op);
     32            else
     33                throw new MapCSSException(
     34                        MessageFormat.format("Expected key ''role'' or ''index'' in link context. Got ''{0}''.", k));
     35
     36        default: throw new AssertionError();
     37        }
     38    }
     39
     40    public static Condition create(String k, boolean not, boolean yes, Context context) {
     41        switch (context) {
     42        case PRIMITIVE:
     43            return new KeyCondition(k, not, yes);
     44        case LINK:
     45            if (yes)
     46                throw new MapCSSException("Question mark operator ''?'' not supported in LINK context");
     47            if (not)
     48                return new RoleCondition(k, Op.NEQ);
     49            else
     50                return new RoleCondition(k, Op.EQ);
     51
     52        default: throw new AssertionError();
     53        }
     54    }
     55
     56    public static Condition create(String id, boolean not, Context context) {
     57        return new PseudoClassCondition(id, not);
     58    }
     59
     60    public static Condition create(Expression e, Context context) {
     61        return new ExpressionCondition(e);
     62    }
     63
     64    public static enum Op {
     65        EQ, NEQ, GREATER_OR_EQUAL, GREATER, LESS_OR_EQUAL, LESS,
     66        REGEX, ONE_OF, BEGINS_WITH, ENDS_WITH, CONTAINS;
     67
     68        public boolean eval(String testString, String prototypeString) {
     69            if (testString == null && this != NEQ)
     70                return false;
     71            switch (this) {
     72            case EQ:
     73                return equal(testString, prototypeString);
     74            case NEQ:
     75                return !equal(testString, prototypeString);
     76            case REGEX:
     77                Pattern p = Pattern.compile(prototypeString);
     78                Matcher m = p.matcher(testString);
     79                return m.find();
     80            case ONE_OF:
     81                String[] parts = testString.split(";");
     82                for (String part : parts) {
     83                    if (equal(prototypeString, part.trim()))
     84                        return true;
     85                }
     86                return false;
     87            case BEGINS_WITH:
     88                return testString.startsWith(prototypeString);
     89            case ENDS_WITH:
     90                return testString.endsWith(prototypeString);
     91            case CONTAINS:
     92                return testString.contains(prototypeString);
     93            }
     94
     95            float test_float;
     96            try {
     97                test_float = Float.parseFloat(testString);
     98            } catch (NumberFormatException e) {
     99                return false;
     100            }
     101            float prototype_float = Float.parseFloat(prototypeString);
     102
     103            switch (this) {
     104            case GREATER_OR_EQUAL:
     105                return test_float >= prototype_float;
     106            case GREATER:
     107                return test_float > prototype_float;
     108            case LESS_OR_EQUAL:
     109                return test_float <= prototype_float;
     110            case LESS:
     111                return test_float < prototype_float;
     112            default:
     113                throw new AssertionError();
     114            }
     115        }
     116    }
     117
     118    /**
     119     * context, where the condition applies
     120     */
     121    public static enum Context {
     122        /**
     123         * normal primitive selector, e.g. way[highway=residential]
     124         */
     125        PRIMITIVE,
     126
     127        /**
     128         * link between primitives, e.g. relation >[role=outer] way
     129         */
     130        LINK
     131    }
    24132
    25133    public final static EnumSet<Op> COMPARISON_OPERATERS =
    26             EnumSet.of(Op.GREATER_OR_EQUAL, Op.GREATER, Op.LESS_OR_EQUAL, Op.LESS);
    27 
     134        EnumSet.of(Op.GREATER_OR_EQUAL, Op.GREATER, Op.LESS_OR_EQUAL, Op.LESS);
     135
     136    /**
     137     * <p>Represents a key/value condition which is either applied to a primitive.</p>
     138     *
     139     */
    28140    public static class KeyValueCondition extends Condition {
    29141
     
    31143        public String v;
    32144        public Op op;
    33         private float v_float;
    34 
     145
     146        /**
     147         * <p>Creates a key/value-condition.</p>
     148         *
     149         * @param k the key
     150         * @param v the value
     151         * @param op the operation
     152         */
    35153        public KeyValueCondition(String k, String v, Op op) {
    36154            this.k = k;
    37155            this.v = v;
    38156            this.op = op;
    39             if (COMPARISON_OPERATERS.contains(op)) {
    40                 v_float = Float.parseFloat(v);
    41             }
    42157        }
    43158
    44159        @Override
    45160        public boolean applies(Environment env) {
    46             String val = env.osm.get(k);
    47             if (val == null && op != Op.NEQ)
    48                 return false;
    49             switch (op) {
    50                 case EQ:
    51                     return equal(val, v);
    52                 case NEQ:
    53                     return !equal(val, v);
    54                 case REGEX:
    55                     Pattern p = Pattern.compile(v);
    56                     Matcher m = p.matcher(val);
    57                     return m.find();
    58                 case ONE_OF:
    59                     String[] parts = val.split(";");
    60                     for (String part : parts) {
    61                         if (equal(v, part.trim()))
    62                             return true;
    63                     }
    64                     return false;
    65                 case BEGINS_WITH:
    66                     return val.startsWith(v);
    67                 case ENDS_WITH:
    68                     return val.endsWith(v);
    69                 case CONTAINS:
    70                     return val.contains(v);
    71             }
    72             float val_float;
    73             try {
    74                 val_float = Float.parseFloat(val);
    75             } catch (NumberFormatException e) {
    76                 return false;
    77             }
    78             switch (op) {
    79                 case GREATER_OR_EQUAL:
    80                     return val_float >= v_float;
    81                 case GREATER:
    82                     return val_float > v_float;
    83                 case LESS_OR_EQUAL:
    84                     return val_float <= v_float;
    85                 case LESS:
    86                     return val_float < v_float;
    87                 default:
    88                     throw new AssertionError();
    89             }
     161            return op.eval(env.osm.get(k), v);
    90162        }
    91163
     
    96168    }
    97169
     170    public static class RoleCondition extends Condition {
     171        public String role;
     172        public Op op;
     173
     174        public RoleCondition(String role, Op op) {
     175            this.role = role;
     176            this.op = op;
     177        }
     178
     179        @Override
     180        public boolean applies(Environment env) {
     181            String testRole = env.getRole();
     182            if (testRole == null) return false;
     183            return op.eval(testRole, role);
     184        }
     185    }
     186
     187    public static class IndexCondition extends Condition {
     188        public String index;
     189        public Op op;
     190
     191        public IndexCondition(String index, Op op) {
     192            this.index = index;
     193            this.op = op;
     194        }
     195
     196        @Override
     197        public boolean applies(Environment env) {
     198            if (env.index == null) return false;
     199            return op.eval(Integer.toString(env.index + 1), index);
     200        }
     201    }
     202
     203    /**
     204     * <p>KeyCondition represent one of the following conditions in either the link or the
     205     * primitive context:</p>
     206     * <pre>
     207     *     ["a label"]  PRIMITIVE:   the primitive has a tag "a label"
     208     *                  LINK:        the parent is a relation and it has at least one member with the role
     209     *                               "a label" referring to the child
     210     *
     211     *     [!"a label"]  PRIMITIVE:  the primitive doesn't have a tag "a label"
     212     *                   LINK:       the parent is a relation but doesn't have a member with the role
     213     *                               "a label" referring to the child
     214     *
     215     *     ["a label"?]  PRIMITIVE:  the primitive has a tag "a label" whose value evaluates to a true-value
     216     *                   LINK:       not supported
     217     * </pre>
     218     */
    98219    public static class KeyCondition extends Condition {
    99220
    100         private String k;
    101         private boolean not;
    102         private boolean yes;
    103 
    104         public KeyCondition(String k, boolean not, boolean yes) {
    105             this.k = k;
    106             this.not = not;
    107             this.yes = yes;
     221        private String label;
     222        private boolean exclamationMarkPresent;
     223        private boolean questionMarkPresent;
     224
     225        /**
     226         *
     227         * @param label
     228         * @param exclamationMarkPresent
     229         * @param questionMarkPresent
     230         */
     231        public KeyCondition(String label, boolean exclamationMarkPresent, boolean questionMarkPresent){
     232            this.label = label;
     233            this.exclamationMarkPresent = exclamationMarkPresent;
     234            this.questionMarkPresent = questionMarkPresent;
    108235        }
    109236
    110237        @Override
    111238        public boolean applies(Environment e) {
    112             if (yes)
    113                 return OsmUtils.isTrue(e.osm.get(k)) ^ not;
    114             else
    115                 return e.osm.hasKey(k) ^ not;
     239            switch(e.getContext()) {
     240            case PRIMITIVE:
     241                if (questionMarkPresent)
     242                    return OsmUtils.isTrue(e.osm.get(label)) ^ exclamationMarkPresent;
     243                else
     244                    return e.osm.hasKey(label) ^ exclamationMarkPresent;
     245            case LINK:
     246                Utils.ensure(false, "Illegal state: KeyCondition not supported in LINK context");
     247                return false;
     248            default: throw new AssertionError();
     249            }
    116250        }
    117251
    118252        @Override
    119253        public String toString() {
    120             return "[" + (not ? "!" : "") + k + "]";
     254            return "[" + (exclamationMarkPresent ? "!" : "") + label + "]";
    121255        }
    122256    }
    123257
    124258    public static class PseudoClassCondition extends Condition {
    125        
     259
    126260        String id;
    127261        boolean not;
     
    144278                    return true;
    145279                return false;
    146             } else if (equal(id, "modified")) {
     280            } else if (equal(id, "modified"))
    147281                return e.osm.isModified() || e.osm.isNewOrUndeleted();
    148             } else if (equal(id, "new")) {
     282            else if (equal(id, "new"))
    149283                return e.osm.isNew();
    150             } else if (equal(id, "connection") && (e.osm instanceof Node)) {
     284            else if (equal(id, "connection") && (e.osm instanceof Node))
    151285                return ((Node) e.osm).isConnectionNode();
    152             } else if (equal(id, "tagged")) {
     286            else if (equal(id, "tagged"))
    153287                return e.osm.isTagged();
    154             }
    155288            return true;
    156289        }
     
    161294        }
    162295    }
    163    
     296
    164297    public static class ExpressionCondition extends Condition {
    165298
     
    181314        }
    182315    }
    183 
    184316}
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java

    r4011 r4069  
    174174
    175175            public String parent_tag(String key) {
    176                 if (env.getMatchingReferrers() == null) {
     176                if (env.parent == null) {
    177177                    // we don't have a matched parent, so just search all referrers
    178178                    for (OsmPrimitive parent : env.osm.getReferrers()) {
     
    183183                    return null;
    184184                }
    185                 if (env.getMatchingReferrers().isEmpty())
    186                     return null;
    187                 // use always the first matching referrer to have consistency
    188                 // in an expression and declaration block
    189                 return env.getMatchingReferrers().iterator().next().get(key);
     185                return env.parent.get(key);
    190186            }
    191187
    192188            public boolean has_tag_key(String key) {
    193189                return env.osm.hasKey(key);
     190            }
     191
     192            public Float index() {
     193                if (env.index == null)
     194                    return null;
     195                return new Float(env.index + 1);
     196            }
     197
     198            public String role() {
     199                return env.getRole();
    194200            }
    195201
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java

    r4011 r4069  
    55
    66import java.awt.Color;
     7import java.io.ByteArrayInputStream;
    78import java.io.IOException;
    89import java.io.InputStream;
     
    2425import org.openstreetmap.josm.gui.preferences.SourceEntry;
    2526import org.openstreetmap.josm.io.MirroredInputStream;
     27import org.openstreetmap.josm.tools.CheckParameterUtil;
    2628import org.openstreetmap.josm.tools.LanguageInfo;
    2729import org.openstreetmap.josm.tools.Utils;
     
    3234    final public List<MapCSSRule> rules;
    3335    private Color backgroundColorOverride;
     36    private String css = null;
    3437
    3538    public MapCSSStyleSource(String url, String name, String shortdescription) {
     
    4043    public MapCSSStyleSource(SourceEntry entry) {
    4144        super(entry);
     45        rules = new ArrayList<MapCSSRule>();
     46    }
     47
     48    /**
     49     * <p>Creates a new style source from the MapCSS styles supplied in
     50     * {@code css}</p>
     51     *
     52     * @param css the MapCSS style declaration. Must not be null.
     53     * @throws IllegalArgumentException thrown if {@code css} is null
     54     */
     55    public MapCSSStyleSource(String css) throws IllegalArgumentException{
     56        super(null, null, null);
     57        CheckParameterUtil.ensureParameterNotNull(css);
     58        this.css = css;
    4259        rules = new ArrayList<MapCSSRule>();
    4360    }
     
    6986    @Override
    7087    public InputStream getSourceInputStream() throws IOException {
     88        if (css != null)
     89            return new ByteArrayInputStream(css.getBytes("UTF-8"));
     90
    7191        MirroredInputStream in = new MirroredInputStream(url);
    7292        InputStream zip = in.getZipEntry("mapcss", "style");
     
    114134                if ((s instanceof GeneralSelector)) {
    115135                    GeneralSelector gs = (GeneralSelector) s;
    116                     if (gs.base.equals(type))
    117                      {
     136                    if (gs.base.equals(type)) {
    118137                        for (Condition cnd : gs.conds) {
    119138                            if (!cnd.applies(env))
     
    140159        for (MapCSSRule r : rules) {
    141160            for (Selector s : r.selectors) {
    142                 env.clearMatchingReferrers();
    143                 if (s.matches(env)) { // as side effect env.matchingReferrers will be set (if s is a child selector)
     161                env.clearSelectorMatchingInformation();
     162                if (s.matches(env)) { // as side effect env.parent will be set (if s is a child selector)
    144163                    if (s.getRange().contains(scale)) {
    145164                        mc.range = Range.cut(mc.range, s.getRange());
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java

    r4011 r4069  
    22package org.openstreetmap.josm.gui.mappaint.mapcss;
    33
    4 import java.util.ArrayList;
    54import java.util.List;
    65
     
    98import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    109import org.openstreetmap.josm.data.osm.Relation;
     10import org.openstreetmap.josm.data.osm.RelationMember;
    1111import org.openstreetmap.josm.data.osm.Way;
    1212import org.openstreetmap.josm.gui.mappaint.Environment;
     
    4646     */
    4747    public static class ChildOrParentSelector implements Selector {
    48         Selector a, b;
     48        //static private final Logger logger = Logger.getLogger(ChildOrParentSelector.class.getName());
     49        private final Selector left;
     50        private final LinkSelector link;
     51        private final Selector right;
    4952        /** true, if this represents a parent selector (otherwise it is a child selector)
    5053         */
     
    5760         * @param parentSelector if true, this is a parent selector; otherwise a child selector
    5861         */
    59         public ChildOrParentSelector(Selector a, Selector b, boolean parentSelector) {
    60             this.a = a;
    61             this.b = b;
     62        public ChildOrParentSelector(Selector a, LinkSelector link, Selector b, boolean parentSelector) {
     63            this.left = a;
     64            this.link = link;
     65            this.right = b;
    6266            this.parentSelector = parentSelector;
    6367        }
     
    6569        @Override
    6670        public boolean matches(Environment e) {
    67             if (!b.matches(e))
     71            if (!right.matches(e))
    6872                return false;
    6973
    70             Environment e2 = new Environment(null, e.mc, e.layer, e.source);
    71             List<OsmPrimitive> matchingRefs = new ArrayList<OsmPrimitive>();
    7274            if (!parentSelector) {
    7375                for (OsmPrimitive ref : e.osm.getReferrers()) {
    74                     e2.osm = ref;
    75                     if (a.matches(e2)) {
    76                         matchingRefs.add(ref);
     76                    if (!left.matches(e.withPrimitive(ref)))
     77                        continue;
     78                    if (ref instanceof Way) {
     79                        List<Node> wayNodes = ((Way) ref).getNodes();
     80                        for (int i=0; i<wayNodes.size(); i++) {
     81                            if (wayNodes.get(i).equals(e.osm)) {
     82                                if (link.matches(e.withParent(ref).withIndex(i).withLinkContext())) {
     83                                    e.parent = ref;
     84                                    e.index = i;
     85                                    return true;
     86                                }
     87                            }
     88                        }
     89                    } else if (ref instanceof Relation) {
     90                        List<RelationMember> members = ((Relation) ref).getMembers();
     91                        for (int i=0; i<members.size(); i++) {
     92                            RelationMember m = members.get(i);
     93                            if (m.getMember().equals(e.osm)) {
     94                                if (link.matches(e.withParent(ref).withIndex(i).withLinkContext())) {
     95                                    e.parent = ref;
     96                                    e.index = i;
     97                                    return true;
     98                                }
     99                            }
     100                        }
    77101                    }
    78102                }
    79                 if (!matchingRefs.isEmpty()) {
    80                     e.setMatchingReferrers(matchingRefs);
    81                     return true;
    82                 }
    83103            } else {
    84                 if (e.osm instanceof Relation) {
    85                     for (OsmPrimitive chld : ((Relation) e.osm).getMemberPrimitives()) {
    86                         e2.osm = chld;
    87                         if (a.matches(e2))
    88                             return true;
     104                if (e.osm instanceof Way) {
     105                    List<Node> wayNodes = ((Way) e.osm).getNodes();
     106                    for (int i=0; i<wayNodes.size(); i++) {
     107                        Node n = wayNodes.get(i);
     108                        if (left.matches(e.withPrimitive(n))) {
     109                            if (link.matches(e.withChild(n).withIndex(i).withLinkContext())) {
     110                                e.child = n;
     111                                e.index = i;
     112                                return true;
     113                            }
     114                        }
    89115                    }
    90                 } else if (e.osm instanceof Way) {
    91                     for (Node n : ((Way) e.osm).getNodes()) {
    92                         e2.osm = n;
    93                         if (a.matches(e2))
    94                             return true;
     116                }
     117                else if (e.osm instanceof Relation) {
     118                    List<RelationMember> members = ((Relation) e.osm).getMembers();
     119                    for (int i=0; i<members.size(); i++) {
     120                        OsmPrimitive member = members.get(i).getMember();
     121                        if (left.matches(e.withPrimitive(member))) {
     122                            if (link.matches(e.withChild(member).withIndex(i).withLinkContext())) {
     123                                e.child = member;
     124                                e.index = i;
     125                                return true;
     126                            }
     127                        }
    95128                    }
    96129                }
     
    101134        @Override
    102135        public String getSubpart() {
    103             return b.getSubpart();
     136            return right.getSubpart();
    104137        }
    105138
    106139        @Override
    107140        public Range getRange() {
    108             return b.getRange();
     141            return right.getRange();
     142        }
     143
     144        @Override
     145        public String toString() {
     146            return left +" "+ (parentSelector? "<" : ">")+link+" " +right;
     147        }
     148    }
     149
     150    public static class LinkSelector implements Selector {
     151        protected List<Condition> conditions;
     152
     153        public LinkSelector(List<Condition> conditions) {
     154            this.conditions = conditions;
     155        }
     156
     157        @Override
     158        public boolean matches(Environment env) {
     159            Utils.ensure(env.isLinkContext(), "Requires LINK context in environment, got ''{0}''", env.getContext());
     160            for (Condition c: conditions) {
     161                if (!c.applies(env)) return false;
     162            }
     163            return true;
     164        }
     165
     166        @Override
     167        public String getSubpart() {
     168            throw new UnsupportedOperationException("Not supported yet.");
     169        }
     170
     171        @Override
     172        public Range getRange() {
     173            throw new UnsupportedOperationException("Not supported yet.");
     174        }
     175
     176        @Override
     177        public String toString() {
     178            return "LinkSelector{" + "conditions=" + conditions + '}';
    109179        }
    110180    }
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.java

    r4011 r4069  
    88import org.openstreetmap.josm.gui.mappaint.Keyword;
    99import org.openstreetmap.josm.gui.mappaint.mapcss.Condition;
     10import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context;
    1011import org.openstreetmap.josm.gui.mappaint.mapcss.Expression;
    1112import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction;
     
    1516import org.openstreetmap.josm.gui.mappaint.mapcss.Expression.FunctionExpression;
    1617import org.openstreetmap.josm.gui.mappaint.mapcss.Expression.LiteralExpression;
     18import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSException;
    1719import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.ChildOrParentSelector;
    1820import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector;
     21import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.LinkSelector;
    1922import org.openstreetmap.josm.tools.Pair;
    2023
     
    237240      }
    238241      try {
    239         r = rule();
    240                        if (r != null) { sheet.rules.add(r); }
     242        /*            try {*/
     243                        r = rule();
     244                           if (r != null) { sheet.rules.add(r); }
    241245        w();
     246      } catch (MapCSSException mex) {
     247            error_skipto(RBRACE, mex);
     248            w();
     249/*                throw new ParseException(mex.getMessage());*/
     250/*            }*/
     251
    242252      } catch (ParseException ex) {
    243             error_skipto(RBRACE);
     253            error_skipto(RBRACE, null);
    244254            w();
    245255      }
     
    276286  final public Selector child_selector() throws ParseException {
    277287    boolean parentSelector = false;
    278     Selector sel1, sel2 = null;
    279     sel1 = selector();
     288    Condition c;
     289    List<Condition> conditions = new ArrayList<Condition>();
     290    Selector selLeft;
     291    LinkSelector selLink = null;
     292    Selector selRight = null;
     293    selLeft = selector();
    280294    w();
    281295    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     
    296310        throw new ParseException();
    297311      }
     312      label_5:
     313      while (true) {
     314        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     315        case LSQUARE:
     316        case EXCLAMATION:
     317        case COLON:
     318          ;
     319          break;
     320        default:
     321          jj_la1[11] = jj_gen;
     322          break label_5;
     323        }
     324        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     325        case LSQUARE:
     326          c = condition(Context.LINK);
     327          break;
     328        case EXCLAMATION:
     329        case COLON:
     330          c = pseudoclass(Context.LINK);
     331          break;
     332        default:
     333          jj_la1[12] = jj_gen;
     334          jj_consume_token(-1);
     335          throw new ParseException();
     336        }
     337                                                                        conditions.add(c);
     338      }
     339          selLink = new LinkSelector(conditions);
    298340      w();
    299       sel2 = selector();
     341      selRight = selector();
    300342      w();
    301343      break;
    302344    default:
    303       jj_la1[11] = jj_gen;
     345      jj_la1[13] = jj_gen;
    304346      ;
    305347    }
    306       {if (true) return sel2 != null ? new ChildOrParentSelector(sel1, sel2, parentSelector) : sel1;}
     348      {if (true) return selRight != null ? new ChildOrParentSelector(selLeft, selLink, selRight, parentSelector) : selLeft;}
    307349    throw new Error("Missing return statement in function");
    308350  }
     
    322364      break;
    323365    default:
    324       jj_la1[12] = jj_gen;
     366      jj_la1[14] = jj_gen;
    325367      jj_consume_token(-1);
    326368      throw new ParseException();
     
    331373      break;
    332374    default:
    333       jj_la1[13] = jj_gen;
     375      jj_la1[15] = jj_gen;
    334376      ;
    335377    }
    336     label_5:
     378    label_6:
    337379    while (true) {
    338380      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     
    343385        break;
    344386      default:
    345         jj_la1[14] = jj_gen;
    346         break label_5;
     387        jj_la1[16] = jj_gen;
     388        break label_6;
    347389      }
    348390      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    349391      case LSQUARE:
    350         c = condition();
     392        c = condition(Context.PRIMITIVE);
    351393        break;
    352394      case EXCLAMATION:
    353395      case COLON:
    354         c = pseudoclass();
     396        c = pseudoclass(Context.PRIMITIVE);
    355397        break;
    356398      default:
    357         jj_la1[15] = jj_gen;
     399        jj_la1[17] = jj_gen;
    358400        jj_consume_token(-1);
    359401        throw new ParseException();
    360402      }
    361                                             conditions.add(c);
     403                                                                              conditions.add(c);
    362404    }
    363405    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     
    366408      break;
    367409    default:
    368       jj_la1[16] = jj_gen;
     410      jj_la1[18] = jj_gen;
    369411      ;
    370412    }
     
    392434          break;
    393435        default:
    394           jj_la1[17] = jj_gen;
     436          jj_la1[19] = jj_gen;
    395437          ;
    396438        }
    397439        break;
    398440      default:
    399         jj_la1[18] = jj_gen;
     441        jj_la1[20] = jj_gen;
    400442        ;
    401443      }
    402444      break;
    403445    default:
    404       jj_la1[19] = jj_gen;
     446      jj_la1[21] = jj_gen;
    405447      jj_consume_token(-1);
    406448      throw new ParseException();
     
    410452  }
    411453
    412   final public Condition condition() throws ParseException {
     454  final public Condition condition(Context context) throws ParseException {
    413455    Condition c;
    414456    Expression e;
     
    416458    s();
    417459    if (jj_2_1(2147483647)) {
    418       c = simple_key_condition();
     460      c = simple_key_condition(context);
    419461      s();
    420462      jj_consume_token(RSQUARE);
    421                                                      {if (true) return c;}
     463                                                            {if (true) return c;}
    422464    } else if (jj_2_2(2147483647)) {
    423       c = simple_key_value_condition();
     465      c = simple_key_value_condition(context);
    424466      s();
    425467      jj_consume_token(RSQUARE);
    426                                                            {if (true) return c;}
     468                                                                  {if (true) return c;}
    427469    } else {
    428470      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     
    438480        e = expression();
    439481        jj_consume_token(RSQUARE);
    440                                        {if (true) return new Condition.ExpressionCondition(e);}
     482                                       {if (true) return Condition.create(e, context);}
    441483        break;
    442484      default:
    443         jj_la1[20] = jj_gen;
     485        jj_la1[22] = jj_gen;
    444486        jj_consume_token(-1);
    445487        throw new ParseException();
     
    460502      t = jj_consume_token(IDENT);
    461503                    s = t.image;
    462       label_6:
     504      label_7:
    463505      while (true) {
    464506        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     
    467509          break;
    468510        default:
    469           jj_la1[21] = jj_gen;
    470           break label_6;
     511          jj_la1[23] = jj_gen;
     512          break label_7;
    471513        }
    472514        jj_consume_token(COLON);
     
    477519      break;
    478520    default:
    479       jj_la1[22] = jj_gen;
     521      jj_la1[24] = jj_gen;
    480522      jj_consume_token(-1);
    481523      throw new ParseException();
     
    484526  }
    485527
    486   final public Condition simple_key_condition() throws ParseException {
     528  final public Condition simple_key_condition(Context context) throws ParseException {
    487529    boolean not = false;
    488530    boolean yes = false;
     
    494536      break;
    495537    default:
    496       jj_la1[23] = jj_gen;
     538      jj_la1[25] = jj_gen;
    497539      ;
    498540    }
     
    504546      break;
    505547    default:
    506       jj_la1[24] = jj_gen;
     548      jj_la1[26] = jj_gen;
    507549      ;
    508550    }
    509       {if (true) return new Condition.KeyCondition(key, not, yes);}
     551      {if (true) return Condition.create(key, not, yes, context);}
    510552    throw new Error("Missing return statement in function");
    511553  }
    512554
    513   final public Condition simple_key_value_condition() throws ParseException {
     555  final public Condition simple_key_value_condition(Context context) throws ParseException {
    514556    String key;
    515557    String val;
     
    564606          break;
    565607        default:
    566           jj_la1[25] = jj_gen;
     608          jj_la1[27] = jj_gen;
    567609          jj_consume_token(-1);
    568610          throw new ParseException();
     
    585627            break;
    586628          default:
    587             jj_la1[26] = jj_gen;
     629            jj_la1[28] = jj_gen;
    588630            jj_consume_token(-1);
    589631            throw new ParseException();
     
    613655          break;
    614656        default:
    615           jj_la1[27] = jj_gen;
     657          jj_la1[29] = jj_gen;
    616658          jj_consume_token(-1);
    617659          throw new ParseException();
     
    622664        break;
    623665      default:
    624         jj_la1[28] = jj_gen;
     666        jj_la1[30] = jj_gen;
    625667        jj_consume_token(-1);
    626668        throw new ParseException();
    627669      }
    628670    }
    629       {if (true) return new Condition.KeyValueCondition(key, val, op);}
     671      {if (true) return Condition.create(key, val, op, context);}
    630672    throw new Error("Missing return statement in function");
    631673  }
    632674
    633   final public Condition pseudoclass() throws ParseException {
     675  final public Condition pseudoclass(Context context) throws ParseException {
    634676    Token t;
    635677    boolean not = false;
     
    640682      break;
    641683    default:
    642       jj_la1[29] = jj_gen;
     684      jj_la1[31] = jj_gen;
    643685      ;
    644686    }
    645687    jj_consume_token(COLON);
    646688    t = jj_consume_token(IDENT);
    647       {if (true) return new Condition.PseudoClassCondition(t.image, not);}
     689      {if (true) return Condition.create(t.image, not, context);}
    648690    throw new Error("Missing return statement in function");
    649691  }
     
    660702      break;
    661703    default:
    662       jj_la1[30] = jj_gen;
     704      jj_la1[32] = jj_gen;
    663705      jj_consume_token(-1);
    664706      throw new ParseException();
     
    675717    jj_consume_token(LBRACE);
    676718    w();
    677     label_7:
     719    label_8:
    678720    while (true) {
    679721      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     
    682724        break;
    683725      default:
    684         jj_la1[31] = jj_gen;
    685         break label_7;
     726        jj_la1[33] = jj_gen;
     727        break label_8;
    686728      }
    687729      key = jj_consume_token(IDENT);
     
    703745          break;
    704746        default:
    705           jj_la1[32] = jj_gen;
     747          jj_la1[34] = jj_gen;
    706748          jj_consume_token(-1);
    707749          throw new ParseException();
     
    720762          break;
    721763        default:
    722           jj_la1[33] = jj_gen;
     764          jj_la1[35] = jj_gen;
    723765          jj_consume_token(-1);
    724766          throw new ParseException();
     
    781823        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    782824        case PLUS:
    783           label_8:
     825          label_9:
    784826          while (true) {
    785827            jj_consume_token(PLUS);
     
    794836              break;
    795837            default:
    796               jj_la1[34] = jj_gen;
    797               break label_8;
     838              jj_la1[36] = jj_gen;
     839              break label_9;
    798840            }
    799841          }
    800842          break;
    801843        case STAR:
    802           label_9:
     844          label_10:
    803845          while (true) {
    804846            jj_consume_token(STAR);
     
    813855              break;
    814856            default:
    815               jj_la1[35] = jj_gen;
    816               break label_9;
     857              jj_la1[37] = jj_gen;
     858              break label_10;
    817859            }
    818860          }
    819861          break;
    820862        case MINUS:
    821           label_10:
     863          label_11:
    822864          while (true) {
    823865            jj_consume_token(MINUS);
     
    832874              break;
    833875            default:
    834               jj_la1[36] = jj_gen;
    835               break label_10;
     876              jj_la1[38] = jj_gen;
     877              break label_11;
    836878            }
    837879          }
    838880          break;
    839881        case SLASH:
    840           label_11:
     882          label_12:
    841883          while (true) {
    842884            jj_consume_token(SLASH);
     
    851893              break;
    852894            default:
    853               jj_la1[37] = jj_gen;
    854               break label_11;
     895              jj_la1[39] = jj_gen;
     896              break label_12;
    855897            }
    856898          }
     
    887929            break;
    888930          default:
    889             jj_la1[38] = jj_gen;
     931            jj_la1[40] = jj_gen;
    890932            ;
    891933          }
     
    936978          break;
    937979        default:
    938           jj_la1[39] = jj_gen;
     980          jj_la1[41] = jj_gen;
    939981          jj_consume_token(-1);
    940982          throw new ParseException();
     
    942984        break;
    943985      default:
    944         jj_la1[40] = jj_gen;
     986        jj_la1[42] = jj_gen;
    945987        ;
    946988      }
    947989      break;
    948990    default:
    949       jj_la1[41] = jj_gen;
     991      jj_la1[43] = jj_gen;
    950992      jj_consume_token(-1);
    951993      throw new ParseException();
     
    9841026        break;
    9851027      default:
    986         jj_la1[42] = jj_gen;
     1028        jj_la1[44] = jj_gen;
    9871029        jj_consume_token(-1);
    9881030        throw new ParseException();
     
    10141056      arg = expression();
    10151057                           args.add(arg);
    1016       label_12:
     1058      label_13:
    10171059      while (true) {
    10181060        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     
    10211063          break;
    10221064        default:
    1023           jj_la1[43] = jj_gen;
    1024           break label_12;
     1065          jj_la1[45] = jj_gen;
     1066          break label_13;
    10251067        }
    10261068        jj_consume_token(COMMA);
     
    10311073      break;
    10321074    default:
    1033       jj_la1[44] = jj_gen;
     1075      jj_la1[46] = jj_gen;
    10341076      ;
    10351077    }
     
    10731115      break;
    10741116    default:
    1075       jj_la1[45] = jj_gen;
     1117      jj_la1[47] = jj_gen;
    10761118      jj_consume_token(-1);
    10771119      throw new ParseException();
     
    10801122  }
    10811123
    1082   void error_skipto(int kind) throws ParseException {
     1124  void error_skipto(int kind, MapCSSException me) throws ParseException {
    10831125    if (token.kind == EOF)
    10841126        throw new ParseException("Reached end of file while parsing");
    1085     ParseException e = generateParseException();
     1127
     1128    Exception e = null;
     1129    ParseException pe = generateParseException();
     1130
     1131    if (me != null) {
     1132        me.setLine(pe.currentToken.next.beginLine);
     1133        me.setColumn(pe.currentToken.next.beginColumn);
     1134        e = me;
     1135    } else {
     1136        e = new ParseException(pe.getMessage()); // prevent memory leak
     1137    }
     1138
    10861139    System.err.println("Skipping to the next rule, because of an error:");
    10871140    System.err.println(e);
    10881141    if (sheet != null) {
    1089         sheet.logError(new ParseException(e.getMessage()));
     1142        sheet.logError(e);
    10901143    }
    10911144    Token t;
     
    11711224  }
    11721225
    1173   private boolean jj_3R_41() {
    1174     if (jj_scan_token(CARET)) return true;
    1175     if (jj_scan_token(EQUAL)) return true;
    1176     return false;
    1177   }
    1178 
    1179   private boolean jj_3R_40() {
    1180     if (jj_scan_token(TILDE)) return true;
    1181     if (jj_scan_token(EQUAL)) return true;
    1182     return false;
    1183   }
    1184 
    1185   private boolean jj_3R_14() {
     1226  private boolean jj_3R_25() {
     1227    Token xsp;
     1228    xsp = jj_scanpos;
     1229    if (jj_3R_39()) {
     1230    jj_scanpos = xsp;
     1231    if (jj_3R_40()) {
     1232    jj_scanpos = xsp;
     1233    if (jj_3R_41()) {
     1234    jj_scanpos = xsp;
     1235    if (jj_3R_42()) {
     1236    jj_scanpos = xsp;
     1237    if (jj_3R_43()) {
     1238    jj_scanpos = xsp;
     1239    if (jj_3R_44()) return true;
     1240    }
     1241    }
     1242    }
     1243    }
     1244    }
     1245    if (jj_3R_15()) return true;
     1246    xsp = jj_scanpos;
     1247    if (jj_3_3()) {
     1248    jj_scanpos = xsp;
     1249    if (jj_3R_45()) {
     1250    jj_scanpos = xsp;
     1251    if (jj_3R_46()) return true;
     1252    }
     1253    }
     1254    return false;
     1255  }
     1256
     1257  private boolean jj_3R_15() {
    11861258    Token xsp;
    11871259    xsp = jj_scanpos;
     
    11901262  }
    11911263
    1192   private boolean jj_3R_59() {
    1193     if (jj_3R_28()) return true;
    1194     return false;
    1195   }
    1196 
    1197   private boolean jj_3R_39() {
    1198     if (jj_scan_token(EQUAL)) return true;
    1199     return false;
    1200   }
    1201 
    1202   private boolean jj_3R_38() {
    1203     if (jj_scan_token(EXCLAMATION)) return true;
    1204     if (jj_scan_token(EQUAL)) return true;
    1205     return false;
    1206   }
    1207 
    1208   private boolean jj_3R_37() {
    1209     if (jj_scan_token(REGEX)) return true;
    1210     return false;
    1211   }
    1212 
    1213   private boolean jj_3R_24() {
    1214     Token xsp;
    1215     xsp = jj_scanpos;
    1216     if (jj_3R_38()) {
    1217     jj_scanpos = xsp;
    1218     if (jj_3R_39()) {
    1219     jj_scanpos = xsp;
    1220     if (jj_3R_40()) {
    1221     jj_scanpos = xsp;
    1222     if (jj_3R_41()) {
    1223     jj_scanpos = xsp;
    1224     if (jj_3R_42()) {
    1225     jj_scanpos = xsp;
    1226     if (jj_3R_43()) return true;
    1227     }
    1228     }
    1229     }
    1230     }
    1231     }
    1232     if (jj_3R_14()) return true;
    1233     xsp = jj_scanpos;
    1234     if (jj_3_3()) {
    1235     jj_scanpos = xsp;
    1236     if (jj_3R_44()) {
    1237     jj_scanpos = xsp;
    1238     if (jj_3R_45()) return true;
    1239     }
    1240     }
    1241     return false;
    1242   }
    1243 
    1244   private boolean jj_3R_56() {
     1264  private boolean jj_3R_60() {
     1265    if (jj_3R_29()) return true;
     1266    return false;
     1267  }
     1268
     1269  private boolean jj_3R_57() {
    12451270    if (jj_scan_token(COLON)) return true;
    1246     if (jj_scan_token(IDENT)) return true;
    1247     return false;
    1248   }
    1249 
    1250   private boolean jj_3R_57() {
    1251     Token xsp;
    1252     xsp = jj_scanpos;
    1253     if (jj_3R_74()) {
    1254     jj_scanpos = xsp;
    1255     if (jj_3R_75()) return true;
    1256     }
    1257     return false;
    1258   }
    1259 
    1260   private boolean jj_3R_74() {
    12611271    if (jj_scan_token(IDENT)) return true;
    12621272    return false;
     
    12661276    if (jj_scan_token(EQUAL)) return true;
    12671277    if (jj_scan_token(TILDE)) return true;
    1268     if (jj_3R_14()) return true;
    1269     if (jj_3R_37()) return true;
     1278    if (jj_3R_15()) return true;
     1279    if (jj_3R_38()) return true;
     1280    return false;
     1281  }
     1282
     1283  private boolean jj_3R_86() {
     1284    if (jj_scan_token(HEXCOLOR)) return true;
    12701285    return false;
    12711286  }
    12721287
    12731288  private boolean jj_3R_85() {
    1274     if (jj_scan_token(HEXCOLOR)) return true;
    1275     return false;
    1276   }
    1277 
    1278   private boolean jj_3R_27() {
    1279     if (jj_3R_51()) return true;
     1289    if (jj_3R_29()) return true;
    12801290    return false;
    12811291  }
    12821292
    12831293  private boolean jj_3R_84() {
    1284     if (jj_3R_28()) return true;
    1285     return false;
    1286   }
    1287 
    1288   private boolean jj_3R_83() {
    12891294    if (jj_scan_token(PLUS)) return true;
    1290     if (jj_3R_28()) return true;
    1291     return false;
    1292   }
    1293 
    1294   private boolean jj_3R_15() {
    1295     if (jj_3R_22()) return true;
    1296     if (jj_3R_14()) return true;
     1295    if (jj_3R_29()) return true;
     1296    return false;
     1297  }
     1298
     1299  private boolean jj_3R_38() {
     1300    if (jj_scan_token(REGEX)) return true;
     1301    return false;
     1302  }
     1303
     1304  private boolean jj_3R_16() {
     1305    if (jj_3R_23()) return true;
     1306    if (jj_3R_15()) return true;
    12971307    Token xsp;
    12981308    xsp = jj_scanpos;
    12991309    if (jj_3_4()) {
    13001310    jj_scanpos = xsp;
    1301     if (jj_3R_24()) {
    1302     jj_scanpos = xsp;
    1303     if (jj_3R_25()) return true;
    1304     }
    1305     }
     1311    if (jj_3R_25()) {
     1312    jj_scanpos = xsp;
     1313    if (jj_3R_26()) return true;
     1314    }
     1315    }
     1316    return false;
     1317  }
     1318
     1319  private boolean jj_3R_83() {
     1320    if (jj_3R_56()) return true;
    13061321    return false;
    13071322  }
    13081323
    13091324  private boolean jj_3R_82() {
    1310     if (jj_3R_55()) return true;
    1311     return false;
    1312   }
    1313 
    1314   private boolean jj_3R_81() {
    13151325    if (jj_scan_token(IDENT)) return true;
    13161326    return false;
    13171327  }
    13181328
    1319   private boolean jj_3R_76() {
     1329  private boolean jj_3R_77() {
    13201330    Token xsp;
    13211331    xsp = jj_scanpos;
    1322     if (jj_3R_81()) {
    1323     jj_scanpos = xsp;
    13241332    if (jj_3R_82()) {
    13251333    jj_scanpos = xsp;
     
    13281336    if (jj_3R_84()) {
    13291337    jj_scanpos = xsp;
    1330     if (jj_3R_85()) return true;
    1331     }
    1332     }
    1333     }
    1334     }
    1335     return false;
    1336   }
    1337 
    1338   private boolean jj_3R_55() {
     1338    if (jj_3R_85()) {
     1339    jj_scanpos = xsp;
     1340    if (jj_3R_86()) return true;
     1341    }
     1342    }
     1343    }
     1344    }
     1345    return false;
     1346  }
     1347
     1348  private boolean jj_3R_58() {
     1349    Token xsp;
     1350    xsp = jj_scanpos;
     1351    if (jj_3R_75()) {
     1352    jj_scanpos = xsp;
     1353    if (jj_3R_76()) return true;
     1354    }
     1355    return false;
     1356  }
     1357
     1358  private boolean jj_3R_75() {
     1359    if (jj_scan_token(IDENT)) return true;
     1360    return false;
     1361  }
     1362
     1363  private boolean jj_3R_28() {
     1364    if (jj_3R_52()) return true;
     1365    return false;
     1366  }
     1367
     1368  private boolean jj_3R_24() {
     1369    if (jj_scan_token(QUESTION)) return true;
     1370    return false;
     1371  }
     1372
     1373  private boolean jj_3R_22() {
     1374    if (jj_scan_token(EXCLAMATION)) return true;
     1375    return false;
     1376  }
     1377
     1378  private boolean jj_3R_87() {
     1379    if (jj_scan_token(COMMA)) return true;
     1380    if (jj_3R_19()) return true;
     1381    if (jj_3R_20()) return true;
     1382    return false;
     1383  }
     1384
     1385  private boolean jj_3R_14() {
     1386    Token xsp;
     1387    xsp = jj_scanpos;
     1388    if (jj_3R_22()) jj_scanpos = xsp;
     1389    if (jj_3R_23()) return true;
     1390    xsp = jj_scanpos;
     1391    if (jj_3R_24()) jj_scanpos = xsp;
     1392    return false;
     1393  }
     1394
     1395  private boolean jj_3R_56() {
    13391396    if (jj_scan_token(STRING)) return true;
    13401397    return false;
    13411398  }
    13421399
    1343   private boolean jj_3R_23() {
    1344     if (jj_scan_token(QUESTION)) return true;
    1345     return false;
    1346   }
    1347 
    1348   private boolean jj_3R_50() {
    1349     Token xsp;
    1350     xsp = jj_scanpos;
    1351     if (jj_3R_58()) {
    1352     jj_scanpos = xsp;
    1353     if (jj_3R_59()) return true;
    1354     }
    1355     return false;
    1356   }
    1357 
    1358   private boolean jj_3R_58() {
    1359     if (jj_scan_token(MINUS)) return true;
    1360     if (jj_3R_28()) return true;
    1361     return false;
    1362   }
    1363 
    1364   private boolean jj_3R_21() {
    1365     if (jj_scan_token(EXCLAMATION)) return true;
    1366     return false;
    1367   }
    1368 
    1369   private boolean jj_3R_86() {
    1370     if (jj_scan_token(COMMA)) return true;
    1371     if (jj_3R_18()) return true;
    1372     if (jj_3R_19()) return true;
    1373     return false;
    1374   }
    1375 
    1376   private boolean jj_3R_13() {
    1377     Token xsp;
    1378     xsp = jj_scanpos;
    1379     if (jj_3R_21()) jj_scanpos = xsp;
    1380     if (jj_3R_22()) return true;
    1381     xsp = jj_scanpos;
    1382     if (jj_3R_23()) jj_scanpos = xsp;
    1383     return false;
    1384   }
    1385 
    1386   private boolean jj_3R_34() {
    1387     if (jj_3R_19()) return true;
     1400  private boolean jj_3R_35() {
     1401    if (jj_3R_20()) return true;
    13881402    Token xsp;
    13891403    while (true) {
    13901404      xsp = jj_scanpos;
    1391       if (jj_3R_86()) { jj_scanpos = xsp; break; }
    1392     }
    1393     return false;
    1394   }
    1395 
    1396   private boolean jj_3R_28() {
     1405      if (jj_3R_87()) { jj_scanpos = xsp; break; }
     1406    }
     1407    return false;
     1408  }
     1409
     1410  private boolean jj_3R_37() {
     1411    if (jj_scan_token(IDENT)) return true;
     1412    Token xsp;
     1413    while (true) {
     1414      xsp = jj_scanpos;
     1415      if (jj_3R_57()) { jj_scanpos = xsp; break; }
     1416    }
     1417    return false;
     1418  }
     1419
     1420  private boolean jj_3R_36() {
     1421    if (jj_3R_56()) return true;
     1422    return false;
     1423  }
     1424
     1425  private boolean jj_3R_23() {
     1426    Token xsp;
     1427    xsp = jj_scanpos;
     1428    if (jj_3R_36()) {
     1429    jj_scanpos = xsp;
     1430    if (jj_3R_37()) return true;
     1431    }
     1432    return false;
     1433  }
     1434
     1435  private boolean jj_3R_21() {
     1436    if (jj_scan_token(IDENT)) return true;
     1437    if (jj_3R_19()) return true;
     1438    if (jj_scan_token(LPAR)) return true;
     1439    if (jj_3R_19()) return true;
     1440    Token xsp;
     1441    xsp = jj_scanpos;
     1442    if (jj_3R_35()) jj_scanpos = xsp;
     1443    if (jj_scan_token(RPAR)) return true;
     1444    return false;
     1445  }
     1446
     1447  private boolean jj_3R_51() {
     1448    Token xsp;
     1449    xsp = jj_scanpos;
     1450    if (jj_3R_59()) {
     1451    jj_scanpos = xsp;
     1452    if (jj_3R_60()) return true;
     1453    }
     1454    return false;
     1455  }
     1456
     1457  private boolean jj_3R_59() {
     1458    if (jj_scan_token(MINUS)) return true;
     1459    if (jj_3R_29()) return true;
     1460    return false;
     1461  }
     1462
     1463  private boolean jj_3_2() {
     1464    if (jj_3R_16()) return true;
     1465    if (jj_3R_15()) return true;
     1466    if (jj_scan_token(RSQUARE)) return true;
     1467    return false;
     1468  }
     1469
     1470  private boolean jj_3_1() {
     1471    if (jj_3R_14()) return true;
     1472    if (jj_3R_15()) return true;
     1473    if (jj_scan_token(RSQUARE)) return true;
     1474    return false;
     1475  }
     1476
     1477  private boolean jj_3R_62() {
     1478    if (jj_scan_token(LPAR)) return true;
     1479    if (jj_3R_19()) return true;
     1480    if (jj_3R_20()) return true;
     1481    if (jj_scan_token(RPAR)) return true;
     1482    return false;
     1483  }
     1484
     1485  private boolean jj_3R_61() {
     1486    if (jj_3R_77()) return true;
     1487    return false;
     1488  }
     1489
     1490  private boolean jj_3R_29() {
    13971491    Token xsp;
    13981492    xsp = jj_scanpos;
     
    14041498  }
    14051499
    1406   private boolean jj_3R_36() {
    1407     if (jj_scan_token(IDENT)) return true;
    1408     Token xsp;
     1500  private boolean jj_3_7() {
     1501    if (jj_3R_21()) return true;
     1502    return false;
     1503  }
     1504
     1505  private boolean jj_3R_54() {
     1506    Token xsp;
     1507    xsp = jj_scanpos;
     1508    if (jj_3_7()) {
     1509    jj_scanpos = xsp;
     1510    if (jj_3R_61()) {
     1511    jj_scanpos = xsp;
     1512    if (jj_3R_62()) return true;
     1513    }
     1514    }
     1515    return false;
     1516  }
     1517
     1518  private boolean jj_3R_27() {
     1519    if (jj_scan_token(MINUS)) return true;
     1520    if (jj_3R_52()) return true;
     1521    return false;
     1522  }
     1523
     1524  private boolean jj_3R_17() {
     1525    Token xsp;
     1526    xsp = jj_scanpos;
     1527    if (jj_3R_27()) {
     1528    jj_scanpos = xsp;
     1529    if (jj_3R_28()) return true;
     1530    }
     1531    return false;
     1532  }
     1533
     1534  private boolean jj_3R_74() {
     1535    if (jj_scan_token(QUESTION)) return true;
     1536    if (jj_3R_19()) return true;
     1537    if (jj_3R_54()) return true;
     1538    if (jj_3R_19()) return true;
     1539    if (jj_scan_token(COLON)) return true;
     1540    if (jj_3R_19()) return true;
     1541    if (jj_3R_54()) return true;
     1542    if (jj_3R_19()) return true;
     1543    return false;
     1544  }
     1545
     1546  private boolean jj_3R_73() {
     1547    if (jj_scan_token(PIPE)) return true;
     1548    if (jj_scan_token(PIPE)) return true;
     1549    if (jj_3R_19()) return true;
     1550    if (jj_3R_54()) return true;
     1551    if (jj_3R_19()) return true;
     1552    return false;
     1553  }
     1554
     1555  private boolean jj_3R_72() {
     1556    if (jj_scan_token(AMPERSAND)) return true;
     1557    if (jj_scan_token(AMPERSAND)) return true;
     1558    if (jj_3R_19()) return true;
     1559    if (jj_3R_54()) return true;
     1560    if (jj_3R_19()) return true;
     1561    return false;
     1562  }
     1563
     1564  private boolean jj_3R_71() {
     1565    if (jj_scan_token(LESS)) return true;
     1566    if (jj_3R_19()) return true;
     1567    if (jj_3R_54()) return true;
     1568    if (jj_3R_19()) return true;
     1569    return false;
     1570  }
     1571
     1572  private boolean jj_3R_52() {
     1573    if (jj_scan_token(UINT)) return true;
     1574    return false;
     1575  }
     1576
     1577  private boolean jj_3R_70() {
     1578    if (jj_scan_token(EQUAL)) return true;
     1579    Token xsp;
     1580    xsp = jj_scanpos;
     1581    if (jj_scan_token(22)) jj_scanpos = xsp;
     1582    if (jj_3R_19()) return true;
     1583    if (jj_3R_54()) return true;
     1584    if (jj_3R_19()) return true;
     1585    return false;
     1586  }
     1587
     1588  private boolean jj_3R_69() {
     1589    if (jj_scan_token(GREATER)) return true;
     1590    if (jj_3R_19()) return true;
     1591    if (jj_3R_54()) return true;
     1592    if (jj_3R_19()) return true;
     1593    return false;
     1594  }
     1595
     1596  private boolean jj_3R_68() {
     1597    if (jj_scan_token(LESS_EQUAL)) return true;
     1598    if (jj_3R_19()) return true;
     1599    if (jj_3R_54()) return true;
     1600    if (jj_3R_19()) return true;
     1601    return false;
     1602  }
     1603
     1604  private boolean jj_3R_81() {
     1605    if (jj_scan_token(SLASH)) return true;
     1606    if (jj_3R_19()) return true;
     1607    if (jj_3R_54()) return true;
     1608    if (jj_3R_19()) return true;
     1609    return false;
     1610  }
     1611
     1612  private boolean jj_3R_67() {
     1613    if (jj_scan_token(GREATER_EQUAL)) return true;
     1614    if (jj_3R_19()) return true;
     1615    if (jj_3R_54()) return true;
     1616    if (jj_3R_19()) return true;
     1617    return false;
     1618  }
     1619
     1620  private boolean jj_3R_80() {
     1621    if (jj_scan_token(MINUS)) return true;
     1622    if (jj_3R_19()) return true;
     1623    if (jj_3R_54()) return true;
     1624    if (jj_3R_19()) return true;
     1625    return false;
     1626  }
     1627
     1628  private boolean jj_3R_66() {
     1629    Token xsp;
     1630    if (jj_3R_81()) return true;
    14091631    while (true) {
    14101632      xsp = jj_scanpos;
    1411       if (jj_3R_56()) { jj_scanpos = xsp; break; }
    1412     }
    1413     return false;
    1414   }
    1415 
    1416   private boolean jj_3R_35() {
    1417     if (jj_3R_55()) return true;
    1418     return false;
    1419   }
    1420 
    1421   private boolean jj_3R_22() {
    1422     Token xsp;
    1423     xsp = jj_scanpos;
    1424     if (jj_3R_35()) {
    1425     jj_scanpos = xsp;
    1426     if (jj_3R_36()) return true;
    1427     }
    1428     return false;
    1429   }
    1430 
    1431   private boolean jj_3R_20() {
    1432     if (jj_scan_token(IDENT)) return true;
    1433     if (jj_3R_18()) return true;
    1434     if (jj_scan_token(LPAR)) return true;
    1435     if (jj_3R_18()) return true;
    1436     Token xsp;
    1437     xsp = jj_scanpos;
    1438     if (jj_3R_34()) jj_scanpos = xsp;
    1439     if (jj_scan_token(RPAR)) return true;
    1440     return false;
    1441   }
    1442 
    1443   private boolean jj_3_2() {
    1444     if (jj_3R_15()) return true;
    1445     if (jj_3R_14()) return true;
    1446     if (jj_scan_token(RSQUARE)) return true;
    1447     return false;
    1448   }
    1449 
    1450   private boolean jj_3_1() {
    1451     if (jj_3R_13()) return true;
    1452     if (jj_3R_14()) return true;
    1453     if (jj_scan_token(RSQUARE)) return true;
    1454     return false;
    1455   }
    1456 
    1457   private boolean jj_3R_26() {
    1458     if (jj_scan_token(MINUS)) return true;
    1459     if (jj_3R_51()) return true;
    1460     return false;
    1461   }
    1462 
    1463   private boolean jj_3R_16() {
    1464     Token xsp;
    1465     xsp = jj_scanpos;
    1466     if (jj_3R_26()) {
    1467     jj_scanpos = xsp;
    1468     if (jj_3R_27()) return true;
    1469     }
    1470     return false;
    1471   }
    1472 
    1473   private boolean jj_3R_61() {
    1474     if (jj_scan_token(LPAR)) return true;
    1475     if (jj_3R_18()) return true;
    1476     if (jj_3R_19()) return true;
    1477     if (jj_scan_token(RPAR)) return true;
    1478     return false;
    1479   }
    1480 
    1481   private boolean jj_3R_60() {
    1482     if (jj_3R_76()) return true;
    1483     return false;
    1484   }
    1485 
    1486   private boolean jj_3R_51() {
    1487     if (jj_scan_token(UINT)) return true;
    1488     return false;
    1489   }
    1490 
    1491   private boolean jj_3_7() {
    1492     if (jj_3R_20()) return true;
    1493     return false;
    1494   }
    1495 
    1496   private boolean jj_3R_53() {
    1497     Token xsp;
    1498     xsp = jj_scanpos;
    1499     if (jj_3_7()) {
    1500     jj_scanpos = xsp;
    1501     if (jj_3R_60()) {
    1502     jj_scanpos = xsp;
    1503     if (jj_3R_61()) return true;
    1504     }
    1505     }
    1506     return false;
    1507   }
    1508 
    1509   private boolean jj_3R_73() {
    1510     if (jj_scan_token(QUESTION)) return true;
    1511     if (jj_3R_18()) return true;
    1512     if (jj_3R_53()) return true;
    1513     if (jj_3R_18()) return true;
    1514     if (jj_scan_token(COLON)) return true;
    1515     if (jj_3R_18()) return true;
    1516     if (jj_3R_53()) return true;
    1517     if (jj_3R_18()) return true;
    1518     return false;
    1519   }
    1520 
    1521   private boolean jj_3R_72() {
    1522     if (jj_scan_token(PIPE)) return true;
    1523     if (jj_scan_token(PIPE)) return true;
    1524     if (jj_3R_18()) return true;
    1525     if (jj_3R_53()) return true;
    1526     if (jj_3R_18()) return true;
    1527     return false;
    1528   }
    1529 
    1530   private boolean jj_3R_71() {
    1531     if (jj_scan_token(AMPERSAND)) return true;
    1532     if (jj_scan_token(AMPERSAND)) return true;
    1533     if (jj_3R_18()) return true;
    1534     if (jj_3R_53()) return true;
    1535     if (jj_3R_18()) return true;
    1536     return false;
    1537   }
    1538 
    1539   private boolean jj_3R_70() {
    1540     if (jj_scan_token(LESS)) return true;
    1541     if (jj_3R_18()) return true;
    1542     if (jj_3R_53()) return true;
    1543     if (jj_3R_18()) return true;
    1544     return false;
    1545   }
    1546 
    1547   private boolean jj_3R_69() {
    1548     if (jj_scan_token(EQUAL)) return true;
    1549     Token xsp;
    1550     xsp = jj_scanpos;
    1551     if (jj_scan_token(22)) jj_scanpos = xsp;
    1552     if (jj_3R_18()) return true;
    1553     if (jj_3R_53()) return true;
    1554     if (jj_3R_18()) return true;
    1555     return false;
    1556   }
    1557 
    1558   private boolean jj_3R_68() {
    1559     if (jj_scan_token(GREATER)) return true;
    1560     if (jj_3R_18()) return true;
    1561     if (jj_3R_53()) return true;
    1562     if (jj_3R_18()) return true;
    1563     return false;
    1564   }
    1565 
    1566   private boolean jj_3R_67() {
    1567     if (jj_scan_token(LESS_EQUAL)) return true;
    1568     if (jj_3R_18()) return true;
    1569     if (jj_3R_53()) return true;
    1570     if (jj_3R_18()) return true;
    1571     return false;
    1572   }
    1573 
    1574   private boolean jj_3R_80() {
    1575     if (jj_scan_token(SLASH)) return true;
    1576     if (jj_3R_18()) return true;
    1577     if (jj_3R_53()) return true;
    1578     if (jj_3R_18()) return true;
    1579     return false;
    1580   }
    1581 
    1582   private boolean jj_3R_66() {
    1583     if (jj_scan_token(GREATER_EQUAL)) return true;
    1584     if (jj_3R_18()) return true;
    1585     if (jj_3R_53()) return true;
    1586     if (jj_3R_18()) return true;
     1633      if (jj_3R_81()) { jj_scanpos = xsp; break; }
     1634    }
    15871635    return false;
    15881636  }
    15891637
    15901638  private boolean jj_3R_79() {
    1591     if (jj_scan_token(MINUS)) return true;
    1592     if (jj_3R_18()) return true;
    1593     if (jj_3R_53()) return true;
    1594     if (jj_3R_18()) return true;
     1639    if (jj_scan_token(STAR)) return true;
     1640    if (jj_3R_19()) return true;
     1641    if (jj_3R_54()) return true;
     1642    if (jj_3R_19()) return true;
    15951643    return false;
    15961644  }
     
    16071655
    16081656  private boolean jj_3R_78() {
    1609     if (jj_scan_token(STAR)) return true;
    1610     if (jj_3R_18()) return true;
    1611     if (jj_3R_53()) return true;
    1612     if (jj_3R_18()) return true;
     1657    if (jj_scan_token(PLUS)) return true;
     1658    if (jj_3R_19()) return true;
     1659    if (jj_3R_54()) return true;
     1660    if (jj_3R_19()) return true;
    16131661    return false;
    16141662  }
     
    16241672  }
    16251673
    1626   private boolean jj_3R_77() {
    1627     if (jj_scan_token(PLUS)) return true;
    1628     if (jj_3R_18()) return true;
    1629     if (jj_3R_53()) return true;
    1630     if (jj_3R_18()) return true;
     1674  private boolean jj_3R_55() {
     1675    Token xsp;
     1676    xsp = jj_scanpos;
     1677    if (jj_3R_63()) {
     1678    jj_scanpos = xsp;
     1679    if (jj_3R_64()) {
     1680    jj_scanpos = xsp;
     1681    if (jj_3R_65()) {
     1682    jj_scanpos = xsp;
     1683    if (jj_3R_66()) {
     1684    jj_scanpos = xsp;
     1685    if (jj_3R_67()) {
     1686    jj_scanpos = xsp;
     1687    if (jj_3R_68()) {
     1688    jj_scanpos = xsp;
     1689    if (jj_3R_69()) {
     1690    jj_scanpos = xsp;
     1691    if (jj_3R_70()) {
     1692    jj_scanpos = xsp;
     1693    if (jj_3R_71()) {
     1694    jj_scanpos = xsp;
     1695    if (jj_3R_72()) {
     1696    jj_scanpos = xsp;
     1697    if (jj_3R_73()) {
     1698    jj_scanpos = xsp;
     1699    if (jj_3R_74()) return true;
     1700    }
     1701    }
     1702    }
     1703    }
     1704    }
     1705    }
     1706    }
     1707    }
     1708    }
     1709    }
     1710    }
    16311711    return false;
    16321712  }
     
    16421722  }
    16431723
    1644   private boolean jj_3R_54() {
     1724  private boolean jj_3R_34() {
     1725    if (jj_3R_54()) return true;
     1726    if (jj_3R_19()) return true;
    16451727    Token xsp;
    16461728    xsp = jj_scanpos;
    1647     if (jj_3R_62()) {
    1648     jj_scanpos = xsp;
    1649     if (jj_3R_63()) {
    1650     jj_scanpos = xsp;
    1651     if (jj_3R_64()) {
    1652     jj_scanpos = xsp;
    1653     if (jj_3R_65()) {
    1654     jj_scanpos = xsp;
    1655     if (jj_3R_66()) {
    1656     jj_scanpos = xsp;
    1657     if (jj_3R_67()) {
    1658     jj_scanpos = xsp;
    1659     if (jj_3R_68()) {
    1660     jj_scanpos = xsp;
    1661     if (jj_3R_69()) {
    1662     jj_scanpos = xsp;
    1663     if (jj_3R_70()) {
    1664     jj_scanpos = xsp;
    1665     if (jj_3R_71()) {
    1666     jj_scanpos = xsp;
    1667     if (jj_3R_72()) {
    1668     jj_scanpos = xsp;
    1669     if (jj_3R_73()) return true;
    1670     }
    1671     }
    1672     }
    1673     }
    1674     }
    1675     }
    1676     }
    1677     }
    1678     }
    1679     }
    1680     }
    1681     return false;
    1682   }
    1683 
    1684   private boolean jj_3R_62() {
    1685     Token xsp;
    1686     if (jj_3R_77()) return true;
    1687     while (true) {
    1688       xsp = jj_scanpos;
    1689       if (jj_3R_77()) { jj_scanpos = xsp; break; }
    1690     }
     1729    if (jj_3R_55()) jj_scanpos = xsp;
    16911730    return false;
    16921731  }
    16931732
    16941733  private boolean jj_3R_33() {
    1695     if (jj_3R_53()) return true;
    1696     if (jj_3R_18()) return true;
    1697     Token xsp;
    1698     xsp = jj_scanpos;
    1699     if (jj_3R_54()) jj_scanpos = xsp;
     1734    if (jj_scan_token(MINUS)) return true;
     1735    if (jj_3R_19()) return true;
     1736    if (jj_3R_54()) return true;
     1737    if (jj_3R_19()) return true;
    17001738    return false;
    17011739  }
    17021740
    17031741  private boolean jj_3R_32() {
    1704     if (jj_scan_token(MINUS)) return true;
    1705     if (jj_3R_18()) return true;
    1706     if (jj_3R_53()) return true;
    1707     if (jj_3R_18()) return true;
    1708     return false;
    1709   }
    1710 
    1711   private boolean jj_3R_31() {
    17121742    if (jj_scan_token(EXCLAMATION)) return true;
    1713     if (jj_3R_18()) return true;
    1714     if (jj_3R_53()) return true;
    1715     if (jj_3R_18()) return true;
     1743    if (jj_3R_19()) return true;
     1744    if (jj_3R_54()) return true;
     1745    if (jj_3R_19()) return true;
    17161746    return false;
    17171747  }
    17181748
    17191749  private boolean jj_3_6() {
    1720     if (jj_3R_19()) return true;
     1750    if (jj_3R_20()) return true;
    17211751    Token xsp;
    17221752    xsp = jj_scanpos;
     
    17281758  }
    17291759
    1730   private boolean jj_3R_19() {
     1760  private boolean jj_3R_20() {
    17311761    Token xsp;
    17321762    xsp = jj_scanpos;
    1733     if (jj_3R_31()) {
    1734     jj_scanpos = xsp;
    17351763    if (jj_3R_32()) {
    17361764    jj_scanpos = xsp;
    1737     if (jj_3R_33()) return true;
     1765    if (jj_3R_33()) {
     1766    jj_scanpos = xsp;
     1767    if (jj_3R_34()) return true;
    17381768    }
    17391769    }
     
    17421772
    17431773  private boolean jj_3_5() {
    1744     if (jj_3R_17()) return true;
    17451774    if (jj_3R_18()) return true;
     1775    if (jj_3R_19()) return true;
    17461776    Token xsp;
    17471777    xsp = jj_scanpos;
     
    17531783  }
    17541784
    1755   private boolean jj_3R_29() {
     1785  private boolean jj_3R_50() {
     1786    if (jj_scan_token(LESS)) return true;
     1787    return false;
     1788  }
     1789
     1790  private boolean jj_3R_49() {
     1791    if (jj_scan_token(LESS_EQUAL)) return true;
     1792    return false;
     1793  }
     1794
     1795  private boolean jj_3R_48() {
     1796    if (jj_scan_token(GREATER)) return true;
     1797    return false;
     1798  }
     1799
     1800  private boolean jj_3R_46() {
     1801    if (jj_3R_58()) return true;
     1802    return false;
     1803  }
     1804
     1805  private boolean jj_3R_47() {
     1806    if (jj_scan_token(GREATER_EQUAL)) return true;
     1807    return false;
     1808  }
     1809
     1810  private boolean jj_3R_45() {
     1811    if (jj_3R_51()) return true;
     1812    return false;
     1813  }
     1814
     1815  private boolean jj_3R_30() {
    17561816    if (jj_scan_token(COMMA)) return true;
    1757     if (jj_3R_14()) return true;
    1758     if (jj_3R_28()) return true;
    1759     return false;
    1760   }
    1761 
    1762   private boolean jj_3R_49() {
    1763     if (jj_scan_token(LESS)) return true;
    1764     return false;
    1765   }
    1766 
    1767   private boolean jj_3R_48() {
    1768     if (jj_scan_token(LESS_EQUAL)) return true;
    1769     return false;
    1770   }
    1771 
    1772   private boolean jj_3R_17() {
    1773     if (jj_3R_28()) return true;
    1774     Token xsp;
     1817    if (jj_3R_15()) return true;
    17751818    if (jj_3R_29()) return true;
    1776     while (true) {
    1777       xsp = jj_scanpos;
    1778       if (jj_3R_29()) { jj_scanpos = xsp; break; }
    1779     }
    1780     return false;
    1781   }
    1782 
    1783   private boolean jj_3R_47() {
    1784     if (jj_scan_token(GREATER)) return true;
    1785     return false;
    1786   }
    1787 
    1788   private boolean jj_3R_45() {
    1789     if (jj_3R_57()) return true;
    1790     return false;
    1791   }
    1792 
    1793   private boolean jj_3R_46() {
    1794     if (jj_scan_token(GREATER_EQUAL)) return true;
    1795     return false;
    1796   }
    1797 
    1798   private boolean jj_3R_52() {
    1799     if (jj_scan_token(COMMENT_START)) return true;
    1800     if (jj_scan_token(COMMENT_END)) return true;
    1801     return false;
    1802   }
    1803 
    1804   private boolean jj_3R_44() {
     1819    return false;
     1820  }
     1821
     1822  private boolean jj_3R_26() {
     1823    Token xsp;
     1824    xsp = jj_scanpos;
     1825    if (jj_3R_47()) {
     1826    jj_scanpos = xsp;
     1827    if (jj_3R_48()) {
     1828    jj_scanpos = xsp;
     1829    if (jj_3R_49()) {
     1830    jj_scanpos = xsp;
    18051831    if (jj_3R_50()) return true;
    1806     return false;
    1807   }
    1808 
    1809   private boolean jj_3R_75() {
    1810     if (jj_3R_55()) return true;
    1811     return false;
    1812   }
    1813 
    1814   private boolean jj_3R_30() {
    1815     Token xsp;
    1816     xsp = jj_scanpos;
    1817     if (jj_scan_token(9)) {
    1818     jj_scanpos = xsp;
    1819     if (jj_3R_52()) return true;
    1820     }
    1821     return false;
    1822   }
    1823 
    1824   private boolean jj_3R_25() {
    1825     Token xsp;
    1826     xsp = jj_scanpos;
    1827     if (jj_3R_46()) {
    1828     jj_scanpos = xsp;
    1829     if (jj_3R_47()) {
    1830     jj_scanpos = xsp;
    1831     if (jj_3R_48()) {
    1832     jj_scanpos = xsp;
    1833     if (jj_3R_49()) return true;
    1834     }
    1835     }
    1836     }
    1837     if (jj_3R_14()) return true;
    1838     if (jj_3R_50()) return true;
     1832    }
     1833    }
     1834    }
     1835    if (jj_3R_15()) return true;
     1836    if (jj_3R_51()) return true;
    18391837    return false;
    18401838  }
    18411839
    18421840  private boolean jj_3R_18() {
    1843     Token xsp;
     1841    if (jj_3R_29()) return true;
     1842    Token xsp;
     1843    if (jj_3R_30()) return true;
    18441844    while (true) {
    18451845      xsp = jj_scanpos;
     
    18501850
    18511851  private boolean jj_3_3() {
    1852     if (jj_3R_16()) return true;
    1853     return false;
    1854   }
    1855 
    1856   private boolean jj_3R_43() {
     1852    if (jj_3R_17()) return true;
     1853    return false;
     1854  }
     1855
     1856  private boolean jj_3R_44() {
    18571857    if (jj_scan_token(STAR)) return true;
    18581858    if (jj_scan_token(EQUAL)) return true;
     
    18601860  }
    18611861
     1862  private boolean jj_3R_53() {
     1863    if (jj_scan_token(COMMENT_START)) return true;
     1864    if (jj_scan_token(COMMENT_END)) return true;
     1865    return false;
     1866  }
     1867
     1868  private boolean jj_3R_43() {
     1869    if (jj_scan_token(DOLLAR)) return true;
     1870    if (jj_scan_token(EQUAL)) return true;
     1871    return false;
     1872  }
     1873
    18621874  private boolean jj_3R_42() {
    1863     if (jj_scan_token(DOLLAR)) return true;
     1875    if (jj_scan_token(CARET)) return true;
     1876    if (jj_scan_token(EQUAL)) return true;
     1877    return false;
     1878  }
     1879
     1880  private boolean jj_3R_41() {
     1881    if (jj_scan_token(TILDE)) return true;
     1882    if (jj_scan_token(EQUAL)) return true;
     1883    return false;
     1884  }
     1885
     1886  private boolean jj_3R_76() {
     1887    if (jj_3R_56()) return true;
     1888    return false;
     1889  }
     1890
     1891  private boolean jj_3R_31() {
     1892    Token xsp;
     1893    xsp = jj_scanpos;
     1894    if (jj_scan_token(9)) {
     1895    jj_scanpos = xsp;
     1896    if (jj_3R_53()) return true;
     1897    }
     1898    return false;
     1899  }
     1900
     1901  private boolean jj_3R_40() {
     1902    if (jj_scan_token(EQUAL)) return true;
     1903    return false;
     1904  }
     1905
     1906  private boolean jj_3R_19() {
     1907    Token xsp;
     1908    while (true) {
     1909      xsp = jj_scanpos;
     1910      if (jj_3R_31()) { jj_scanpos = xsp; break; }
     1911    }
     1912    return false;
     1913  }
     1914
     1915  private boolean jj_3R_39() {
     1916    if (jj_scan_token(EXCLAMATION)) return true;
    18641917    if (jj_scan_token(EQUAL)) return true;
    18651918    return false;
     
    18771930  private int jj_la;
    18781931  private int jj_gen;
    1879   final private int[] jj_la1 = new int[46];
     1932  final private int[] jj_la1 = new int[48];
    18801933  static private int[] jj_la1_0;
    18811934  static private int[] jj_la1_1;
     
    18851938   }
    18861939   private static void jj_la1_init_0() {
    1887       jj_la1_0 = new int[] {0x4,0xc,0xc,0x12,0x200,0x200,0x200,0x10000000,0x402,0x10000000,0x300000,0x300000,0x402,0x40000000,0x2804000,0x2804000,0x4000000,0x4,0x0,0x4,0x8081011e,0x2000000,0x12,0x800000,0x0,0x1c00400,0x1e,0x3c0000,0x1fc0400,0x800000,0x402,0x2,0x8002000,0x8002000,0x80000000,0x400,0x0,0x800,0x400000,0xa07c0c00,0xa07c0c00,0x8081011e,0x8001011e,0x10000000,0x8081011e,0x8000011e,};
     1940      jj_la1_0 = new int[] {0x4,0xc,0xc,0x12,0x200,0x200,0x200,0x10000000,0x402,0x10000000,0x300000,0x2804000,0x2804000,0x300000,0x402,0x40000000,0x2804000,0x2804000,0x4000000,0x4,0x0,0x4,0x8081011e,0x2000000,0x12,0x800000,0x0,0x1c00400,0x1e,0x3c0000,0x1fc0400,0x800000,0x402,0x2,0x8002000,0x8002000,0x80000000,0x400,0x0,0x800,0x400000,0xa07c0c00,0xa07c0c00,0x8081011e,0x8001011e,0x10000000,0x8081011e,0x8000011e,};
    18881941   }
    18891942   private static void jj_la1_init_1() {
    1890       jj_la1_1 = new int[] {0x1,0x0,0x1,0x0,0x0,0x20,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x0,0x0,0x0,0x4,0x18,0x1,0x0,0x18,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x7,0x7,0x1,0x0,0x0,0x1,0x0,};
     1943      jj_la1_1 = new int[] {0x1,0x0,0x1,0x0,0x0,0x20,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x0,0x0,0x0,0x4,0x18,0x1,0x0,0x18,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x7,0x7,0x1,0x0,0x0,0x1,0x0,};
    18911944   }
    18921945  final private JJCalls[] jj_2_rtns = new JJCalls[7];
     
    19051958    jj_ntk = -1;
    19061959    jj_gen = 0;
    1907     for (int i = 0; i < 46; i++) jj_la1[i] = -1;
     1960    for (int i = 0; i < 48; i++) jj_la1[i] = -1;
    19081961    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
    19091962  }
     
    19201973    jj_ntk = -1;
    19211974    jj_gen = 0;
    1922     for (int i = 0; i < 46; i++) jj_la1[i] = -1;
     1975    for (int i = 0; i < 48; i++) jj_la1[i] = -1;
    19231976    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
    19241977  }
     
    19311984    jj_ntk = -1;
    19321985    jj_gen = 0;
    1933     for (int i = 0; i < 46; i++) jj_la1[i] = -1;
     1986    for (int i = 0; i < 48; i++) jj_la1[i] = -1;
    19341987    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
    19351988  }
     
    19421995    jj_ntk = -1;
    19431996    jj_gen = 0;
    1944     for (int i = 0; i < 46; i++) jj_la1[i] = -1;
     1997    for (int i = 0; i < 48; i++) jj_la1[i] = -1;
    19451998    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
    19461999  }
     
    19522005    jj_ntk = -1;
    19532006    jj_gen = 0;
    1954     for (int i = 0; i < 46; i++) jj_la1[i] = -1;
     2007    for (int i = 0; i < 48; i++) jj_la1[i] = -1;
    19552008    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
    19562009  }
     
    19622015    jj_ntk = -1;
    19632016    jj_gen = 0;
    1964     for (int i = 0; i < 46; i++) jj_la1[i] = -1;
     2017    for (int i = 0; i < 48; i++) jj_la1[i] = -1;
    19652018    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
    19662019  }
     
    20792132      jj_kind = -1;
    20802133    }
    2081     for (int i = 0; i < 46; i++) {
     2134    for (int i = 0; i < 48; i++) {
    20822135      if (jj_la1[i] == jj_gen) {
    20832136        for (int j = 0; j < 32; j++) {
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.jj

    r4011 r4069  
    1313import org.openstreetmap.josm.gui.mappaint.Keyword;
    1414import org.openstreetmap.josm.gui.mappaint.mapcss.Condition;
     15import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context;
    1516import org.openstreetmap.josm.gui.mappaint.mapcss.Expression;
    1617import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction;
     
    2021import org.openstreetmap.josm.gui.mappaint.mapcss.Expression.FunctionExpression;
    2122import org.openstreetmap.josm.gui.mappaint.mapcss.Expression.LiteralExpression;
     23import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSException;
    2224import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.ChildOrParentSelector;
    2325import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector;
     26import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.LinkSelector;
    2427import org.openstreetmap.josm.tools.Pair;
    2528
     
    224227    (
    225228        try {
    226             r=rule() { if (r != null) { sheet.rules.add(r); } } w()
     229                r=rule() { if (r != null) { sheet.rules.add(r); } } w()
     230        } catch (MapCSSException mex) {
     231            error_skipto(RBRACE, mex);
     232            w();
    227233        } catch (ParseException ex) {
    228             error_skipto(RBRACE);
     234            error_skipto(RBRACE, null);
    229235            w();
    230236        }
     
    252258{
    253259    boolean parentSelector = false;
    254     Selector sel1, sel2 = null;
    255 }
    256 {
    257     sel1=selector() w()
    258     (
    259         ( <GREATER> { parentSelector = false; } | <LESS> { parentSelector = true; } ) w()
    260         sel2=selector() w()
     260    Condition c;
     261    List<Condition> conditions = new ArrayList<Condition>();
     262    Selector selLeft;
     263    LinkSelector selLink = null;
     264    Selector selRight = null;
     265}
     266{
     267    selLeft=selector() w()
     268    (
     269        ( <GREATER> { parentSelector = false; } | <LESS> { parentSelector = true; } )
     270        ( ( c=condition(Context.LINK) | c=pseudoclass(Context.LINK) ) { conditions.add(c); } )*
     271        { selLink = new LinkSelector(conditions); }
     272        w()
     273        selRight=selector() w()
    261274    )?
    262     { return sel2 != null ? new ChildOrParentSelector(sel1, sel2, parentSelector) : sel1; }
     275    { return selRight != null ? new ChildOrParentSelector(selLeft, selLink, selRight, parentSelector) : selLeft; }
    263276}
    264277
     
    274287    ( base=<IDENT> | base=<STAR> )
    275288    ( r=zoom() )?
    276     ( ( c=condition() | c=pseudoclass() ) { conditions.add(c); } )*
     289    ( ( c=condition(Context.PRIMITIVE) | c=pseudoclass(Context.PRIMITIVE) ) { conditions.add(c); } )*
    277290    ( sub=subpart() )?
    278291    { return new GeneralSelector(base.image, r, conditions, sub); }
     
    294307}
    295308
    296 Condition condition() :
     309Condition condition(Context context) :
    297310{
    298311    Condition c;
     
    302315    <LSQUARE> s()
    303316    (
    304         LOOKAHEAD( simple_key_condition() s() <RSQUARE> )
    305             c=simple_key_condition() s() <RSQUARE> { return c; }
     317        LOOKAHEAD( simple_key_condition(context) s() <RSQUARE> )
     318            c=simple_key_condition(context) s() <RSQUARE> { return c; }
    306319        |
    307         LOOKAHEAD( simple_key_value_condition() s() <RSQUARE> )
    308             c=simple_key_value_condition() s() <RSQUARE> { return c; }
     320        LOOKAHEAD( simple_key_value_condition(context) s() <RSQUARE> )
     321            c=simple_key_value_condition(context) s() <RSQUARE> { return c; }
    309322        |
    310             e=expression() <RSQUARE> { return new Condition.ExpressionCondition(e); }
     323            e=expression() <RSQUARE> { return Condition.create(e, context); }
    311324    )
    312325}
     
    323336}
    324337
    325 Condition simple_key_condition() :
     338Condition simple_key_condition(Context context) :
    326339{
    327340    boolean not = false;
     
    333346    key=tag_key()
    334347    ( <QUESTION> { yes = true; } )?
    335     { return new Condition.KeyCondition(key, not, yes); }
    336 }
    337 
    338 Condition simple_key_value_condition() :
     348    { return Condition.create(key, not, yes, context); }
     349}
     350
     351Condition simple_key_value_condition(Context context) :
    339352{
    340353    String key;
     
    385398            f=float_() { val=Float.toString(f); }
    386399    )
    387     { return new Condition.KeyValueCondition(key, val, op); }
    388 }
    389 
    390 Condition pseudoclass() :
     400    { return Condition.create(key, val, op, context); }
     401}
     402
     403Condition pseudoclass(Context context) :
    391404{
    392405    Token t;
     
    397410    <COLON>
    398411    t=<IDENT>
    399     { return new Condition.PseudoClassCondition(t.image, not); }
     412    { return Condition.create(t.image, not, context); }
    400413}
    401414
     
    550563
    551564JAVACODE
    552 void error_skipto(int kind) {
     565void error_skipto(int kind, MapCSSException me) {
    553566    if (token.kind == EOF)
    554567        throw new ParseException("Reached end of file while parsing");
    555     ParseException e = generateParseException();
     568       
     569    Exception e = null;       
     570    ParseException pe = generateParseException();
     571
     572    if (me != null) {
     573        me.setLine(pe.currentToken.next.beginLine);
     574        me.setColumn(pe.currentToken.next.beginColumn);
     575        e = me;
     576    } else {
     577        e = new ParseException(pe.getMessage()); // prevent memory leak
     578    }
     579   
    556580    System.err.println("Skipping to the next rule, because of an error:");
    557581    System.err.println(e);
    558582    if (sheet != null) {
    559         sheet.logError(new ParseException(e.getMessage()));
     583        sheet.logError(e);
    560584    }
    561585    Token t;
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParserTokenManager.java

    r4011 r4069  
    66import org.openstreetmap.josm.gui.mappaint.Keyword;
    77import org.openstreetmap.josm.gui.mappaint.mapcss.Condition;
     8import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context;
    89import org.openstreetmap.josm.gui.mappaint.mapcss.Expression;
    910import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction;
     
    1314import org.openstreetmap.josm.gui.mappaint.mapcss.Expression.FunctionExpression;
    1415import org.openstreetmap.josm.gui.mappaint.mapcss.Expression.LiteralExpression;
     16import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSException;
    1517import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.ChildOrParentSelector;
    1618import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector;
     19import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.LinkSelector;
    1720import org.openstreetmap.josm.tools.Pair;
    1821
  • trunk/src/org/openstreetmap/josm/tools/Utils.java

    r4065 r4069  
    77import java.io.InputStream;
    88import java.io.OutputStream;
     9import java.text.MessageFormat;
    910import java.util.Collection;
    1011
     12/**
     13 * Basic utils, that can be useful in different parts of the program.
     14 */
    1115public class Utils {
    1216
     
    8084            return true;
    8185        return (a != null && a.equals(b));
     86    }
     87
     88    public static void ensure(boolean condition, String message, Object...data) {
     89        if (!condition)
     90            throw new AssertionError(
     91                    MessageFormat.format(message,data)
     92            );
    8293    }
    8394
     
    162173    }
    163174
     175    public static Color complement(Color clr) {
     176        return new Color(255 - clr.getRed(), 255 - clr.getGreen(), 255 - clr.getBlue(), clr.getAlpha());
     177    }
    164178
    165179    public static int copyStream(InputStream source, OutputStream destination) throws IOException {
     
    172186        }
    173187        return count;
    174     }
    175 
    176 
    177 
    178     public static Color complement(Color clr) {
    179         return new Color(255 - clr.getRed(), 255 - clr.getGreen(), 255 - clr.getBlue(), clr.getAlpha());
    180188    }
    181189
  • trunk/test/unit/org/openstreetmap/josm/gui/mappaint/AllMappaintTests.groovy

    r3990 r4069  
    22package org.openstreetmap.josm.gui.mappaint
    33
    4 import junit.framework.TestCase;
     4import junit.framework.TestCase
    55
    6 import org.junit.runner.RunWith;
    7 import org.junit.runners.Suite;
     6import org.junit.runner.RunWith
     7import org.junit.runners.Suite
     8import org.openstreetmap.josm.gui.mappaint.mapcss.AllMapCSSTests
    89
    910@RunWith(Suite.class)
    1011@Suite.SuiteClasses([
    1112    LabelCompositionStrategyTest.class,
    12     MapCSSWithExtendedTextDirectivesTest.class
     13    MapCSSWithExtendedTextDirectivesTest.class,
     14    AllMapCSSTests.class
     15   
    1316])
    1417public class AllMappaintTests extends TestCase{}
  • trunk/test/unit/org/openstreetmap/josm/gui/mappaint/MapCSSWithExtendedTextDirectivesTest.groovy

    r3991 r4069  
    22package org.openstreetmap.josm.gui.mappaint
    33
    4 import java.awt.Color;
     4import java.awt.Color
    55
    6 import org.junit.*;
    7 import org.openstreetmap.josm.fixtures.JOSMFixture
    8 import org.openstreetmap.josm.gui.mappaint.LabelCompositionStrategy.DeriveLabelFromNameTagsCompositionStrategy
    9 import org.openstreetmap.josm.gui.mappaint.LabelCompositionStrategy.StaticLabelCompositionStrategy
    10 import org.openstreetmap.josm.gui.mappaint.LabelCompositionStrategy.TagLookupCompositionStrategy
     6import org.junit.*
     7import org.openstreetmap.josm.fixtures.JOSMFixture
     8import org.openstreetmap.josm.gui.mappaint.LabelCompositionStrategy.DeriveLabelFromNameTagsCompositionStrategy
     9import org.openstreetmap.josm.gui.mappaint.LabelCompositionStrategy.TagLookupCompositionStrategy
    1110class MapCSSWithExtendedTextDirectivesTest {
    1211   
Note: See TracChangeset for help on using the changeset viewer.