Index: trunk/org.gvsig.desktop/org.gvsig.desktop.library/org.gvsig.expressionevaluator/org.gvsig.expressionevaluator.lib/org.gvsig.expressionevaluator.lib.api/src/main/java/org/gvsig/expressionevaluator/spi/AbstractLexicalAnalyzer.java
===================================================================
--- trunk/org.gvsig.desktop/org.gvsig.desktop.library/org.gvsig.expressionevaluator/org.gvsig.expressionevaluator.lib/org.gvsig.expressionevaluator.lib.api/src/main/java/org/gvsig/expressionevaluator/spi/AbstractLexicalAnalyzer.java	(revision 44429)
+++ trunk/org.gvsig.desktop/org.gvsig.desktop.library/org.gvsig.expressionevaluator/org.gvsig.expressionevaluator.lib/org.gvsig.expressionevaluator.lib.api/src/main/java/org/gvsig/expressionevaluator/spi/AbstractLexicalAnalyzer.java	(revision 44430)
@@ -313,57 +313,32 @@
         token.set(Token.STRING_LITERAL, buffer.toString());
     }
 
-    protected void parseSpecialNumber() {
-        char ch = getch();
-        if( ch!='@' ) {
-            throw new ExpressionSyntaxException(I18N.Wrong_special_number_start(), this);
-        }
-        buffer.clear();
-        ch = getch();
-        while (true) {
-            if (ch == EOF) {
-                throw new ExpressionSyntaxException(I18N.End_of_string_was_expected_and_end_of_source_was_found(), this);
-            }
-            if( !Character.isAlphabetic(ch) ) {
-                break;
-            }
-            buffer.add(ch);
-            ch = getch();
-        }
-        String formatName = buffer.toString();
-        if( StringUtils.isBlank(formatName) ) {
-            formatName = "DMS";
-        }
-        formatName = formatName.toUpperCase();
-        /*
-        From https://es.wikipedia.org/wiki/Sistema_de_coordenadas#Coordenadas_geogr%C3%A1ficas
-        
-        DD --- Decimal Degree (Grados Polares)
-        DM --- Degree:Minute (Grados:Minutos)
-        DMS -- Degree:Minute:Second 
-        */
-        switch(formatName) {
-            case "DMS":
-                ungetch();
-                parseDMSNumber();
-                break;
-            default:
-                throw new ExpressionSyntaxException(I18N.Special_number_format_not_supported(formatName), this);
-        }
-    }
-
-    private void parseDMSNumber() {
+    protected void parseDMSNumber() {
         int d;
         int m;
         int s_i;
-        int s_d;
+        double s_d;
         double s;
-        String ll;
         char ch;
+        Integer sign = null;
         
+        skipblanks();
+        ch = getch();
+        if( ch!='@' ) {
+            throw new ExpressionSyntaxException(I18N.Wrong_special_number_start(), this);
+        }
+        
         // Parseamos los grados
         skipblanks();
         ch = getch();
+        if( ch=='+' ) {
+            sign = 1;
+            ch = getch();
+        } else if ( ch=='-' ) {
+            sign = -1;
+            ch = getch();
+        }
+        
         buffer.clear();
         if( !Character.isDigit(ch) ) {
             throw new ExpressionSyntaxException(I18N.Expected_a_number_at_position_XpositionX(this.getPosition()), this);        
@@ -442,7 +417,8 @@
                 buffer.add(ch);
                 ch = getch();
             }            
-            s_d = Integer.parseInt(buffer.toString());
+            String ss = buffer.toString();
+            s_d = (double) Integer.parseInt(ss) / Math.pow(10, ss.length());
         } else {
             s_d = 0;
         }
@@ -450,55 +426,57 @@
             throw new ExpressionSyntaxException(I18N.Expected_XexpectedX_and_found_XfoundX(" ", String.valueOf(ch)), this);
         }
         
-        s = Double.parseDouble(s_i+"."+s_d);
+        s = s_i + s_d; 
         
         double dd = d + m / 60.0 + s / 3600.0;
         
-        skipblanks();
-        ch = getch();
-        switch(ch) {
-            case 'N':
-            case 'n':
-                if( dd>90 ) {
-                    throw new ExpressionSyntaxException(I18N.Incorrect_value_for_latitude(dd), this);
-                }
-                dd = -dd;
-                break;
-                
-            case 'S':
-            case 's':
-                if( dd>90 ) {
-                    throw new ExpressionSyntaxException(I18N.Incorrect_value_for_latitude(dd), this);
-                }
-                break;
-            case 'E':
-            case 'e':
-                if( dd>180 ) {
-                    throw new ExpressionSyntaxException(I18N.Incorrect_value_for_latitude(dd), this);
-                }
-                break;
-                
-            case 'O':
-            case 'o':
-            case 'W':
-            case 'w':
-                if( dd>180 ) {
-                    throw new ExpressionSyntaxException(I18N.Incorrect_value_for_latitude(dd), this);
-                }
-                dd = -dd;
-                break;
-                
-            default:
-                throw new ExpressionSyntaxException(I18N.Expected_XexpectedX_and_found_XfoundX("N/S/E/W", String.valueOf(ch)), this);
-        }
-        ll = String.valueOf(Character.toUpperCase(ch));
-        
+        if( sign==null ) {
+            skipblanks();
+            ch = getch();
+            switch(ch) {
+                case 'N':
+                case 'n':
+                    if( dd>90 ) {
+                        throw new ExpressionSyntaxException(I18N.Incorrect_value_for_latitude(dd), this);
+                    }
+                    sign = 1;
+                    break;
+
+                case 'S':
+                case 's':
+                    if( dd>90 ) {
+                        throw new ExpressionSyntaxException(I18N.Incorrect_value_for_latitude(dd), this);
+                    }
+                    sign = -1;
+                    break;
+                case 'E':
+                case 'e':
+                    if( dd>180 ) {
+                        throw new ExpressionSyntaxException(I18N.Incorrect_value_for_latitude(dd), this);
+                    }
+                    sign = 1;
+                    break;
+
+                case 'O':
+                case 'o':
+                case 'W':
+                case 'w':
+                    if( dd>180 ) {
+                        throw new ExpressionSyntaxException(I18N.Incorrect_value_for_longitude(dd), this);
+                    }
+                    sign = -1;
+                    break;
+
+                default:
+                    throw new ExpressionSyntaxException(I18N.Expected_XexpectedX_and_found_XfoundX("N/S/E/W", String.valueOf(ch)), this);
+            }
+        } 
+        dd = dd * sign;
         token.set(
                 Token.FLOATING_POINT_LITERAL,
-                String.format("@%dº %d' %f\" %s", d,m,s,ll) ,
+                String.format("@%s%dº %d' %f\"", sign<0? "-":"+", d,m,s) ,
                 dd
         );
-        
     }
     
     protected void parseNumber() {
Index: trunk/org.gvsig.desktop/org.gvsig.desktop.library/org.gvsig.expressionevaluator/org.gvsig.expressionevaluator.lib/org.gvsig.expressionevaluator.lib.impl/src/test/java/org/gvsig/expresionevaluator/impl/TestInterpreter.java
===================================================================
--- trunk/org.gvsig.desktop/org.gvsig.desktop.library/org.gvsig.expressionevaluator/org.gvsig.expressionevaluator.lib/org.gvsig.expressionevaluator.lib.impl/src/test/java/org/gvsig/expresionevaluator/impl/TestInterpreter.java	(revision 44429)
+++ trunk/org.gvsig.desktop/org.gvsig.desktop.library/org.gvsig.expressionevaluator/org.gvsig.expressionevaluator.lib/org.gvsig.expressionevaluator.lib.impl/src/test/java/org/gvsig/expresionevaluator/impl/TestInterpreter.java	(revision 44430)
@@ -94,7 +94,32 @@
 
         Code code = compiler.compileExpression(source);
         Object v = interpreter.run(code);
-        assertEquals(-10.5003, Math.round(((Number)v).doubleValue()*10000d)/10000d);
+        assertEquals(10.5003, Math.round(((Number)v).doubleValue()*10000d)/10000d);
+
+        source = "@10 30 0.09 N";
+
+        code = compiler.compileExpression(source);
+        v = interpreter.run(code);
+        assertEquals(10.500025, Math.round(((Number)v).doubleValue()*1000000d)/1000000d);
+
+        source = "@10 30 0.09 S";
+
+        code = compiler.compileExpression(source);
+        v = interpreter.run(code);
+        assertEquals(-10.500025, Math.round(((Number)v).doubleValue()*1000000d)/1000000d);
+
+        source = "@+10 30 0.09";
+
+        code = compiler.compileExpression(source);
+        v = interpreter.run(code);
+        assertEquals(10.500025, Math.round(((Number)v).doubleValue()*1000000d)/1000000d);
+
+        source = "@-10 30 0.09";
+
+        code = compiler.compileExpression(source);
+        v = interpreter.run(code);
+        assertEquals(-10.500025, Math.round(((Number)v).doubleValue()*1000000d)/1000000d);
+
     }
     
     public void testTrue() {
Index: trunk/org.gvsig.desktop/org.gvsig.desktop.library/org.gvsig.expressionevaluator/org.gvsig.expressionevaluator.lib/org.gvsig.expressionevaluator.lib.impl/src/main/java/org/gvsig/expressionevaluator/impl/SQLLexicalAnalyzer.java
===================================================================
--- trunk/org.gvsig.desktop/org.gvsig.desktop.library/org.gvsig.expressionevaluator/org.gvsig.expressionevaluator.lib/org.gvsig.expressionevaluator.lib.impl/src/main/java/org/gvsig/expressionevaluator/impl/SQLLexicalAnalyzer.java	(revision 44429)
+++ trunk/org.gvsig.desktop/org.gvsig.desktop.library/org.gvsig.expressionevaluator/org.gvsig.expressionevaluator.lib/org.gvsig.expressionevaluator.lib.impl/src/main/java/org/gvsig/expressionevaluator/impl/SQLLexicalAnalyzer.java	(revision 44430)
@@ -214,7 +214,7 @@
         
         case '@':
             ungetch();
-            parseSpecialNumber();
+            parseDMSNumber();
             return token;
         }
         
