Fixed/simplified integer and floating-point number terminals and value
conversion.
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/conversion/FLOATValueConverter_toValue_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/conversion/FLOATValueConverter_toValue_Test.java
new file mode 100644
index 0000000..520e078
--- /dev/null
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/conversion/FLOATValueConverter_toValue_Test.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.protobuf.conversion;
+
+import static java.util.Arrays.asList;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+
+import java.util.Collection;
+
+import org.eclipse.xtext.nodemodel.INode;
+import org.junit.*;
+import org.junit.runner.RunWith;
+import org.junit.runners.*;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.google.eclipse.protobuf.junit.core.XtextRule;
+
+/**
+ * Tests for <code>{@link FLOATValueConverter#toValue(String, INode)}</code>.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+@RunWith(Parameterized.class)
+public class FLOATValueConverter_toValue_Test {
+
+ @Rule public XtextRule xtext = new XtextRule();
+
+ private final String input;
+ private final Float expected;
+
+ @Parameters
+ public static Collection<Object[]> parameters() {
+ return asList(new Object[][] {
+ { "6.8", 6.8F },
+ { "-3.1", -3.1F },
+ { ".3", 0.3F }
+ });
+ }
+
+ public FLOATValueConverter_toValue_Test(String input, Float expected) {
+ this.input = input;
+ this.expected = expected;
+ }
+
+ private FLOATValueConverter converter;
+ private INode node;
+
+ @Before public void setUp() {
+ node = mock(INode.class);
+ converter = xtext.injector().getInstance(FLOATValueConverter.class);
+ }
+
+ @Test public void should_parse_hexadecimal_number() {
+ Float value = converter.toValue(input, node);
+ assertThat(value, equalTo(expected));
+ }
+}
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/conversion/FLOATValueConverter_toValue_withInvalidInput_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/conversion/FLOATValueConverter_toValue_withInvalidInput_Test.java
new file mode 100644
index 0000000..a2957f4
--- /dev/null
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/conversion/FLOATValueConverter_toValue_withInvalidInput_Test.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.protobuf.conversion;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.junit.Assert.*;
+import static org.junit.rules.ExpectedException.none;
+import static org.mockito.Mockito.mock;
+
+import org.eclipse.xtext.conversion.ValueConverterException;
+import org.eclipse.xtext.nodemodel.INode;
+import org.junit.*;
+import org.junit.rules.ExpectedException;
+
+import com.google.eclipse.protobuf.junit.core.XtextRule;
+
+/**
+ * Tests for <code>{@link FLOATValueConverter#toValue(String, INode)}</code>.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class FLOATValueConverter_toValue_withInvalidInput_Test {
+
+ @Rule public XtextRule xtext = new XtextRule();
+ @Rule public ExpectedException thrown = none();
+
+ private FLOATValueConverter converter;
+ private INode node;
+
+ @Before public void setUp() {
+ node = mock(INode.class);
+ converter = xtext.injector().getInstance(FLOATValueConverter.class);
+ }
+
+ @Test public void should_throw_error_if_input_is_null() {
+ thrown.expect(ValueConverterException.class);
+ thrown.expectMessage("Couldn't convert empty string to float.");
+ converter.toValue(null, node);
+ }
+
+ @Test public void should_throw_error_if_input_is_empty() {
+ thrown.expect(ValueConverterException.class);
+ thrown.expectMessage("Couldn't convert empty string to float.");
+ converter.toValue("", node);
+ }
+
+ @Test public void should_throw_error_if_conversion_throws_NumberFormatException() {
+ try {
+ converter.toValue("abc", node);
+ fail("Expecting a " + ValueConverterException.class.getName());
+ } catch (ValueConverterException e) {
+ assertThat(e.getMessage(), equalTo("Couldn't convert 'abc' to float."));
+ assertThat(e.getCause(), instanceOf(NumberFormatException.class));
+ }
+ }
+}
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/conversion/INTValueConverter_toValue_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/conversion/INTValueConverter_toValue_Test.java
new file mode 100644
index 0000000..af29dea
--- /dev/null
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/conversion/INTValueConverter_toValue_Test.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.protobuf.conversion;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.junit.rules.ExpectedException.none;
+import static org.mockito.Mockito.mock;
+
+import org.eclipse.xtext.conversion.ValueConverterException;
+import org.eclipse.xtext.nodemodel.INode;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import com.google.eclipse.protobuf.junit.core.XtextRule;
+
+/**
+ * Tests for <code>{@link INTValueConverter#toString()}</code>.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class INTValueConverter_toValue_Test {
+
+ @Rule public XtextRule xtext = new XtextRule();
+ @Rule public ExpectedException thrown = none();
+
+ private INTValueConverter converter;
+ private INode node;
+
+ @Before public void setUp() {
+ node = mock(INode.class);
+ converter = xtext.injector().getInstance(INTValueConverter.class);
+ }
+
+ @Test public void should_throw_error_if_input_is_null() {
+ thrown.expect(ValueConverterException.class);
+ thrown.expectMessage("Couldn't convert empty string to int.");
+ converter.toValue(null, node);
+ }
+
+ @Test public void should_throw_error_if_input_is_empty() {
+ thrown.expect(ValueConverterException.class);
+ thrown.expectMessage("Couldn't convert empty string to int.");
+ converter.toValue("", node);
+ }
+
+ @Test public void should_throw_error_if_conversion_throws_NumberFormatException() {
+ try {
+ converter.toValue("abc", node);
+ fail("Expecting a " + ValueConverterException.class.getName());
+ } catch (ValueConverterException e) {
+ assertThat(e.getMessage(), equalTo("Couldn't convert 'abc' to int."));
+ assertThat(e.getCause(), instanceOf(NumberFormatException.class));
+ }
+ }
+
+ @Test public void should_parse_integer() {
+ assertThat(converter.toValue("68", node), equalTo(68));
+ }
+
+ @Test public void should_parse_negative_integer() {
+ assertThat(converter.toValue("-2", node), equalTo(-2));
+ }
+}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/Protobuf.xtext b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/Protobuf.xtext
index 1c52aa3..c9f1c3a 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/Protobuf.xtext
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/Protobuf.xtext
@@ -128,7 +128,7 @@
| false;
NumberRef:
- HexRef | IntRef | LongRef | FloatRef | DoubleRef;
+ HexRef | IntRef | FloatRef;
HexRef:
hex=HEX;
@@ -137,30 +137,12 @@
int=INT;
terminal INT returns ecore::EInt:
- SIGNED_INT;
-
-LongRef:
- long=LONG;
-
-terminal LONG returns ecore::ELong:
- SIGNED_INT;
-
-terminal SIGNED_INT:
('-')? (NUMBER)+;
FloatRef:
float=FLOAT;
terminal FLOAT returns ecore::EFloat:
- DECIMAL;
-
-DoubleRef:
- double=DOUBLE;
-
-terminal DOUBLE returns ecore::EDouble:
- DECIMAL;
-
-terminal DECIMAL:
('-')? (NUMBER)* ('.' (NUMBER)+)?;
StringRef:
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/conversion/FLOATValueConverter.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/conversion/FLOATValueConverter.java
new file mode 100644
index 0000000..930b070
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/conversion/FLOATValueConverter.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.protobuf.conversion;
+
+import static org.eclipse.xtext.util.Strings.isEmpty;
+
+import org.eclipse.xtext.conversion.ValueConverterException;
+import org.eclipse.xtext.conversion.impl.AbstractLexerBasedConverter;
+import org.eclipse.xtext.nodemodel.INode;
+
+/**
+ * Converts floating-point numbers to {@code float}s.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class FLOATValueConverter extends AbstractLexerBasedConverter<Float> {
+
+ /**
+ * Creates an {@code float} from the given input, if the given input represents a floating-point number.
+ * @param string the given input.
+ * @param node the parsed node including hidden parts.
+ * @return the new {@code float}.
+ * @throws ValueConverterException if the given input is {@code null}, empty or does not represent a floating-point
+ * number.
+ */
+ public Float toValue(String string, INode node) throws ValueConverterException {
+ if (isEmpty(string)) throw new ValueConverterException("Couldn't convert empty string to float.", node, null);
+ try {
+ return Float.parseFloat(string);
+ } catch (NumberFormatException e) {
+ throw parsingError(string, node, e);
+ }
+ }
+
+ private ValueConverterException parsingError(String string, INode node, Exception cause) {
+ return new ValueConverterException("Couldn't convert '" + string + "' to float.", node, cause);
+ }
+}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/conversion/HEXValueConverter.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/conversion/HEXValueConverter.java
index 5901541..8f26d41 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/conversion/HEXValueConverter.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/conversion/HEXValueConverter.java
@@ -25,7 +25,7 @@
* Creates an {@code int} from the given input, if the given input represents an hexadecimal number.
* @param string the given input.
* @param node the parsed node including hidden parts.
- * @return the new integer.
+ * @return the new {@code int}.
* @throws ValueConverterException if the given input is {@code null}, empty or does not represent an hexadecimal
* number.
*/
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/conversion/INTValueConverter.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/conversion/INTValueConverter.java
new file mode 100644
index 0000000..2538d52
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/conversion/INTValueConverter.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.protobuf.conversion;
+
+import static org.eclipse.xtext.util.Strings.isEmpty;
+
+import org.eclipse.xtext.conversion.ValueConverterException;
+import org.eclipse.xtext.conversion.impl.AbstractLexerBasedConverter;
+import org.eclipse.xtext.nodemodel.INode;
+
+/**
+ * Converts integer numbers to {@code int}s.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class INTValueConverter extends AbstractLexerBasedConverter<Integer> {
+
+ /**
+ * Creates an {@code int} from the given input, if the given input represents an integer number.
+ * @param string the given input.
+ * @param node the parsed node including hidden parts.
+ * @return the new {@code int}.
+ * @throws ValueConverterException if the given input is {@code null}, empty or does not represent an integer number.
+ */
+ public Integer toValue(String string, INode node) throws ValueConverterException {
+ if (isEmpty(string)) throw new ValueConverterException("Couldn't convert empty string to int.", node, null);
+ try {
+ return Integer.parseInt(string, 10);
+ } catch (NumberFormatException e) {
+ throw parsingError(string, node, e);
+ }
+ }
+
+ private ValueConverterException parsingError(String string, INode node, Exception cause) {
+ return new ValueConverterException("Couldn't convert '" + string + "' to int.", node, cause);
+ }
+}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/conversion/ProtobufTerminalConverters.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/conversion/ProtobufTerminalConverters.java
index c56b41b..9a6af27 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/conversion/ProtobufTerminalConverters.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/conversion/ProtobufTerminalConverters.java
@@ -18,16 +18,28 @@
*/
public class ProtobufTerminalConverters extends DefaultTerminalConverters {
+ @Inject private FLOATValueConverter floatValueConverter;
@Inject private HEXValueConverter hexValueConverter;
+ @Inject private INTValueConverter intValueConverter;
@Inject private STRINGValueConverter stringValueConverter;
-
+
+ @ValueConverter(rule = "FLOAT")
+ public IValueConverter<Float> FLOAT() {
+ return floatValueConverter;
+ }
+
@ValueConverter(rule = "HEX")
public IValueConverter<Integer> HEX() {
return hexValueConverter;
}
+
+ @ValueConverter(rule = "INT")
+ @Override public IValueConverter<Integer> INT() {
+ return intValueConverter;
+ }
@ValueConverter(rule = "STRING")
- public IValueConverter<String> STRING() {
+ @Override public IValueConverter<String> STRING() {
return stringValueConverter;
}
}