Merge: nitrpg: fix crash when the Reviews/Work requests return nothing
authorJean Privat <jean@pryen.org>
Mon, 3 Aug 2015 18:35:20 +0000 (14:35 -0400)
committerJean Privat <jean@pryen.org>
Mon, 3 Aug 2015 18:35:20 +0000 (14:35 -0400)
Nitrpg was down since last wednesday because of this. It's now back on track: http://nitlanguage.org/rpg/games/privat/nit

Since the listener didn't crash, no data were loss during the downtime.

Pull-Request: #1604
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Jean Privat <jean@pryen.org>

41 files changed:
VERSION
contrib/jwrapper/Makefile
contrib/jwrapper/examples/android_api/.gitignore
contrib/jwrapper/examples/android_api/Makefile
contrib/jwrapper/examples/java_api/.gitignore [new file with mode: 0644]
contrib/jwrapper/examples/java_api/Makefile [new file with mode: 0644]
contrib/jwrapper/examples/java_api/api_user.nit [new file with mode: 0644]
contrib/jwrapper/examples/java_api/api_user.sav [new file with mode: 0644]
contrib/jwrapper/examples/queue/Makefile
contrib/jwrapper/grammar/javap.sablecc
contrib/jwrapper/src/code_generator.nit
contrib/jwrapper/src/javap_visitor.nit
contrib/jwrapper/src/jwrapper.nit
contrib/jwrapper/src/model.nit
contrib/jwrapper/tests/generics.javap [new file with mode: 0644]
contrib/jwrapper/tests/statics.javap [new file with mode: 0644]
contrib/rss_downloader/src/rss_downloader.nit
lib/android/audio.nit
lib/app/audio.nit
lib/dom/examples/checker.nit [new file with mode: 0644]
lib/java/base.nit [new file with mode: 0644]
lib/java/collections.nit
lib/java/io.nit
lib/java/java.nit
lib/standard/collection/abstract_collection.nit
lib/standard/exec.nit
lib/standard/file.nit
lib/standard/stream.nit
lib/standard/text/abstract_text.nit
lib/standard/text/ropes.nit
misc/vim/syntax/nit.vim
src/literal.nit
src/parser/nit.sablecc3xx
src/parser/tables_nit.c
tests/base_test_bases.nit
tests/niti.skip
tests/nitvm.skip
tests/sav/base_error_literal.res
tests/sav/checker.res [new file with mode: 0644]
tests/sav/nitpick_args1.res
tests/test_ropebuffer.nit [new file with mode: 0644]

diff --git a/VERSION b/VERSION
index 378c127..b977a66 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-v0.7.6
+v0.7.7
index 4a52abf..d8d05e0 100644 (file)
@@ -20,6 +20,10 @@ clean:
 
 check: bin/jwrapper tests/wildcards.javap
        mkdir -p tmp
+       bin/jwrapper -v -u stub -o tests/statics.nit tests/statics.javap
+       ../../bin/nitpick -q tests/statics.nit
+       bin/jwrapper -v -u comment -o tests/generics.nit tests/generics.javap
+       ../../bin/nitpick -q tests/generics.nit
        bin/jwrapper -v -u comment -o tests/long.nit tests/long.javap
        ../../bin/nitpick -q tests/long.nit
        bin/jwrapper -v -u comment -o tests/inits.nit tests/inits.javap
@@ -31,6 +35,7 @@ check: bin/jwrapper tests/wildcards.javap
        bin/jwrapper -v -u comment -o tests/wildcards.nit tests/wildcards.javap
        ../../bin/nitpick -q tests/wildcards.nit
        make -C examples/queue/ check
+       make -C examples/java_api/ check
 
 check-libs: bin/jwrapper
        # This config dependent rule must be tweaked according to each system
index e26ba9c..e01cb00 100644 (file)
@@ -4,11 +4,12 @@ all: android_api.nit
 
 java_api.nit:
        mkdir -p tmp
-       ../../bin/jwrapper -v -u comment -o java_api.nit -r "^java" $(ANDROID_JAR)
+       ../../bin/jwrapper -vv -u comment -o java_api.nit -r "^(java|javax|junit|org)" $(ANDROID_JAR) -i ../../../../lib/java/collections.nit
+       echo "+ Disabled functions: `grep '#\s*fun' $@ | wc -l` / `grep '^\s*fun' $@ | wc -l`"
 
 android_api.nit: java_api.nit
-       ../../bin/jwrapper -v -u comment -o android_api.nit -r "^android" -i java_api.nit $(ANDROID_JAR)
-       echo "+ Disabled functions: `grep '#    fun' $@ | wc -l` / `grep '^     fun' $@ | wc -l`"
+       ../../bin/jwrapper -vv -u comment -o android_api.nit -r "^(android|com.android)" -i java_api.nit $(ANDROID_JAR) -i ../../../../lib/java/collections.nit
+       echo "+ Disabled functions: `grep '#\s*fun' $@ | wc -l` / `grep '^\s*fun' $@ | wc -l`"
 
        # Insert an import between the 2 modules
        sed -i -e "s/import java/import java\nimport java_api/" android_api.nit
diff --git a/contrib/jwrapper/examples/java_api/.gitignore b/contrib/jwrapper/examples/java_api/.gitignore
new file mode 100644 (file)
index 0000000..f2f6834
--- /dev/null
@@ -0,0 +1,5 @@
+java_api.nit
+api_user
+api_user.res
+api_user.jar
+tmp/
diff --git a/contrib/jwrapper/examples/java_api/Makefile b/contrib/jwrapper/examples/java_api/Makefile
new file mode 100644 (file)
index 0000000..a98f013
--- /dev/null
@@ -0,0 +1,31 @@
+RT_JAR ?= /usr/lib/jvm/default-java/jre/lib/rt.jar
+
+all: api_user
+
+java_api.nit:
+       mkdir -p tmp
+       ../../bin/jwrapper -vv -u comment -o java_api.nit $(RT_JAR) \
+               -r "^java.(lang|util|io)" -i ../../../../lib/java/collections.nit
+       echo "+ Disabled functions: `grep '#\s*fun' $@ | wc -l` / `grep '^\s*fun' $@ | wc -l`"
+
+api_user: java_api.nit
+       # Using --semi-global makes it much faster
+       time -f "%E k:%S u:%U" ../../../../bin/nitc -v api_user.nit --semi-global
+
+check: api_user
+       ./api_user > api_user.res
+       diff api_user.sav api_user.res
+
+check-more-java:
+       mkdir -p tmp
+       ../../bin/jwrapper -vv -u comment -o java_api.nit $(RT_JAR) \
+               -r "^(java|org)" -i ../../../../lib/java/collections.nit
+       echo "+ Disabled functions: `grep '#\s*fun' $@ | wc -l` / `grep '^\s*fun' $@ | wc -l`"
+
+       # This may take a while...
+       time -f "%E k:%S u:%U" ../../../../bin/nitc -v api_user.nit --no-cc
+
+       # Don't compile the C only the Java
+       make -C nit_compile Nit_rt.class
+
+.PHONY: api_user java_api.nit
diff --git a/contrib/jwrapper/examples/java_api/api_user.nit b/contrib/jwrapper/examples/java_api/api_user.nit
new file mode 100644 (file)
index 0000000..b0f5a0c
--- /dev/null
@@ -0,0 +1,34 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import java_api
+
+# Get a Java string
+var str = java_lang_integer_to_string_int(5678)
+
+# Do some Java side printing
+var stdout = java_lang_system_out
+stdout.println_int 1234
+stdout.println_String str
+
+# Test a generic list
+var list = new Java_util_ArrayList
+
+print list.is_empty
+assert list.is_empty
+
+print list.size
+assert list.size == 0
+
+list.clear
diff --git a/contrib/jwrapper/examples/java_api/api_user.sav b/contrib/jwrapper/examples/java_api/api_user.sav
new file mode 100644 (file)
index 0000000..86d17d1
--- /dev/null
@@ -0,0 +1,4 @@
+1234
+5678
+true
+0
index a07438c..fc9a0ae 100644 (file)
@@ -1,5 +1,5 @@
 # Nit test program
-user_test: queue.nit $(shell ../../../../bin/nitls -M user_test.nit) ../../../../bin/nitc
+user_test: queue.nit $(shell ../../../../bin/nitls -M user_test.nit) ../../../../bin/nitc ../../bin/jwrapper
        CLASSPATH=`pwd` ../../../../bin/nitc user_test.nit
 
        # Manually add our class file to the Jar for easy access
index dc46557..718a446 100644 (file)
@@ -44,8 +44,8 @@ type_bound
        | {head:} full_class_name;
 
 generic_identifier
-       = full_class_name
-       | wildcard;
+       = {class:} full_class_name
+       | {wildcard:} wildcard;
 
 full_class_name
        = {tail:} full_class_name separator class_name
index 5e3d770..eed951a 100644 (file)
@@ -66,11 +66,16 @@ class CodeGenerator
                file_out.write "\n"
 
                for key, jclass in model.classes do
+                       # Skip anonymous classes
+                       if jclass.class_type.is_anonymous then continue
+
+                       # Skip classes with an invalid name at the Java language level
+                       if jclass.class_type.extern_equivalent.has("-") then continue
 
                        generate_class_header(jclass.class_type)
 
                        for id, signatures in jclass.methods do
-                               for signature in signatures do
+                               for signature in signatures do if not signature.is_static then
                                        generate_method(jclass, id, id, signature.return_type, signature.params)
                                        file_out.write "\n"
                                end
@@ -80,17 +85,41 @@ class CodeGenerator
                        for constructor in jclass.constructors do
                                var complex = jclass.constructors.length != 1 and constructor.params.not_empty
                                var base_name = if complex then "from" else ""
-                               var name = jclass.nit_name_for(base_name, constructor.params, complex)
+                               var name = jclass.nit_name_for(base_name, constructor.params, complex, false)
 
                                generate_constructor(jclass, constructor, name)
                        end
 
                        # Attributes
-                       for id, java_type in jclass.attributes do
-                               generate_getter_setter(jclass, id, java_type)
+                       for id, attribute in jclass.attributes do if not attribute.is_static then
+                               generate_getter_setter(jclass, id, attribute)
                        end
 
+                       # JNI services
+                       generate_jni_services jclass.class_type
+
+                       # Close the class
                        file_out.write "end\n\n"
+
+                       # Static functions as top-level methods
+                       var static_functions_prefix = jclass.class_type.extern_name.to_snake_case
+                       for id, signatures in jclass.methods do
+                               for signature in signatures do if signature.is_static then
+                                       var nit_id = static_functions_prefix + "_" + id
+                                       generate_method(jclass, id, nit_id, signature.return_type, signature.params, is_static=true)
+                                       file_out.write "\n"
+                               end
+                       end
+
+                       # Static attributes as top-level getters and setters
+                       for id, attribute in jclass.attributes do if attribute.is_static then
+                               generate_getter_setter(jclass, id, attribute)
+                       end
+
+                       # Primitive arrays
+                       for d in [1..opt_arrays.value] do
+                               generate_primitive_array(jclass, d)
+                       end
                end
 
                if stub_for_unknown_types then
@@ -123,8 +152,8 @@ class CodeGenerator
        private fun generate_class_header(jtype: JavaType)
        do
                var nit_type = model.java_to_nit_type(jtype)
-               file_out.write "# Java class: {jtype.to_package_name}\n"
-               file_out.write "extern class {nit_type} in \"Java\" `\{ {jtype.to_package_name} `\}\n"
+               file_out.write "# Java class: {jtype}\n"
+               file_out.write "extern class {nit_type} in \"Java\" `\{ {jtype.extern_equivalent} `\}\n"
                file_out.write "\tsuper JavaObject\n\n"
        end
 
@@ -132,105 +161,111 @@ class CodeGenerator
        do
                var nit_type = jtype.extern_name
 
-               file_out.write "extern class {nit_type} in \"Java\" `\{ {jtype.to_package_name} `\}\n"
+               file_out.write "extern class {nit_type} in \"Java\" `\{ {jtype.extern_equivalent} `\}\n"
                file_out.write "\tsuper JavaObject\n\nend\n"
        end
 
-       private fun generate_method(java_class: JavaClass, jmethod_id, method_id: String,
-               jreturn_type: JavaType, jparam_list: Array[JavaType])
+       private fun generate_method(java_class: JavaClass, java_method_id, method_id: String,
+               java_return_type: JavaType, java_params: Array[JavaType], is_static: nullable Bool)
        do
-               var java_params = ""
-               var nit_params  = ""
+               var java_args = new Array[String]
+               var nit_params = new Array[String]
                var nit_id = "arg"
                var nit_id_no = 0
-               var nit_types = new Array[NitType]
-               var comment = ""
+               var c = ""
 
                # Parameters
-               for i in [0..jparam_list.length[ do
-                       var jparam = jparam_list[i]
+               for jparam in java_params do
                        var nit_type = model.java_to_nit_type(jparam)
 
-                       if not nit_type.is_known and comment_unknown_types then comment = "#"
-                       if jparam.is_primitive_array then comment = "#"
+                       if not nit_type.is_known and comment_unknown_types then c = "#"
+                       if jparam.is_vararg then c = "#"
 
-                       var cast = jparam.param_cast
-
-                       nit_types.add(nit_type)
-
-                       if i == jparam_list.length - 1 then
-                               java_params += "{cast}{nit_id}{nit_id_no}"
-                               nit_params  += "{nit_id}{nit_id_no}: {nit_type}"
-                       else
-                               java_params += "{cast}{nit_id}{nit_id_no}" + ", "
-                               nit_params  += "{nit_id}{nit_id_no}: {nit_type}, "
-                       end
+                       java_args.add "{jparam.param_cast}{nit_id}{nit_id_no}"
+                       nit_params.add "{nit_id}{nit_id_no}: {nit_type}"
 
                        nit_id_no += 1
                end
 
-               # Method documentation
-               var doc = "\t# Java implementation: {java_class}.{jmethod_id}\n"
-
                # Method identifier
                method_id = method_id.to_nit_method_name
-               method_id = java_class.nit_name_for(method_id, jparam_list, java_class.methods[jmethod_id].length > 1)
+               method_id = java_class.nit_name_for(method_id, java_params, java_class.methods[java_method_id].length > 1, is_static == true)
+
+               # Build the signature
                var nit_signature = new Array[String]
+               nit_signature.add "fun {method_id}"
+               if not java_params.is_empty then nit_signature.add "({nit_params.join(", ")})"
+
+               # Return value
+               var return_type = null
+               if not java_return_type.is_void then
+                       return_type = model.java_to_nit_type(java_return_type)
 
-               nit_signature.add "\tfun {method_id}"
+                       if not return_type.is_known and comment_unknown_types then c = "#"
+                       if java_return_type.is_vararg then c = "#"
 
-               if not jparam_list.is_empty then
-                       nit_signature.add "({nit_params})"
+                       nit_signature.add ": " + return_type.to_s
                end
 
-               var return_type = null
-               if not jreturn_type.is_void then
-                       return_type = model.java_to_nit_type(jreturn_type)
+               # Build the call in Java
+               var java_call
+               if is_static == true then
+                       java_call = java_class.class_type.package_name
+               else java_call = "self"
+               java_call += ".{java_method_id}({java_args.join(", ")})"
 
-                       if not return_type.is_known and comment_unknown_types then comment = "#"
-                       if jreturn_type.is_primitive_array then comment = "#"
+               if return_type != null then java_call = "return {java_return_type.return_cast}" + java_call
 
-                       nit_signature.add ": {return_type} "
-               end
+               # Tabulation
+               var t = "\t"
+               if is_static == true then t = ""
+               var ct = c+t
 
-               file_out.write doc
-               file_out.write comment + nit_signature.join
-
-               if comment == "#" then
-                       file_out.write " in \"Java\" `\{\n{comment}\t\tself.{jmethod_id}({java_params});\n{comment}\t`\}\n"
-               # Methods with return type
-               else if return_type != null then
-                       file_out.write " in \"Java\" `\{\n{comment}\t\treturn {jreturn_type.return_cast}self.{jmethod_id}({java_params});\n{comment}\t`\}\n"
-               # Methods without return type
-               else if jreturn_type.is_void then
-                       file_out.write " in \"Java\" `\{\n{comment}\t\tself.{jmethod_id}({java_params});\n{comment}\t`\}\n"
-               # No copy
-               else
-                       file_out.write " in \"Java\" `\{\n{comment}\t\tself.{jmethod_id}({java_params});\n{comment}\t`\}\n"
-               end
+               # Write
+               file_out.write """
+{{{t}}}# Java implementation: {{{java_return_type}}} {{{java_class}}}.{{{java_method_id}}}({{{java_params.join(", ")}}})
+{{{ct}}}{{{nit_signature.join}}} in "Java" `{
+{{{ct}}}       {{{java_call}}};
+{{{ct}}}`}
+"""
        end
 
        # Generate getter and setter to access an attribute, of field
-       private fun generate_getter_setter(java_class: JavaClass, java_id: String, java_type: JavaType)
+       private fun generate_getter_setter(java_class: JavaClass, java_id: String,
+               attribute: JavaAttribute)
        do
+               var java_type = attribute.java_type
                var nit_type = model.java_to_nit_type(java_type)
-               var nit_id = java_id.to_nit_method_name
-               nit_id = java_class.nit_name_for(nit_id, [java_type], false)
+
+               var nit_id = java_id
+               if attribute.is_static then nit_id = java_class.class_type.extern_name.to_snake_case + "_" + nit_id
+               nit_id = nit_id.to_nit_method_name
+               nit_id = java_class.nit_name_for(nit_id, [java_type], false, attribute.is_static)
 
                var c = ""
                if not nit_type.is_known and comment_unknown_types then c = "#"
-               if java_type.is_primitive_array then c = "#"
+               if java_type.is_vararg then c = "#"
+
+               var recv
+               if attribute.is_static then
+                       recv = java_class.class_type.package_name
+               else recv = "self"
+
+               # Tabulation
+               var t = "\t"
+               if attribute.is_static then t = ""
+               var ct = c+t
 
                file_out.write """
-       # Java getter: {{{java_class}}}.{{{java_id}}}
-{{{c}}}        fun {{{nit_id}}}: {{{nit_type}}} in "Java" `{
-{{{c}}}                return self.{{{java_id}}};
-{{{c}}}        `}
+{{{t}}}# Java getter: {{{java_class}}}.{{{java_id}}}
+{{{ct}}}fun {{{nit_id}}}: {{{nit_type}}} in "Java" `{
+{{{ct}}}       return {{{recv}}}.{{{java_id}}};
+{{{ct}}}`}
 
-       # Java setter: {{{java_class}}}.{{{java_id}}}
-{{{c}}}        fun {{{nit_id}}}=(value: {{{nit_type}}}) in "Java" `{
-{{{c}}}                self.{{{java_id}}} = value;
-{{{c}}}        `}
+{{{t}}}# Java setter: {{{java_class}}}.{{{java_id}}}
+{{{ct}}}fun {{{nit_id}}}=(value: {{{nit_type}}}) in "Java" `{
+{{{ct}}}       {{{recv}}}.{{{java_id}}} = value;
+{{{ct}}}`}
 
 """
        end
@@ -255,7 +290,7 @@ class CodeGenerator
                                param_id = param_id.successor(1)
 
                                if not nit_type.is_known and comment_unknown_types then c = "#"
-                               if java_type.is_primitive_array then c = "#"
+                               if java_type.is_vararg then c = "#"
                        end
 
                        nit_params_s = "(" + nit_params.join(", ") + ")"
@@ -265,11 +300,62 @@ class CodeGenerator
                file_out.write """
        # Java constructor: {{{java_class}}}
 {{{c}}}        new {{{name}}}{{{nit_params_s}}} in "Java" `{
-{{{c}}}                return new {{{java_class}}}({{{java_params_s}}});
+{{{c}}}                return new {{{java_class.class_type.package_name}}}({{{java_params_s}}});
 {{{c}}}        `}
 
 """
        end
+
+       private fun generate_primitive_array(java_class: JavaClass, dimensions: Int)
+       do
+               var base_java_type = java_class.class_type
+               var java_type = base_java_type.clone
+               java_type.array_dimension = dimensions
+
+               var base_nit_type = model.java_to_nit_type(base_java_type)
+               var nit_type = model.java_to_nit_type(java_type)
+
+               file_out.write """
+# Java primitive array: {{{java_type}}}
+extern class {{{nit_type}}} in "Java" `{ {{{java_type.extern_equivalent}}} `}
+       super AbstractJavaArray[{{{base_nit_type}}}]
+
+       # Get a new array of the given `size`
+       new(size: Int) in "Java" `{ return new {{{base_java_type}}}[(int)size]; `}
+
+       redef fun [](i) in "Java" `{ return self[(int)i]; `}
+
+       redef fun []=(i, e) in "Java" `{ self[(int)i] = e; `}
+
+       redef fun length in "Java" `{ return self.length; `}
+
+"""
+               generate_jni_services(java_type)
+               file_out.write """
+end
+
+"""
+       end
+
+       # Generate JNI related services
+       #
+       # For now, mostly avoid issue #845, but more services could be generated as needed.
+       private fun generate_jni_services(java_type: JavaType)
+       do
+               var nit_type = model.java_to_nit_type(java_type)
+
+               file_out.write """
+       redef fun new_global_ref import sys, Sys.jni_env `{
+               Sys sys = {{{nit_type}}}_sys(self);
+               JNIEnv *env = Sys_jni_env(sys);
+               return (*env)->NewGlobalRef(env, self);
+       `}
+
+       redef fun pop_from_local_frame_with_env(jni_env) `{
+               return (*jni_env)->PopLocalFrame(jni_env, self);
+       `}
+"""
+       end
 end
 
 redef class Sys
@@ -283,10 +369,16 @@ redef class Sys
                "protected", "public", "return", "self", "super", "then", "true", "type", "var", "while",
 
        # Top-level methods
-               "class_name", "get_time", "hash", "is_same_type", "is_same_instance", "output",
+               "class_name", "get_time", "hash", "inspect", "inspect_head", "is_same_type",
+               "is_same_instance", "object_id", "output", "output_class_name", "sys", "to_s",
 
        # Pointer or JavaObject methods
                "free"])
+
+       # Name of methods used at the top-level
+       #
+       # Used by `JavaClass::nit_name_for` with static properties.
+       private var top_level_used_names = new HashSet[String]
 end
 
 redef class String
@@ -317,13 +409,13 @@ end
 
 redef class JavaClass
        # Property names used in this class
-       private var used_name = new HashSet[String]
+       private var used_names = new HashSet[String]
 
        # Get an available property name for the Java property with `name` and parameters
        #
        # If `use_parameters_name` then expect that there will be conflicts,
        # so use the types of `parameters` to build the name.
-       private fun nit_name_for(name: String, parameters: Array[JavaType], use_parameters_name: Bool): String
+       private fun nit_name_for(name: String, parameters: Array[JavaType], use_parameters_name: Bool, is_static: Bool): String
        do
                # Append the name of each parameter
                if use_parameters_name then
@@ -332,15 +424,21 @@ redef class JavaClass
                        end
                end
 
+               # Set of property names, local or top-level
+               var used_names
+               if is_static then
+                       used_names = sys.top_level_used_names
+               else used_names = self.used_names
+
                # As a last resort, append numbers to the name
                var base_name = name
                var count = 1
-               while used_name.has(name) do
+               while used_names.has(name) do
                        name = base_name + count.to_s
                        count += 1
                end
 
-               used_name.add name
+               used_names.add name
                return name
        end
 end
index c3e5f98..fe81c88 100644 (file)
@@ -80,9 +80,20 @@ end
 redef class Nproperty_declaration_method
        redef fun accept_visitor(v)
        do
+               var is_static = false
+               var modifiers = n_modifier
+               if modifiers != null then is_static = modifiers.has_static
+
                var id = n_identifier.text
                var return_jtype = n_type.to_java_type
 
+               # Generic parameters
+               var n_params = n_generic_parameters
+               var generic_params
+               if n_params != null then
+                       generic_params = n_params.n_parameters.to_a
+               else generic_params = new Array[JavaType]
+
                # Collect parameters
                var n_parameters = n_parameters
                var params
@@ -90,7 +101,7 @@ redef class Nproperty_declaration_method
                        params = n_parameters.to_a
                else params = new Array[JavaType]
 
-               var method = new JavaMethod(return_jtype, params)
+               var method = new JavaMethod(is_static, return_jtype, params, generic_params)
                v.java_class.methods[id].add method
        end
 end
@@ -106,7 +117,14 @@ redef class Nproperty_declaration_constructor
                        params = n_parameters.to_a
                else params = new Array[JavaType]
 
-               var method = new JavaConstructor(params)
+               # Generic parameters
+               var n_params = n_generic_parameters
+               var generic_params
+               if n_params != null then
+                       generic_params = n_params.n_parameters.to_a
+               else generic_params = new Array[JavaType]
+
+               var method = new JavaConstructor(params, generic_params)
                v.java_class.constructors.add method
        end
 end
@@ -122,7 +140,11 @@ redef class Nproperty_declaration_attribute
                var brackets = n_brackets
                if brackets != null then jtype.array_dimension += brackets.children.length
 
-               v.java_class.attributes[id] = jtype
+               var is_static = false
+               var modifiers = n_modifier
+               if modifiers != null then is_static = modifiers.has_static
+
+               v.java_class.attributes[id] = new JavaAttribute(is_static, jtype)
        end
 end
 
@@ -153,7 +175,6 @@ redef class Nbase_type
        private fun to_java_type: JavaType
        do
                # By default, everything is bound by object
-               # TODO use a more precise bound
                var jtype = new JavaType
                jtype.identifier.add_all(["java", "lang", "object"])
                return jtype
@@ -189,6 +210,41 @@ redef class Nbase_type_void
        end
 end
 
+redef class Nbase_type_extends
+       redef fun to_java_type do return n_generic_identifier.to_java_type
+end
+
+redef class Nbase_type_super
+       redef fun to_java_type
+       do
+               var bounds = n_type_bound.to_a
+
+               # Java use more than one lower bound,
+               # it can't be translated statically to Nit,
+               # so we use the only the first one.
+               # This may cause problems on complex generic types,
+               # but these cases can be handled manually.
+               return bounds.first
+       end
+end
+
+redef class Ngeneric_identifier
+       private fun to_java_type: JavaType is abstract
+end
+
+redef class Ngeneric_identifier_class
+       redef fun to_java_type do return n_full_class_name.to_java_type
+end
+
+redef class Ngeneric_identifier_wildcard
+       redef fun to_java_type
+       do
+               var jtype = new JavaType
+               jtype.identifier.add_all(["java", "lang", "Object"])
+               return jtype
+       end
+end
+
 redef class Nfull_class_name
        # All the identifiers composing this class name
        private fun to_a: Array[String] is abstract
@@ -257,3 +313,32 @@ redef class Nparameter
                return jtype
        end
 end
+
+redef class Nodes
+       private fun has_static: Bool
+       do
+               for modifier in depth do
+                       if modifier isa NToken and modifier.text == "static" then return true
+               end
+
+               return false
+       end
+end
+
+redef class Ntype_bound
+       # Get the types composing this bound
+       private fun to_a: Array[JavaType] is abstract
+end
+
+redef class Ntype_bound_head
+       redef fun to_a do return [n_full_class_name.to_java_type]
+end
+
+redef class Ntype_bound_tail
+       redef fun to_a
+       do
+               var a = n_type_bound.to_a
+               a.add n_full_class_name.to_java_type
+               return a
+       end
+end
index 04878da..0a84fa9 100644 (file)
@@ -44,7 +44,7 @@ var opt_output = new OptionString("Output file", "-o")
 var opt_regex = new OptionString("Regex pattern to filter classes in Jar archives", "-r")
 var opt_help = new OptionBool("Show this help message", "-h", "--help")
 
-opts.add_option(opt_output, opt_unknown, opt_extern_class_prefix, opt_libs, opt_regex, opt_cast_objects, opt_verbose, opt_help)
+opts.add_option(opt_output, opt_unknown, opt_extern_class_prefix, opt_libs, opt_regex, opt_cast_objects, opt_arrays, opt_verbose, opt_help)
 opts.parse args
 
 if opts.errors.not_empty or opts.rest.is_empty or opt_help.value then
@@ -192,6 +192,9 @@ var visitor = new JavaVisitor(model)
 visitor.enter_visit root_node
 sys.perfs["core model"].add clock.lapse
 
+model.resolve_types
+sys.perfs["core resolve"].add clock.lapse
+
 if opt_verbose.value > 0 then print "# Generating Nit code"
 
 var use_comment = opt_unknown.value == 0
@@ -203,4 +206,15 @@ sys.perfs["code generator"].add clock.lapse
 if opt_verbose.value > 1 then
        print "# Performance Analysis:"
        print sys.perfs
+
+       print "# {model.unknown_types.length} unknown types:"
+       var c = 0
+       for id, ntype in model.unknown_types do
+               print "* {id}"
+               c += 1
+               if c > 100 then
+                       print "* ..."
+                       break
+               end
+       end
 end
index 8d6da40..50d54f1 100644 (file)
@@ -24,7 +24,14 @@ import opts
 import jtype_converter
 
 class JavaType
+       super Cloneable
+
+       # Identifiers composing the namespace and class name
+       #
+       # An array of all the names that would be separated by `.`.
+       # Each name may contain `$`.
        var identifier = new Array[String]
+
        var generic_params: nullable Array[JavaType] = null
 
        # Is this a void return type?
@@ -33,6 +40,16 @@ class JavaType
        # Is this type a vararg?
        var is_vararg = false is writable
 
+       # Is this type based on an anonymous class?
+       var is_anonymous: Bool is lazy do
+               for id in identifier do
+                       for part in id.split("$") do
+                               if part.chars.first.is_digit then return true
+                       end
+               end
+               return false
+       end
+
        # Has some generic type to be resolved (T extends foo => T is resolved to foo)
        var has_unresolved_types = false
 
@@ -42,8 +59,6 @@ class JavaType
        fun is_primitive_array: Bool do return array_dimension > 0
 
        fun has_generic_params: Bool do return not generic_params == null
-       fun full_id: String do return identifier.join(".")
-       fun id: String do return identifier.last.replace("$", "")
 
        fun return_cast: String do return converter.cast_as_return(self.id)
 
@@ -80,14 +95,27 @@ class JavaType
                        name = prefix + id
                end
 
+               if is_primitive_array then
+                       name += "_" + "Array" * array_dimension
+               end
+
                name = name.replace("-", "_")
                name = name.replace("$", "_")
                return name
        end
 
-       redef fun to_s
-       do
-               var id = self.full_id
+       # Short name of the class, mangled to remove `$` (e.g. `Set`)
+       fun id: String do return identifier.last.replace("$", "")
+
+       # Full name of this class as used in an importation (e.g. `java.lang.Set`)
+       fun package_name: String do return identifier.join(".")
+
+       # Name of this class for the extern declaration in Nit (e.g. `java.lang.Set[]`)
+       fun extern_equivalent: String do return package_name + "[]" * array_dimension
+
+       # Full name of this class with arrays and generic values (e.g. `java.lang.Set<E>[]`)
+       redef fun to_s do
+               var id = self.package_name
 
                if self.is_primitive_array then
                        id += "[]" * array_dimension
@@ -99,34 +127,24 @@ class JavaType
                return id
        end
 
-       # To fully qualified package name
-       # Cuts the primitive array `[]`
-       fun to_package_name: String
+       # Get a copy of `self`
+       redef fun clone
        do
-               var str = self.to_s
-               var len = str.length
-
-               return str.substring(0, len - (2*array_dimension))
-       end
-
-       fun resolve_types(conversion_map: HashMap[String, Array[String]])
-       do
-               if identifier.length == 1 then
-                       var resolved_id = conversion_map.get_or_null(self.id)
-                       if resolved_id != null then self.identifier = new Array[String].from(resolved_id)
-               end
-
-               if self.has_generic_params then
-                       for params in generic_params do params.resolve_types(conversion_map)
-               end
+               var jtype = new JavaType
+               jtype.identifier = identifier
+               jtype.generic_params = generic_params
+               jtype.is_void = is_void
+               jtype.is_vararg = is_vararg
+               jtype.array_dimension = array_dimension
+               return jtype
        end
 
        # Comparison based on fully qualified named
        redef fun ==(other) do return other isa JavaType and
-               self.full_id == other.full_id and
-               self.is_primitive_array == other.is_primitive_array
+               self.package_name == other.package_name and
+               self.array_dimension == other.array_dimension
 
-       redef fun hash do return self.full_id.hash
+       redef fun hash do return self.package_name.hash
 end
 
 class NitType
@@ -148,7 +166,7 @@ class JavaClass
        var class_type: JavaType
 
        # Attributes of this class
-       var attributes = new HashMap[String, JavaType]
+       var attributes = new HashMap[String, JavaAttribute]
 
        # Methods of this class organized by their name
        var methods = new MultiHashMap[String, JavaMethod]
@@ -160,6 +178,58 @@ class JavaClass
        var imports = new HashSet[NitModule]
 
        redef fun to_s do return class_type.to_s
+
+       # Resolve the types in `other` in the context of this class
+       private fun resolve_types_of(other: JavaClass)
+       do
+               # Methods
+               for mid, method in other.methods do
+                       for signature in method do
+                               self.resolve(signature.return_type, signature.generic_params)
+                               for param in signature.params do self.resolve(param, signature.generic_params)
+                       end
+               end
+
+               # Constructors
+               for signature in other.constructors do
+                       for param in signature.params do self.resolve(param, signature.generic_params)
+               end
+
+               # Attributes
+               for aid, attribute in other.attributes do
+                       self.resolve attribute.java_type
+               end
+       end
+
+       # Resolve `java_type` in the context of this class
+       #
+       # Replace, in place, parameter types by their bound.
+       private fun resolve(java_type: JavaType, property_generic_params: nullable Array[JavaType])
+       do
+               # Skip types with a full package name
+               if java_type.identifier.length != 1 then return
+
+               # Skip primitive types
+               if converter.type_map.keys.has(java_type.id) then return
+
+               # Gather the generic parameters of the method, then the class
+               var params = new Array[JavaType]
+               if property_generic_params != null then params.add_all property_generic_params
+               var class_generic_params = class_type.generic_params
+               if class_generic_params != null then params.add_all class_generic_params
+
+               # Skip if there is not parameters usable to resolve
+               if params.is_empty then return
+
+               for param in params do
+                       if param.identifier == java_type.identifier then
+                               # Found a marching parameter type
+                               # TODO use a more precise bound
+                               java_type.identifier = ["java", "lang", "Object"]
+                               return
+                       end
+               end
+       end
 end
 
 # Model of all the Java class analyzed in one run
@@ -171,15 +241,15 @@ class JavaModel
        # Add a class in `classes`
        fun add_class(jclass: JavaClass)
        do
-               var key = jclass.class_type.full_id
+               var key = jclass.class_type.package_name
                classes[key] = jclass
        end
 
        # Unknown types, not already wrapped and not in this pass
-       private var unknown_types = new HashMap[JavaType, NitType]
+       var unknown_types = new HashMap[JavaType, NitType]
 
        # Wrapped types, or classes analyzed in this pass
-       private var known_types = new HashMap[JavaType, NitType]
+       var known_types = new HashMap[JavaType, NitType]
 
        # Get the `NitType` corresponding to the `JavaType`
        #
@@ -203,16 +273,17 @@ class JavaModel
                end
 
                # Is being wrapped in this pass?
-               var key = jtype.full_id
+               var key = jtype.package_name
                if classes.keys.has(key) then
-                       var nit_type = new NitType(jtype.extern_name)
-                       known_types[jtype] = nit_type
-
-                       return nit_type
+                       if jtype.array_dimension <= opt_arrays.value then
+                               var nit_type = new NitType(jtype.extern_name)
+                               known_types[jtype] = nit_type
+                               return nit_type
+                       end
                end
 
                # Search in lib
-               var nit_type = find_extern_class[jtype.full_id]
+               var nit_type = find_extern_class[jtype.extern_equivalent]
                if nit_type != null then
                        known_types[jtype] = nit_type
                        return nit_type
@@ -224,21 +295,62 @@ class JavaModel
                unknown_types[jtype] = nit_type
                return nit_type
        end
+
+       # Resolve the types in methods and attributes of this class
+       fun resolve_types
+       do
+               for id, java_class in classes do
+                       java_class.resolve_types_of java_class
+
+                       # Ask nester classes for resolve too
+                       var matches = id.search_all("$")
+                       for match in matches do
+                               var nester_name = id.substring(0, match.from)
+                               if classes.keys.has(nester_name) then
+                                       var nester = classes[nester_name]
+                                       nester.resolve_types_of java_class
+                               end
+                       end
+               end
+       end
+end
+
+# A property to a Java class
+abstract class JavaProperty
+
+       # Is this property marked static?
+       var is_static: Bool
 end
 
 # A Java method, with its signature
 class JavaMethod
+       super JavaProperty
+
        # Type returned by the method
        var return_type: JavaType
 
        # Type of the arguments of the method
        var params: Array[JavaType]
+
+       # Generic parameters of this method
+       var generic_params: Array[JavaType]
+end
+
+# An attribute in a Java class
+class JavaAttribute
+       super JavaProperty
+
+       # Type of the attribute
+       var java_type: JavaType
 end
 
 # A Java method, with its signature
 class JavaConstructor
        # Type of the parameters of this constructor
        var params: Array[JavaType]
+
+       # Generic parameters of this constructor
+       var generic_params: Array[JavaType]
 end
 
 # A Nit module, use to import the referenced extern classes
@@ -257,7 +369,7 @@ end
 redef class Sys
        # Collection of Java classes already wrapped in the library
        #
-       # * The key is from `JavaType.full_id`.
+       # * The key uses `JavaType.to_s`.
        # * The value is the corresponding `NitType`.
        var find_extern_class: DefaultMap[String, nullable NitType] is lazy do
                var map = new DefaultMap[String, nullable NitType](null)
@@ -290,16 +402,16 @@ redef class Sys
                grep.wait
 
                # Sort out the modules, Nit class names and Java types
-               var regex = """(.+):\\s*extern +class +([a-zA-Z0-9_]+) *in *"Java" *`\\{ *([a-zA-Z0-9.$/]+) *`\\}""".to_re
+               var regex = """(.+):\\s*extern +class +([a-zA-Z0-9_]+) *in *"Java" *`\\{(.+)`\\}""".to_re
                for line in lines do
                        var matches = line.search_all(regex)
                        for match in matches do
                                var path = match[1].to_s
                                var nit_name = match[2].to_s
-                               var java_name = match[3].to_s
+                               var java_name = match[3].to_s.trim
 
                                # Debug code
-                               # print "+ Found {nit_name}:{java_name} at {path}"
+                               # print "+ Found {nit_name}: {java_name} at {path}"
 
                                var mod = modules.get_or_null(path)
                                if mod == null then
@@ -322,6 +434,9 @@ redef class Sys
 
        # Libraries to search for existing wrappers
        var opt_libs = new OptionArray("Paths to libraries with wrappers of Java classes ('auto' to use the full Nit lib)", "-i")
+
+       # Generate the primitive array version of each class up to the given depth
+       var opt_arrays = new OptionInt("Depth of the primitive array for each wrapped class (default: 1)", 1, "-a")
 end
 
 redef class Text
diff --git a/contrib/jwrapper/tests/generics.javap b/contrib/jwrapper/tests/generics.javap
new file mode 100644 (file)
index 0000000..0753c90
--- /dev/null
@@ -0,0 +1,6 @@
+public abstract class android.os.asynctask<params, progress, result> {
+  public android.os.asynctask();
+  public final android.os.asynctask$status getstatus();
+  public final result get(long, java.util.concurrent.timeunit) throws java.lang.interruptedexception, java.util.concurrent.executionexception, java.util.concurrent.timeoutexception;
+  public final android.os.asynctask<params, progress, result> execute(params...);
+}
diff --git a/contrib/jwrapper/tests/statics.javap b/contrib/jwrapper/tests/statics.javap
new file mode 100644 (file)
index 0000000..a10cc75
--- /dev/null
@@ -0,0 +1,18 @@
+public final class com.oracle.net.Sdp {
+  public static java.net.Socket openSocket() throws java.io.IOException;
+  public static java.net.ServerSocket openServerSocket() throws java.io.IOException;
+  public static java.nio.channels.SocketChannel openSocketChannel() throws java.io.IOException;
+  public static java.nio.channels.ServerSocketChannel openServerSocketChannel() throws java.io.IOException;
+}
+public class com.sun.activation.registries.LogSupport {
+  public static void log(java.lang.String);
+  public static void log(java.lang.String, java.lang.Throwable);
+  public static boolean isLoggable();
+}
+public class com.sun.activation.registries.MailcapTokenizer {
+  public static final int UNKNOWN_TOKEN;
+}
+public final class com.sun.beans.TypeResolver {
+  public com.sun.beans.TypeResolver();
+  public static java.lang.reflect.Type resolveInClass(java.lang.Class<?>, java.lang.reflect.Type);
+}
index 323a84e..b5c884b 100644 (file)
@@ -52,6 +52,12 @@ class Config
        # XML tag used for pattern recognition
        fun tag_title: String do return "title"
 
+       # XML tag of the link to act upon
+       fun tag_link: String do return "link"
+
+       # Are the feeds at `rss_source_urls` compressed?
+       var compressed: nullable Bool
+
        # Action to apply on each selected RSS element
        fun act_on(element: Element)
        do
@@ -131,6 +137,7 @@ class Downloader
                var elements = new HashSet[Element]
                for rss_url in config.rss_source_urls do
                        var rss = rss_url.fetch_rss_content
+                       if config.compressed == true then rss = rss.gunzip
                        elements.add_all rss.to_rss_elements
                end
 
@@ -144,7 +151,7 @@ class Downloader
 
                if sys.verbose then
                        print "\n# {matches.length} matching elements:"
-                       print matches.join("\n")
+                       print "* " + matches.join("\n* ")
                        print "\n# Downloading..."
                end
 
@@ -155,13 +162,13 @@ class Downloader
                                # Do not download a file that is not unique according to `unique_id`
                                if not element.is_unique_exception(config) then
                                        # We make some exceptions
-                                       if sys.verbose then print "File in log, skipping {element}"
+                                       if sys.verbose then print "- Skipping {element}"
                                        continue
                                end
                        end
 
                        # Download element
-                       if sys.verbose then print "Acting on {element}"
+                       if sys.verbose then print "+ Acting on {element}"
 
                        tool_config.act_on element
 
@@ -256,23 +263,36 @@ redef class Text
        fun to_rss_elements: Array[Element]
        do
                var xml = to_xml
+               if xml isa XMLError then
+                       print_error "RSS Parse Error: {xml.message}:{xml.location or else "null"}"
+                       return new Array[Element]
+               end
                var items = xml["rss"].first["channel"].first["item"]
 
                var elements = new Array[Element]
                for item in items do
                        var title = item[tool_config.tag_title].first.as(XMLStartTag).data
-                       var link = item["link"].first.as(XMLStartTag).data
+                       var link = item[tool_config.tag_link].first.as(XMLStartTag).data
 
                        elements.add new Element(title, link)
                end
 
                if sys.verbose then
                        print "# Found elements:"
-                       print elements.join("\n")
+                       print "* " + elements.join("\n* ")
                end
 
                return elements
        end
+
+       # Expand the Lempel-Ziv encoded `self`
+       fun gunzip: String
+       do
+               var proc = new ProcessDuplex("gunzip", new Array[String]...)
+               var res = proc.write_and_read(self)
+               assert proc.status == 0 else print_error "gunzip failed: {proc.last_error or else "Unknown"}"
+               return res
+       end
 end
 
 # Implement this method in your module to configure this tool
index 7dd2767..6cec4e1 100644 (file)
 # limitations under the License.
 
 # Android audio services, wraps a part of android audio API
+# This module modifies the default behaviour of the audio loading:
+# It is first loaded from the `res/raw` folder.
+# The file extension is not needed for the `res/raw` loading part.
+# If it didn't work, it is loaded from the `assets` folder.
+# The file extension is needed for the `assets` loading part.
+#
+# `assets` contains the portable version of sounds, since the `res` folder exsists only in android projects.
 #
 # For this example, the sounds "test_sound" and "test_music" are located in the "assets/sounds" folder,
 # they both have ".ogg" extension. "test_sound" is a short sound and "test_music" a music track
@@ -503,28 +510,28 @@ redef class Sound
 
        redef fun load do
                if is_loaded then return
-               var nam = app.asset_manager.open_fd(self.name)
-               if nam.is_java_null then
-                       self.error = new Error("Failed to get file descriptor for " + self.name)
-                       var retval_resources = app.default_soundpool.load_name_rid(app.resource_manager, app.native_activity, self.name)
-                       if retval_resources == -1 then
-                               self.error = new Error("Failed to load" + self.name)
+               var retval_resources = app.default_soundpool.load_name_rid(app.resource_manager, app.native_activity, self.name.strip_extension)
+               if retval_resources == -1 then
+                       self.error = new Error("failed to load" + self.name)
+                       var nam = app.asset_manager.open_fd(self.name)
+                       if nam.is_java_null then
+                               self.error = new Error("Failed to get file descriptor for " + self.name)
                        else
-                               self.soundpool_id = retval_resources
-                               self.soundpool = app.default_soundpool
-                               self.error = null
-                               self.soundpool.error = null
+                               var retval_assets = app.default_soundpool.load_asset_fd_rid(nam)
+                               if retval_assets == -1 then
+                                       self.error = new Error("Failed to load" + self.name)
+                               else
+                                       self.soundpool_id = retval_assets
+                                       self.soundpool = app.default_soundpool
+                                       self.error = null
+                                       self.soundpool.error = null
+                               end
                        end
                else
-                       var retval_assets = app.default_soundpool.load_asset_fd_rid(nam)
-                       if retval_assets == -1 then
-                               self.error = new Error("Failed to load" + self.name)
-                       else
-                               self.soundpool_id = retval_assets
-                               self.soundpool = app.default_soundpool
-                               self.error = null
-                               self.soundpool.error = null
-                       end
+                       self.soundpool_id = retval_resources
+                       self.soundpool = app.default_soundpool
+                       self.error = null
+                       self.soundpool.error = null
                end
                is_loaded = true
        end
@@ -567,26 +574,26 @@ redef class Music
 
        redef fun load do
                if is_loaded then return
-               var nam = app.asset_manager.open_fd(self.name)
-               if nam.is_java_null then
-                       self.error = new Error("Failed to get file descriptor for " + self.name)
-                       var mp_sound_resources = app.default_mediaplayer.load_sound(app.resource_manager.raw_id(self.name), app.native_activity)
-                       if mp_sound_resources.error != null then
-                               self.error = mp_sound_resources.error
+               var mp_sound_resources = app.default_mediaplayer.load_sound(app.resource_manager.raw_id(self.name.strip_extension), app.native_activity)
+               if mp_sound_resources.error != null then
+                       self.error = mp_sound_resources.error
+                       var nam = app.asset_manager.open_fd(self.name)
+                       if nam.is_java_null then
+                               self.error = new Error("Failed to get file descriptor for " + self.name)
                        else
-                               self.media_player = app.default_mediaplayer
-                               self.error = null
-                               self.media_player.error = null
+                               var mp_sound_assets = app.default_mediaplayer.data_source_fd(nam)
+                               if mp_sound_assets.error != null then
+                                       self.error = mp_sound_assets.error
+                               else
+                                       self.media_player = app.default_mediaplayer
+                                       self.error = null
+                                       self.media_player.error = null
+                               end
                        end
                else
-                       var mp_sound_assets = app.default_mediaplayer.data_source_fd(nam)
-                       if mp_sound_assets.error != null then
-                               self.error = mp_sound_assets.error
-                       else
-                               self.media_player = app.default_mediaplayer
-                               self.error = null
-                               self.media_player.error = null
-                       end
+                       self.media_player = app.default_mediaplayer
+                       self.error = null
+                       self.media_player.error = null
                end
                is_loaded = true
        end
@@ -649,7 +656,7 @@ redef class App
 
        # Retrieves a music with a media player in the `assets` folder using its name.
        # Used to play long sounds or musics, can't play multiple sounds simultaneously
-       redef fun load_music(path: String): Music do
+       redef fun load_music(path) do
                var fd = asset_manager.open_fd(path)
                if not fd.is_java_null then
                        return add_to_sounds(default_mediaplayer.data_source_fd(fd)).as(Music)
index 51c0c12..759ed81 100644 (file)
@@ -15,6 +15,8 @@
 # limitations under the License.
 
 # App audio abstraction
+# Default behaviour is loading the audio from the `assets` folder of the project with its name and extension
+# Platforms implementations can modify this comportement
 #
 # Once the application has started (after `App.setup`)
 # use `App.load_sound` to get a sound
@@ -41,7 +43,7 @@ abstract class PlayableAudio
        # Is this already loaded ?
        protected var is_loaded = false is writable
 
-       # load this playable audio
+       # Load this playable audio
        fun load is abstract
 
        # Plays the sound
diff --git a/lib/dom/examples/checker.nit b/lib/dom/examples/checker.nit
new file mode 100644 (file)
index 0000000..cc3b341
--- /dev/null
@@ -0,0 +1,43 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# This file is free software, which comes along with NIT.  This software is
+# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without  even  the implied warranty of  MERCHANTABILITY or  FITNESS FOR A
+# PARTICULAR PURPOSE.  You can modify it is you want,  provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You  are  allowed  to  redistribute it and sell it, alone or is a part of
+# another product.
+
+# Simple XML validity checker using the `dom` module
+module checker
+
+import dom
+
+# Check arguments
+if args.length != 1 then
+       print_error "Usage: checker xml_file"
+       exit 2
+end
+
+var path = args.first
+if not path.file_exists then
+       print_error "Path '{path}' does not exist"
+       exit 3
+end
+
+# Read file
+var content = path.to_path.read_all
+
+# Parse XML
+var xml = content.to_xml
+
+# Check for errors
+if xml isa XMLError then
+       print_error "XML file at '{path}' is invalid:"
+       print_error xml.message
+       var loc = xml.location
+       if loc != null then print_error loc
+       exit 1
+else
+       print "XML file at '{path}' is valid"
+end
diff --git a/lib/java/base.nit b/lib/java/base.nit
new file mode 100644 (file)
index 0000000..0db04a4
--- /dev/null
@@ -0,0 +1,195 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Supporting services for the FFI with Java
+#
+# This modules relies on `Sys::jvm`, `Sys::jni_env` and
+# `Sys::create_default_jvm` to get a handle on a JVM. You can adapt the
+# behavior of the FFI and services in this module by redefing
+# `Sys::create_default_jvm` and supply your own JVM object. You can manage
+# multiple java thread by switching the current environment in a redef
+# of `Sys::jni_env`, and multiple JVM using `Sys::jvm`.
+module base is
+       cflags "-I $(JAVA_HOME)/include/ -I $(JAVA_HOME)/include/linux/"
+       ldflags "-L $(JNI_LIB_PATH) -ljvm"
+       new_annotation extra_java_files
+end
+
+import jvm
+
+redef class Sys
+       private var jvm_cache: nullable JavaVM = null
+       private var jni_env_cache: nullable JniEnv = null
+
+       # Default Java Virtual Machine to use (will be instantiated using
+       # `create_default_jvm` if not already set)
+       fun jvm: JavaVM
+       do
+               if jvm_cache == null then create_default_jvm
+               return jvm_cache.as(not null)
+       end
+
+       # Sets the current default Java Virtual Machine (use with `jni_env=`)
+       fun jvm=(jvm: JavaVM) do jvm_cache = jvm
+
+       # Current main `JniEnv`
+       fun jni_env: JniEnv
+       do
+               if jni_env_cache == null then create_default_jvm
+               return jni_env_cache.as(not null)
+       end
+
+       # Sets the current default JNI env (use with `jvm=`)
+       fun jni_env=(jni_env: JniEnv) do jni_env_cache = jni_env
+
+       # Called by `jvm` and `jni_env` to instantiate a Java Virtual Machine.
+       # Used mostly for the FFI with Java.
+       protected fun create_default_jvm
+       do
+               var builder = new JavaVMBuilder
+
+               # By default, look for Java classes in a jar file the same directory as the executable
+               builder.options.add "-Djava.class.path={sys.program_name}.jar"
+
+               var jvm = builder.create_jvm
+               assert jvm != null else print "JVM creation failed"
+
+               self.jvm = jvm
+               self.jni_env = builder.jni_env.as(not null)
+       end
+
+       # Get a Java class by its name from the current `jni_env`
+       fun load_jclass(name: NativeString): JClass import jni_env `{
+               JNIEnv *nit_ffi_jni_env = Sys_jni_env(self);
+
+               // retrieve the implementation Java class
+               jclass java_class = (*nit_ffi_jni_env)->FindClass(nit_ffi_jni_env, name);
+               if (java_class == NULL) {
+                       fprintf(stderr, "Nit FFI with Java error: failed to load class.\\n");
+                       (*nit_ffi_jni_env)->ExceptionDescribe(nit_ffi_jni_env);
+                       exit(1);
+               }
+
+               return java_class;
+       `}
+end
+
+# A standard Java string `java.lang.String`
+#
+# Converted to a Nit string using `to_s`, or to a C string with `to_cstring`.
+# Created using `String::to_java_string` or `NativeString::to_java_string`.
+extern class JavaString in "Java" `{ java.lang.String `}
+       super JavaObject
+
+       # Get the string from Java and copy it to Nit memory
+       fun to_cstring: NativeString import sys, Sys.jni_env `{
+               Sys sys = JavaString_sys(self);
+               JNIEnv *env = Sys_jni_env(sys);
+
+               // Get the data from Java
+               const char *java_cstr = (*env)->GetStringUTFChars(env, self, NULL);
+               jsize len = (*env)->GetStringUTFLength(env, self);
+
+               // Copy it in control of Nit
+               char *nit_cstr = (char*)malloc(len+1);
+               memcpy(nit_cstr, java_cstr, len);
+               nit_cstr[len] = '\0';
+
+               // Free JNI ref and return
+               (*env)->ReleaseStringUTFChars(env, self, java_cstr);
+               return nit_cstr;
+       `}
+
+       redef fun to_s do return to_cstring.to_s
+end
+
+redef class NativeString
+       # Get a Java string from this C string
+       #
+       # This instance is only valid until the next execution of Java code.
+       # You can use `new_local_ref` to keep it longer.
+       fun to_java_string: JavaString import sys, Sys.jni_env `{
+               Sys sys = JavaString_sys(self);
+               JNIEnv *env = Sys_jni_env(sys);
+               return (*env)->NewStringUTF(env, self);
+       `}
+end
+
+redef class Text
+       # Get `self` as a `JavaString`
+       fun to_java_string: JavaString do return to_cstring.to_java_string
+end
+
+redef extern class JavaObject
+
+       # Returns a global reference to the Java object behind this reference
+       #
+       # You must use a global reference when keeping a Java object
+       # across execution of Java code, per JNI specification.
+       fun new_global_ref: SELF import sys, Sys.jni_env `{
+               Sys sys = JavaObject_sys(self);
+               JNIEnv *env = Sys_jni_env(sys);
+               return (*env)->NewGlobalRef(env, self);
+       `}
+
+       # Delete this global reference
+       fun delete_global_ref import sys, Sys.jni_env `{
+               Sys sys = JavaObject_sys(self);
+               JNIEnv *env = Sys_jni_env(sys);
+               (*env)->DeleteGlobalRef(env, self);
+       `}
+
+       # Delete this local reference
+       fun delete_local_ref import sys, Sys.jni_env `{
+               Sys sys = JavaObject_sys(self);
+               JNIEnv *env = Sys_jni_env(sys);
+               (*env)->DeleteLocalRef(env, self);
+       `}
+
+       # Pops the current local reference frame and return a valid reference to self
+       #
+       # Similar to `JavaVM::pop_local_frame` but returns a value.
+       fun pop_from_local_frame: SELF
+       do
+               var jni_env = sys.jni_env
+               return pop_from_local_frame_with_env(jni_env)
+       end
+
+       # Java implementation of `pop_from_local_frame`
+       protected fun pop_from_local_frame_with_env(jni_env: JniEnv): SELF `{
+               return (*jni_env)->PopLocalFrame(jni_env, self);
+       `}
+
+       # Is `self` null in Java?
+       #
+       # Since Java type system doesn't have the same `nullable` concept as Nit's,
+       # the two systems are not directly compatible. Any Nit instances of
+       # `JavaObject` may hold a Java null.
+       #
+       # To benefit from the safer type system of Nit, it is recommended to check
+       # the return of all extern methods implemented in Java to ensure the value
+       # is not a Java null. In case it is, you should replace it by a normal Nit
+       # `null`.
+       fun is_java_null: Bool in "Java" `{ return self == null; `}
+
+       # `JavaString` representation of `self` using Java's `toString`
+       fun to_java_string: JavaString in "Java" `{ return self.toString(); `}
+
+       # Use Java's `toString` for any `JavaObject`
+       redef fun to_s
+       do
+               if is_java_null then return super
+               return to_java_string.to_s
+       end
+end
index 0c24718..097158f 100644 (file)
@@ -28,7 +28,7 @@
 # ~~~
 module collections
 
-import java
+import base
 
 # Java primitive array
 #
index 6731c85..40d3f02 100644 (file)
@@ -19,7 +19,7 @@
 # This module is used by `android::assets_and_resources` and `android::audio`.
 module io
 
-import java
+import base
 
 in "Java" `{
        import java.io.File;
index 04e8743..116f40d 100644 (file)
@@ -1,7 +1,5 @@
 # This file is part of NIT ( http://www.nitlanguage.org ).
 #
-# Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
-#
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 # The module `jvm` gives more control over the JVM instances and wraps
 # most of JNI functions. You can use it to further customize the behavior
 # of your code.
-module java is
-       cflags "-I $(JAVA_HOME)/include/ -I $(JAVA_HOME)/include/linux/"
-       ldflags "-L $(JNI_LIB_PATH) -ljvm"
-       new_annotation extra_java_files
-end
-
-import jvm
-
-redef class Sys
-       private var jvm_cache: nullable JavaVM = null
-       private var jni_env_cache: nullable JniEnv = null
-
-       # Default Java Virtual Machine to use (will be instantiated using
-       # `create_default_jvm` if not already set)
-       fun jvm: JavaVM
-       do
-               if jvm_cache == null then create_default_jvm
-               return jvm_cache.as(not null)
-       end
-
-       # Sets the current default Java Virtual Machine (use with `jni_env=`)
-       fun jvm=(jvm: JavaVM) do jvm_cache = jvm
-
-       # Current main `JniEnv`
-       fun jni_env: JniEnv
-       do
-               if jni_env_cache == null then create_default_jvm
-               return jni_env_cache.as(not null)
-       end
-
-       # Sets the current default JNI env (use with `jvm=`)
-       fun jni_env=(jni_env: JniEnv) do jni_env_cache = jni_env
-
-       # Called by `jvm` and `jni_env` to instantiate a Java Virtual Machine.
-       # Used mostly for the FFI with Java.
-       protected fun create_default_jvm
-       do
-               var builder = new JavaVMBuilder
-
-               # By default, look for Java classes in a jar file the same directory as the executable
-               builder.options.add "-Djava.class.path={sys.program_name}.jar"
-
-               var jvm = builder.create_jvm
-               assert jvm != null else print "JVM creation failed"
-
-               self.jvm = jvm
-               self.jni_env = builder.jni_env.as(not null)
-       end
-
-       # Get a Java class by its name from the current `jni_env`
-       fun load_jclass(name: NativeString): JClass import jni_env `{
-               JNIEnv *nit_ffi_jni_env = Sys_jni_env(self);
-
-               // retrieve the implementation Java class
-               jclass java_class = (*nit_ffi_jni_env)->FindClass(nit_ffi_jni_env, name);
-               if (java_class == NULL) {
-                       fprintf(stderr, "Nit FFI with Java error: failed to load class.\\n");
-                       (*nit_ffi_jni_env)->ExceptionDescribe(nit_ffi_jni_env);
-                       exit(1);
-               }
-
-               return java_class;
-       `}
-end
-
-# A standard Java string `java.lang.String`
-#
-# Converted to a Nit string using `to_s`, or to a C string with `to_cstring`.
-# Created using `String::to_java_string` or `NativeString::to_java_string`.
-extern class JavaString in "Java" `{ java.lang.String `}
-       super JavaObject
-
-       # Get the string from Java and copy it to Nit memory
-       fun to_cstring: NativeString import sys, Sys.jni_env `{
-               Sys sys = JavaString_sys(self);
-               JNIEnv *env = Sys_jni_env(sys);
-
-               // Get the data from Java
-               const char *java_cstr = (*env)->GetStringUTFChars(env, self, NULL);
-               jsize len = (*env)->GetStringUTFLength(env, self);
-
-               // Copy it in control of Nit
-               char *nit_cstr = (char*)malloc(len+1);
-               memcpy(nit_cstr, java_cstr, len);
-               nit_cstr[len] = '\0';
-
-               // Free JNI ref and return
-               (*env)->ReleaseStringUTFChars(env, self, java_cstr);
-               return nit_cstr;
-       `}
-
-       redef fun to_s do return to_cstring.to_s
-end
-
-redef class NativeString
-       # Get a Java string from this C string
-       #
-       # This instance is only valid until the next execution of Java code.
-       # You can use `new_local_ref` to keep it longer.
-       fun to_java_string: JavaString import sys, Sys.jni_env `{
-               Sys sys = JavaString_sys(self);
-               JNIEnv *env = Sys_jni_env(sys);
-               return (*env)->NewStringUTF(env, self);
-       `}
-end
-
-redef class Text
-       # Get `self` as a `JavaString`
-       fun to_java_string: JavaString do return to_cstring.to_java_string
-end
-
-redef extern class JavaObject
-
-       # Returns a global reference to the Java object behind this reference
-       #
-       # You must use a global reference when keeping a Java object
-       # across execution of Java code, per JNI specification.
-       fun new_global_ref: SELF import sys, Sys.jni_env `{
-               Sys sys = JavaObject_sys(self);
-               JNIEnv *env = Sys_jni_env(sys);
-               return (*env)->NewGlobalRef(env, self);
-       `}
-
-       # Delete this global reference
-       fun delete_global_ref import sys, Sys.jni_env `{
-               Sys sys = JavaObject_sys(self);
-               JNIEnv *env = Sys_jni_env(sys);
-               (*env)->DeleteGlobalRef(env, self);
-       `}
-
-       # Delete this local reference
-       fun delete_local_ref import sys, Sys.jni_env `{
-               Sys sys = JavaObject_sys(self);
-               JNIEnv *env = Sys_jni_env(sys);
-               (*env)->DeleteLocalRef(env, self);
-       `}
-
-       # Pops the current local reference frame and return a valid reference to self
-       #
-       # Similar to `JavaVM::pop_local_frame` but returns a value.
-       fun pop_from_local_frame: SELF
-       do
-               var jni_env = sys.jni_env
-               return pop_from_local_frame_with_env(jni_env)
-       end
-
-       private fun pop_from_local_frame_with_env(jni_env: JniEnv): SELF `{
-               return (*jni_env)->PopLocalFrame(jni_env, self);
-       `}
-
-       # Is `self` null in Java?
-       #
-       # Since Java type system doesn't have the same `nullable` concept as Nit's,
-       # the two systems are not directly compatible. Any Nit instances of
-       # `JavaObject` may hold a Java null.
-       #
-       # To benefit from the safer type system of Nit, it is recommended to check
-       # the return of all extern methods implemented in Java to ensure the value
-       # is not a Java null. In case it is, you should replace it by a normal Nit
-       # `null`.
-       fun is_java_null: Bool in "Java" `{ return self == null; `}
-
-       # `JavaString` representation of `self` using Java's `toString`
-       fun to_java_string: JavaString in "Java" `{ return self.toString(); `}
+module java
 
-       # Use Java's `toString` for any `JavaObject`
-       redef fun to_s
-       do
-               if is_java_null then return super
-               return to_java_string.to_s
-       end
-end
+import base
+import collections
index 39938bd..5192797 100644 (file)
@@ -534,6 +534,16 @@ interface MapRead[K, V]
        #     assert x.is_empty  == false
        fun is_empty: Bool is abstract
 
+       # Alias for `not is_empty`.
+       #
+       # Some people prefer to have conditions grammatically easier to read.
+       #
+       #     var map = new HashMap[String, Int]
+       #     assert map.not_empty == false
+       #     map["one"] = 1
+       #     assert map.not_empty == true
+       fun not_empty: Bool do return not self.is_empty
+
        # Number of items in the collection.
        #
        #     var x = new HashMap[String, Int]
index 517edf3..3e0d97a 100644 (file)
@@ -272,9 +272,49 @@ class ProcessDuplex
 
        redef fun pipeflags do return 3
 
-       redef fun execute
+       redef fun execute do super
+
+       # Write `input` to process and return its output
+       #
+       # Writing and reading are processed line by line,
+       # reading only when something is available.
+       #
+       # ~~~
+       # var proc = new ProcessDuplex("tr", "[:lower:]", "[:upper:]")
+       # assert proc.write_and_read("""
+       #     Alice
+       #     Bob
+       # """) == """
+       #     ALICE
+       #     BOB
+       # """
+       # ~~~
+       fun write_and_read(input: Text): String
        do
-               super
+               var read = new Buffer #new Array[String]
+
+               # Main loop, read and write line by line
+               var prev = 0
+               for delimiter in input.search_all('\n') do
+                       write input.substring(prev, delimiter.after-prev)
+                       prev = delimiter.after
+
+                       while stream_in.poll_in do
+                               read.append stream_in.read_line
+                       end
+               end
+
+               # Write the last line
+               write input.substring_from(prev)
+               stream_out.close
+
+               # Read the rest, may be everything for some programs
+               read.append stream_in.read_all
+               stream_in.close
+
+               # Clean up
+               wait
+               return read.to_s
        end
 end
 
index 849b4e7..e5fc85b 100644 (file)
@@ -176,6 +176,20 @@ class FileReader
                        end_reached = true
                end
        end
+
+       redef fun poll_in
+       do
+               var res = native_poll_in(fd)
+               if res == -1 then
+                       last_error = new IOError(errno.to_s)
+                       return false
+               else return res > 0
+       end
+
+       private fun native_poll_in(fd: Int): Int `{
+               struct pollfd fds = {fd, POLLIN, 0};
+               return poll(&fds, 1, 0);
+       `}
 end
 
 # `Stream` that can write to a File
@@ -305,16 +319,6 @@ class Stdin
                path = "/dev/stdin"
                prepare_buffer(1)
        end
-
-       redef fun poll_in `{
-               struct pollfd fd = {0, POLLIN, 0};
-               int res = poll(&fd, 1, 0);
-               if (res == -1) {
-                       perror("Error poll stdin");
-                       exit(EXIT_FAILURE);
-               }
-               return res > 0;
-       `}
 end
 
 # Standard output stream.
index 7218514..ce6e9b3 100644 (file)
@@ -166,7 +166,32 @@ abstract class Reader
        # var i = new StringReader(txt)
        # assert i.read_all == txt
        # ~~~
-       fun read_all: String do return read_all_bytes.to_s
+       fun read_all: String do
+               var s = read_all_bytes
+               var slen = s.length
+               if slen == 0 then return ""
+               var rets = ""
+               var pos = 0
+               var sits = s.items
+               var remsp = slen
+               while pos < slen do
+                       # The 129 size was decided more or less arbitrarily
+                       # It will require some more benchmarking to compute
+                       # if this is the best size or not
+                       var chunksz = 129
+                       if chunksz > remsp then
+                               rets += new FlatString.with_infos(sits, remsp, pos, pos + remsp - 1)
+                               break
+                       end
+                       var st = sits.find_beginning_of_char_at(pos + chunksz - 1)
+                       var bytelen = st - pos
+                       rets += new FlatString.with_infos(sits, bytelen, pos, st - 1)
+                       pos = st
+                       remsp -= bytelen
+               end
+               if rets isa Concat then return rets.balance
+               return rets
+       end
 
        # Read all the stream until the eof.
        #
index 97191d2..cf0d1dc 100644 (file)
@@ -231,14 +231,103 @@ abstract class Text
        #     assert "abcd".has_suffix("bcd")        ==  true
        fun has_suffix(suffix: String): Bool do return has_substring(suffix, length - suffix.length)
 
-       # If `self` contains only digits, return the corresponding integer
+       # Returns a copy of `self` minus all occurences of `c`
+       #
+       #     assert "__init__".remove_all('_') == "init"
+       fun remove_all(c: Char): String do
+               var b = new Buffer
+               for i in chars do if i != c then b.add i
+               return b.to_s
+       end
+
+       # Is `self` a well-formed Integer (i.e. parsable via `to_i`)
+       #
+       #     assert "123".is_int
+       #     assert "0b1011".is_int
+       #     assert not "0x_".is_int
+       #     assert not "0xGE".is_int
+       fun is_int: Bool do
+               var s = remove_all('_')
+               var pos = 0
+               while s[pos] == '-' do
+                       pos += 1
+               end
+               s = s.substring_from(pos)
+               var rets = s.strip_numhead
+               if rets == "" then return false
+               var hd = get_numhead
+               if hd == "0x" or hd == "0X" then return rets.is_hex
+               if hd == "0b" or hd == "0B" then return rets.is_bin
+               if hd == "0o" or hd == "0O" then return rets.is_oct
+               return hd.is_dec
+       end
+
+       # Removes the numeric head of `self` if present
+       #
+       #     intrude import standard::text::abstract_text
+       #     assert "0xFFEF".strip_numhead  == "FFEF"
+       #     assert "0o7364".strip_numhead  == "7364"
+       #     assert "0b01001".strip_numhead == "01001"
+       #     assert "98".strip_numhead      == "98"
+       private fun strip_numhead: Text do
+               if get_numhead != "" then return substring_from(2)
+               return self
+       end
+
+       # Gets the numeric head of `self` if present
+       # Returns "" otherwise
+       #
+       #     intrude import standard::text::abstract_text
+       #     assert "0xFEFF".get_numhead  == "0x"
+       #     assert "0b01001".get_numhead == "0b"
+       #     assert "0o872".get_numhead   == "0o"
+       #     assert "98".get_numhead      == ""
+       private fun get_numhead: Text do
+               if self.length < 2 then return ""
+               var c = self[0]
+               if c != '0' then return ""
+               c = self[1]
+               if c == 'x' or c == 'b' or c == 'o' or
+                  c == 'X' or c == 'B' or c == 'O' then return substring(0, 2)
+               return ""
+       end
+
+       # Returns `self` as the corresponding integer
        #
        #     assert "123".to_i        == 123
        #     assert "-1".to_i         == -1
+       #     assert "0x64".to_i       == 100
+       #     assert "0b1100_0011".to_i== 195
+       #     assert "--12".to_i       == 12
+       #
+       # REQUIRE: `self`.`is_int`
        fun to_i: Int
        do
-               # Shortcut
-               return to_s.to_cstring.atoi
+               assert self.is_int
+               var s = remove_all('_')
+               var val = 0
+               var neg = false
+               var pos = 0
+               while s[pos] == '-' do
+                       neg = not neg
+                       pos += 1
+               end
+               s = s.substring_from(pos)
+               if s.length >= 2 then
+                       var s1 = s[1]
+                       if s1 == 'x' or s1 == 'X' then
+                               val = s.substring_from(2).to_hex
+                       else if s1 == 'o' or s1 == 'O' then
+                               val = s.substring_from(2).to_oct
+                       else if s1 == 'b' or s1 == 'B' then
+                               val = s.substring_from(2).to_bin
+                       else if s1.is_numeric then
+                               val = s.to_dec
+                       end
+               else
+                       val = s.to_dec
+               end
+               return if neg then -val else val
        end
 
        # If `self` contains a float, return the corresponding float
@@ -267,6 +356,11 @@ abstract class Text
        #     assert "101101".to_bin == 45
        fun to_bin: Int do return a_to(2)
 
+       # If `self` contains only digits '0' .. '9', return the corresponding integer.
+       #
+       #     assert "108".to_dec == 108
+       fun to_dec: Int do return a_to(10)
+
        # If `self` contains only digits and letters, return the corresponding integer in a given base
        #
        #     assert "120".a_to(3)     == 15
@@ -335,6 +429,33 @@ abstract class Text
                return true
        end
 
+       # Returns `true` if the string contains only Binary digits
+       #
+       #     assert "1101100".is_bin  == true
+       #     assert "1101020".is_bin  == false
+       fun is_bin: Bool do
+               for i in chars do if i != '0' and i != '1' then return false
+               return true
+       end
+
+       # Returns `true` if the string contains only Octal digits
+       #
+       #     assert "213453".is_oct  == true
+       #     assert "781".is_oct     == false
+       fun is_oct: Bool do
+               for i in chars do if i < '0' or i > '7' then return false
+               return true
+       end
+
+       # Returns `true` if the string contains only Decimal digits
+       #
+       #     assert "10839".is_dec == true
+       #     assert "164F".is_dec  == false
+       fun is_dec: Bool do
+               for i in chars do if i < '0' or i > '9' then return false
+               return true
+       end
+
        # Are all letters in `self` upper-case ?
        #
        #     assert "HELLO WORLD".is_upper == true
index 018217e..08611b7 100644 (file)
@@ -82,6 +82,12 @@ private class Concat
 
        redef fun empty do return ""
 
+       # Cache for the latest accessed FlatString in `self`
+       var flat_cache: String = ""
+
+       # Position of the beginning of `flat_cache` in `self`
+       var flat_last_pos_start: Int = -1
+
        redef var to_cstring is lazy do
                var len = bytelen
                var ns = new NativeString(len + 1)
@@ -119,9 +125,27 @@ private class Concat
        end
 
        redef fun [](i) do
-               var llen = left.length
-               if i >= llen then return right[i - llen]
-               return left[i]
+               if flat_last_pos_start != -1 then
+                       var fsp = i - flat_last_pos_start
+                       if fsp >= 0 and fsp < flat_cache.length then return flat_cache[fsp]
+               end
+               var s: String = self
+               var st = i
+               loop
+                       if s isa FlatString then break
+                       s = s.as(Concat)
+                       var lft = s.left
+                       var llen = lft.length
+                       if i >= llen then
+                               s = s.right
+                               i -= llen
+                       else
+                               s = s.left
+                       end
+               end
+               flat_last_pos_start = st - i
+               flat_cache = s
+               return s[i]
        end
 
        redef fun substring(from, len) do
@@ -180,6 +204,50 @@ private class Concat
                        st = 0
                end
        end
+
+       # Returns a balanced version of `self`
+       fun balance: String do
+               var children = new Array[String]
+               var rnod: String
+               var iter: nullable RopeCharIteratorPiece = new RopeCharIteratorPiece(self, false, false, null)
+               loop
+                       if iter == null then break
+                       rnod = iter.node
+                       if not rnod isa Concat then
+                               children.push rnod
+                               iter = iter.prev
+                               continue
+                       end
+                       if not iter.ldone then
+                               iter.ldone = true
+                               iter = new RopeCharIteratorPiece(rnod.left, false, false, iter)
+                       else if not iter.rdone then
+                               iter.rdone = true
+                               iter = new RopeCharIteratorPiece(rnod.right, false, false, iter)
+                       else
+                               iter = iter.prev
+                       end
+
+               end
+               return recurse_balance(children, children.length)
+       end
+
+       fun recurse_balance(nodes: Array[String], len: Int): String do
+               var finpos = 0
+               var stpos = 0
+               while stpos < len do
+                       if len - stpos > 1 then
+                               nodes[finpos] = new Concat(nodes[stpos], nodes[stpos + 1])
+                               stpos += 2
+                       else
+                               nodes[finpos] = nodes[stpos]
+                               stpos += 1
+                       end
+                       finpos += 1
+               end
+               if finpos == 1 then return nodes[0]
+               return recurse_balance(nodes, finpos)
+       end
 end
 
 # Mutable `Rope`, optimized for concatenation operations
@@ -449,7 +517,8 @@ class RopeBuffer
        redef fun enlarge(i) do end
 
        redef fun to_s do
-               dump_buffer
+               persist_buffer
+               written = true
                return str
        end
 
index 9c3ede7..2930d81 100644 (file)
@@ -36,8 +36,9 @@ syn match NITExprSubst "{\([^}]\|\n\)*}" contained
 syn match NITExprSubstLong "\\." contained
 syn match NITExprSubstLong "{*\zs{{{\([^}]\|\n\)*}}}\ze}*" contained
 
-" Numbers and ASCII Codes
-syn match NITNumber "\<\(\d\+\.\d\+\|\d\+\)\>"
+" Numbers
+syn match NITNumber "\<\([0-9_]\+\|0[bB][01_]\+\|0[oO][0-7_]\+\|0[xX][0-9a-fA-F_]\+\)\([iu]\(8\|16\|32\)\)\?\>"
+syn match NITNumber "\<[0-9_]\+\.[0-9_]\+\>"
 
 " Identifiers
 syn match NITClass             "\<\u\w*"
index eb04e7a..541f752 100644 (file)
@@ -74,115 +74,69 @@ redef class AExpr
        end
 end
 
-redef class Text
-       private fun remove_underscores: Text do
-               var b = new FlatBuffer
-               for i in chars do
-                       if i == '_' then continue
-                       b.add i
-               end
-               return b
-       end
-end
-
 redef class AIntExpr
        # The value of the literal int once computed.
        var value: nullable Int
-end
 
-redef class ADecIntExpr
        redef fun accept_literal(v)
        do
-               value = self.n_number.text.to_i
+               if not text.is_int then
+                       v.toolcontext.error(hot_location, "Error: invalid literal `{text}`")
+                       return
+               end
+               value = text.to_i
        end
+
+       private fun text: String is abstract
+end
+
+redef class ADecIntExpr
+       redef fun text do return self.n_number.text
 end
 
 redef class AHexIntExpr
-       redef fun accept_literal(v)
-       do
-               var s = self.n_hex_number.text.substring_from(2).remove_underscores
-               if s.is_empty then
-                       v.toolcontext.error(location, "Error: invalid hexadecimal literal")
-                       return
-               end
-               value = s.to_hex
-       end
+       redef fun text do return self.n_hex_number.text
 end
 
 redef class ABinIntExpr
-       redef fun accept_literal(v)
-       do
-               var s = self.n_bin_number.text.substring_from(2).remove_underscores
-               if s.is_empty then
-                       v.toolcontext.error(location, "Error: invalid binary literal")
-                       return
-               end
-               value = s.to_bin
-       end
+       redef fun text do return self.n_bin_number.text
 end
 
 redef class AOctIntExpr
-       redef fun accept_literal(v)
-       do
-               var s = self.n_oct_number.text.substring_from(2).remove_underscores
-               if s.is_empty then
-                       v.toolcontext.error(location, "Error: invalid octal literal")
-                       return
-               end
-               value = s.to_oct
-       end
+       redef fun text do return self.n_oct_number.text
 end
 
 redef class AByteExpr
        # The value of the literal int once computed.
        var value: nullable Byte
-end
 
-redef class ADecByteExpr
        redef fun accept_literal(v)
        do
-               var t = self.n_bytenum.text
-               value = t.substring(0, t.length - 2).to_i.to_b
+               var s = text.substring(0, text.length - 2)
+               if not s.is_int then
+                       v.toolcontext.error(hot_location, "Error: invalid byte literal `{text}`")
+                       return
+               end
+               value = s.to_i.to_b
        end
+
+       private fun text: String is abstract
+end
+
+redef class ADecByteExpr
+       redef fun text do return self.n_bytenum.text
 end
 
 redef class AHexByteExpr
-       redef fun accept_literal(v)
-       do
-               var t = self.n_hex_bytenum.text
-               var s = t.substring(2, t.length - 4).remove_underscores
-               if s.is_empty then
-                       v.toolcontext.error(location, "Error: invalid hexadecimal literal")
-                       return
-               end
-               value = s.to_hex.to_b
-       end
+       redef fun text do return self.n_hex_bytenum.text
 end
 
 redef class ABinByteExpr
-       redef fun accept_literal(v)
-       do
-               var t = self.n_bin_bytenum.text
-               var s = t.substring(2, t.length - 4).remove_underscores
-               if s.is_empty then
-                       v.toolcontext.error(location, "Error: invalid binary literal")
-                       return
-               end
-               value = s.to_bin.to_b
-       end
+       redef fun text do return self.n_bin_bytenum.text
 end
 
 redef class AOctByteExpr
-       redef fun accept_literal(v)
-       do
-               var t = self.n_oct_bytenum.text
-               var s = t.substring(2, t.length - 4).remove_underscores
-               if s.is_empty then
-                       v.toolcontext.error(location, "Error: invalid octal literal")
-                       return
-               end
-               value = s.to_oct.to_b
-       end
+       redef fun text do return self.n_oct_bytenum.text
 end
 
 redef class AFloatExpr
index 592cc42..3904c1f 100644 (file)
@@ -199,11 +199,11 @@ classid = uppercase letter*;
 id = lowercase letter*;
 attrid = '_' lowercase letter*;
 
-number = digit+;
+number = digit (digit | '_')*;
 hex_number = ('0x' | '0X') hexdigit+;
 bin_number = ('0b' | '0B') bindigit+;
 oct_number = ('0o' | '0O') octdigit+;
-bytenum = digit+ 'u8';
+bytenum = digit (digit | '_')* 'u8';
 hex_bytenum = ('0x' | '0X') hexdigit+ 'u8';
 bin_bytenum = ('0b' | '0B') bindigit+ 'u8';
 oct_bytenum = ('0o' | '0O') octdigit+ 'u8';
index 4fd03ae..23c4d85 100644 (file)
@@ -140,258 +140,260 @@ static const int lexer_goto_row19[] = {
        61, 61, 75
 };
 static const int lexer_goto_row20[] = {
-       11,
+       12,
        46, 46, 76,
-       48, 57, 20,
-       66, 66, 77,
-       69, 69, 78,
-       79, 79, 79,
-       88, 88, 80,
-       98, 98, 81,
-       101, 101, 82,
-       111, 111, 83,
-       117, 117, 84,
-       120, 120, 85
+       48, 57, 77,
+       66, 66, 78,
+       69, 69, 79,
+       79, 79, 80,
+       88, 88, 81,
+       95, 95, 82,
+       98, 98, 83,
+       101, 101, 84,
+       111, 111, 85,
+       117, 117, 86,
+       120, 120, 87
 };
 static const int lexer_goto_row21[] = {
-       4,
+       5,
        46, 57, -21,
-       69, 69, 78,
-       101, 101, 82,
-       117, 117, 84
+       69, 69, 79,
+       95, 95, 82,
+       101, 101, 84,
+       117, 117, 86
 };
 static const int lexer_goto_row22[] = {
        1,
-       58, 58, 86
+       58, 58, 88
 };
 static const int lexer_goto_row24[] = {
        2,
-       60, 60, 87,
-       61, 61, 88
+       60, 60, 89,
+       61, 61, 90
 };
 static const int lexer_goto_row25[] = {
        1,
-       61, 61, 89
+       61, 61, 91
 };
 static const int lexer_goto_row26[] = {
        2,
-       61, 61, 90,
-       62, 62, 91
+       61, 61, 92,
+       62, 62, 93
 };
 static const int lexer_goto_row28[] = {
        4,
-       48, 57, 92,
-       65, 90, 93,
-       95, 95, 94,
-       97, 122, 95
+       48, 57, 94,
+       65, 90, 95,
+       95, 95, 96,
+       97, 122, 97
 };
 static const int lexer_goto_row31[] = {
        1,
-       61, 61, 96
+       61, 61, 98
 };
 static const int lexer_goto_row32[] = {
        2,
-       95, 95, 97,
-       97, 122, 98
+       95, 95, 99,
+       97, 122, 100
 };
 static const int lexer_goto_row33[] = {
        1,
-       123, 123, 99
+       123, 123, 101
 };
 static const int lexer_goto_row34[] = {
        10,
-       48, 57, 100,
-       65, 90, 101,
-       95, 95, 102,
-       97, 97, 103,
-       98, 98, 104,
-       99, 109, 103,
-       110, 110, 105,
-       111, 114, 103,
-       115, 115, 106,
-       116, 122, 103
+       48, 57, 102,
+       65, 90, 103,
+       95, 95, 104,
+       97, 97, 105,
+       98, 98, 106,
+       99, 109, 105,
+       110, 110, 107,
+       111, 114, 105,
+       115, 115, 108,
+       116, 122, 105
 };
 static const int lexer_goto_row35[] = {
        4,
        48, 95, -35,
-       97, 113, 103,
-       114, 114, 107,
-       115, 122, 103
+       97, 113, 105,
+       114, 114, 109,
+       115, 122, 105
 };
 static const int lexer_goto_row36[] = {
        6,
        48, 95, -35,
-       97, 107, 103,
-       108, 108, 108,
-       109, 110, 103,
-       111, 111, 109,
-       112, 122, 103
+       97, 107, 105,
+       108, 108, 110,
+       109, 110, 105,
+       111, 111, 111,
+       112, 122, 105
 };
 static const int lexer_goto_row37[] = {
        4,
        48, 95, -35,
-       97, 110, 103,
-       111, 111, 110,
-       112, 122, 103
+       97, 110, 105,
+       111, 111, 112,
+       112, 122, 105
 };
 static const int lexer_goto_row38[] = {
        7,
        48, 107, -37,
-       108, 108, 111,
-       109, 109, 103,
-       110, 110, 112,
-       111, 119, 103,
-       120, 120, 113,
-       121, 122, 103
+       108, 108, 113,
+       109, 109, 105,
+       110, 110, 114,
+       111, 119, 105,
+       120, 120, 115,
+       121, 122, 105
 };
 static const int lexer_goto_row39[] = {
        7,
        48, 95, -35,
-       97, 97, 114,
-       98, 110, 103,
-       111, 111, 115,
-       112, 116, 103,
-       117, 117, 116,
-       118, 122, 103
+       97, 97, 116,
+       98, 110, 105,
+       111, 111, 117,
+       112, 116, 105,
+       117, 117, 118,
+       118, 122, 105
 };
 static const int lexer_goto_row40[] = {
        2,
        48, 95, -35,
-       97, 122, 103
+       97, 122, 105
 };
 static const int lexer_goto_row41[] = {
        9,
        48, 95, -35,
-       97, 101, 103,
-       102, 102, 117,
-       103, 108, 103,
-       109, 109, 118,
-       110, 110, 119,
-       111, 114, 103,
-       115, 115, 120,
-       116, 122, 103
+       97, 101, 105,
+       102, 102, 119,
+       103, 108, 105,
+       109, 109, 120,
+       110, 110, 121,
+       111, 114, 105,
+       115, 115, 122,
+       116, 122, 105
 };
 static const int lexer_goto_row42[] = {
        5,
        48, 95, -35,
-       97, 97, 121,
-       98, 110, 103,
-       111, 111, 122,
-       112, 122, 103
+       97, 97, 123,
+       98, 110, 105,
+       111, 111, 124,
+       112, 122, 105
 };
 static const int lexer_goto_row43[] = {
        3,
        48, 110, -38,
-       111, 111, 123,
-       112, 122, 103
+       111, 111, 125,
+       112, 122, 105
 };
 static const int lexer_goto_row44[] = {
        8,
        48, 95, -35,
-       97, 100, 103,
-       101, 101, 124,
-       102, 110, 103,
-       111, 111, 125,
-       112, 116, 103,
-       117, 117, 126,
-       118, 122, 103
+       97, 100, 105,
+       101, 101, 126,
+       102, 110, 105,
+       111, 111, 127,
+       112, 116, 105,
+       117, 117, 128,
+       118, 122, 105
 };
 static const int lexer_goto_row45[] = {
        6,
        48, 95, -35,
-       97, 109, 103,
-       110, 110, 127,
-       111, 113, 103,
-       114, 114, 128,
-       115, 122, 103
+       97, 109, 105,
+       110, 110, 129,
+       111, 113, 105,
+       114, 114, 130,
+       115, 122, 105
 };
 static const int lexer_goto_row46[] = {
        7,
        48, 95, -35,
-       97, 97, 129,
-       98, 113, 103,
-       114, 114, 130,
-       115, 116, 103,
-       117, 117, 131,
-       118, 122, 103
+       97, 97, 131,
+       98, 113, 105,
+       114, 114, 132,
+       115, 116, 105,
+       117, 117, 133,
+       118, 122, 105
 };
 static const int lexer_goto_row47[] = {
        3,
        48, 100, -45,
-       101, 101, 132,
-       102, 122, 103
+       101, 101, 134,
+       102, 122, 105
 };
 static const int lexer_goto_row48[] = {
        5,
        48, 100, -45,
-       101, 101, 133,
-       102, 116, 103,
-       117, 117, 134,
-       118, 122, 103
+       101, 101, 135,
+       102, 116, 105,
+       117, 117, 136,
+       118, 122, 105
 };
 static const int lexer_goto_row49[] = {
        8,
        48, 95, -35,
-       97, 103, 103,
-       104, 104, 135,
-       105, 113, 103,
-       114, 114, 136,
-       115, 120, 103,
-       121, 121, 137,
-       122, 122, 103
+       97, 103, 105,
+       104, 104, 137,
+       105, 113, 105,
+       114, 114, 138,
+       115, 120, 105,
+       121, 121, 139,
+       122, 122, 105
 };
 static const int lexer_goto_row50[] = {
        3,
        48, 109, -46,
-       110, 110, 138,
-       111, 122, 103
+       110, 110, 140,
+       111, 122, 105
 };
 static const int lexer_goto_row51[] = {
        3,
        48, 95, -35,
-       97, 97, 139,
-       98, 122, 103
+       97, 97, 141,
+       98, 122, 105
 };
 static const int lexer_goto_row52[] = {
        4,
        48, 103, -50,
-       104, 104, 140,
-       105, 105, 141,
-       106, 122, 103
+       104, 104, 142,
+       105, 105, 143,
+       106, 122, 105
 };
 static const int lexer_goto_row53[] = {
        1,
-       61, 61, 142
+       61, 61, 144
 };
 static const int lexer_goto_row54[] = {
        11,
-       0, 9, 143,
-       11, 12, 143,
-       14, 33, 143,
-       34, 34, 144,
-       35, 91, 143,
-       92, 92, 145,
-       93, 122, 143,
-       123, 123, 146,
-       124, 124, 143,
-       125, 125, 147,
-       126, 255, 143
+       0, 9, 145,
+       11, 12, 145,
+       14, 33, 145,
+       34, 34, 146,
+       35, 91, 145,
+       92, 92, 147,
+       93, 122, 145,
+       123, 123, 148,
+       124, 124, 145,
+       125, 125, 149,
+       126, 255, 145
 };
 static const int lexer_goto_row58[] = {
        3,
        0, 33, -8,
-       34, 34, 148,
+       34, 34, 150,
        35, 255, -8
 };
 static const int lexer_goto_row59[] = {
        1,
-       34, 34, 149
+       34, 34, 151
 };
 static const int lexer_goto_row60[] = {
        3,
-       0, 9, 150,
-       11, 12, 150,
-       14, 255, 150
+       0, 9, 152,
+       11, 12, 152,
+       14, 255, 152
 };
 static const int lexer_goto_row62[] = {
        1,
@@ -399,102 +401,105 @@ static const int lexer_goto_row62[] = {
 };
 static const int lexer_goto_row64[] = {
        1,
-       10, 10, 151
+       10, 10, 153
 };
 static const int lexer_goto_row67[] = {
        1,
-       39, 39, 152
+       39, 39, 154
 };
 static const int lexer_goto_row68[] = {
        1,
-       39, 39, 153
+       39, 39, 155
 };
 static const int lexer_goto_row69[] = {
        3,
-       0, 9, 154,
-       11, 12, 154,
-       14, 255, 154
+       0, 9, 156,
+       11, 12, 156,
+       14, 255, 156
 };
 static const int lexer_goto_row70[] = {
        1,
-       61, 61, 155
+       61, 61, 157
 };
 static const int lexer_goto_row74[] = {
        1,
-       46, 46, 156
+       46, 46, 158
 };
 static const int lexer_goto_row75[] = {
-       2,
+       3,
        48, 57, 74,
-       69, 101, -22
+       69, 69, 79,
+       101, 101, 84
 };
 static const int lexer_goto_row77[] = {
        1,
        48, 57, 74
 };
 static const int lexer_goto_row78[] = {
-       3,
-       48, 48, 157,
-       49, 49, 158,
-       95, 95, 159
+       1,
+       46, 117, -22
 };
 static const int lexer_goto_row79[] = {
        3,
-       43, 43, 160,
-       45, 45, 161,
-       48, 57, 162
+       48, 48, 159,
+       49, 49, 160,
+       95, 95, 161
 };
 static const int lexer_goto_row80[] = {
-       2,
-       48, 55, 163,
-       95, 95, 164
+       3,
+       43, 43, 162,
+       45, 45, 163,
+       48, 57, 164
 };
 static const int lexer_goto_row81[] = {
-       4,
-       48, 57, 165,
-       65, 70, 166,
-       95, 95, 167,
-       97, 102, 168
+       2,
+       48, 55, 165,
+       95, 95, 166
 };
 static const int lexer_goto_row82[] = {
-       1,
-       48, 95, -79
+       4,
+       48, 57, 167,
+       65, 70, 168,
+       95, 95, 169,
+       97, 102, 170
 };
 static const int lexer_goto_row83[] = {
-       1,
-       43, 57, -80
+       3,
+       48, 57, 171,
+       95, 95, 82,
+       117, 117, 86
 };
 static const int lexer_goto_row84[] = {
        1,
-       48, 95, -81
+       48, 95, -80
 };
 static const int lexer_goto_row85[] = {
        1,
-       56, 56, 169
+       43, 57, -81
 };
 static const int lexer_goto_row86[] = {
        1,
-       48, 102, -82
+       48, 95, -82
 };
-static const int lexer_goto_row88[] = {
+static const int lexer_goto_row87[] = {
        1,
-       61, 61, 170
+       56, 56, 172
 };
-static const int lexer_goto_row89[] = {
+static const int lexer_goto_row88[] = {
        1,
-       62, 62, 171
+       48, 102, -83
 };
-static const int lexer_goto_row92[] = {
+static const int lexer_goto_row90[] = {
        1,
-       61, 61, 172
+       61, 61, 173
 };
-static const int lexer_goto_row93[] = {
+static const int lexer_goto_row91[] = {
        1,
-       48, 122, -29
+       62, 62, 174
 };
 static const int lexer_goto_row94[] = {
        1,
-       48, 122, -29
+       61, 61, 175
 };
 static const int lexer_goto_row95[] = {
        1,
@@ -504,873 +509,869 @@ static const int lexer_goto_row96[] = {
        1,
        48, 122, -29
 };
+static const int lexer_goto_row97[] = {
+       1,
+       48, 122, -29
+};
 static const int lexer_goto_row98[] = {
        1,
-       100, 100, 173
+       48, 122, -29
 };
-static const int lexer_goto_row99[] = {
+static const int lexer_goto_row100[] = {
+       1,
+       100, 100, 176
+};
+static const int lexer_goto_row101[] = {
        4,
-       48, 57, 174,
-       65, 90, 175,
-       95, 95, 176,
-       97, 122, 177
+       48, 57, 177,
+       65, 90, 178,
+       95, 95, 179,
+       97, 122, 180
 };
-static const int lexer_goto_row100[] = {
+static const int lexer_goto_row102[] = {
        5,
-       0, 91, 178,
-       92, 92, 179,
-       93, 95, 178,
-       96, 96, 180,
-       97, 255, 178
+       0, 91, 181,
+       92, 92, 182,
+       93, 95, 181,
+       96, 96, 183,
+       97, 255, 181
 };
-static const int lexer_goto_row101[] = {
+static const int lexer_goto_row103[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row102[] = {
+static const int lexer_goto_row104[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row103[] = {
+static const int lexer_goto_row105[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row104[] = {
+static const int lexer_goto_row106[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row105[] = {
+static const int lexer_goto_row107[] = {
        5,
        48, 110, -38,
-       111, 111, 181,
-       112, 114, 103,
-       115, 115, 182,
-       116, 122, 103
+       111, 111, 184,
+       112, 114, 105,
+       115, 115, 185,
+       116, 122, 105
 };
-static const int lexer_goto_row106[] = {
+static const int lexer_goto_row108[] = {
        4,
        48, 95, -35,
-       97, 99, 103,
-       100, 100, 183,
-       101, 122, 103
+       97, 99, 105,
+       100, 100, 186,
+       101, 122, 105
 };
-static const int lexer_goto_row107[] = {
+static const int lexer_goto_row109[] = {
        4,
        48, 95, -35,
-       97, 114, 103,
-       115, 115, 184,
-       116, 122, 103
+       97, 114, 105,
+       115, 115, 187,
+       116, 122, 105
 };
-static const int lexer_goto_row108[] = {
+static const int lexer_goto_row110[] = {
        3,
        48, 100, -45,
-       101, 101, 185,
-       102, 122, 103
+       101, 101, 188,
+       102, 122, 105
 };
-static const int lexer_goto_row109[] = {
+static const int lexer_goto_row111[] = {
        3,
        48, 95, -35,
-       97, 97, 186,
-       98, 122, 103
+       97, 97, 189,
+       98, 122, 105
 };
-static const int lexer_goto_row110[] = {
+static const int lexer_goto_row112[] = {
        3,
        48, 109, -46,
-       110, 110, 187,
-       111, 122, 103
+       110, 110, 190,
+       111, 122, 105
 };
-static const int lexer_goto_row111[] = {
+static const int lexer_goto_row113[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row112[] = {
+static const int lexer_goto_row114[] = {
        3,
-       48, 114, -108,
-       115, 115, 188,
-       116, 122, 103
+       48, 114, -110,
+       115, 115, 191,
+       116, 122, 105
 };
-static const int lexer_goto_row113[] = {
+static const int lexer_goto_row115[] = {
        5,
-       48, 99, -107,
-       100, 100, 189,
-       101, 116, 103,
-       117, 117, 190,
-       118, 122, 103
+       48, 99, -109,
+       100, 100, 192,
+       101, 116, 105,
+       117, 117, 193,
+       118, 122, 105
 };
-static const int lexer_goto_row114[] = {
+static const int lexer_goto_row116[] = {
        4,
        48, 95, -35,
-       97, 115, 103,
-       116, 116, 191,
-       117, 122, 103
+       97, 115, 105,
+       116, 116, 194,
+       117, 122, 105
 };
-static const int lexer_goto_row115[] = {
+static const int lexer_goto_row117[] = {
        3,
        48, 107, -37,
-       108, 108, 192,
-       109, 122, 103
+       108, 108, 195,
+       109, 122, 105
 };
-static const int lexer_goto_row116[] = {
+static const int lexer_goto_row118[] = {
        3,
        48, 113, -36,
-       114, 114, 193,
-       115, 122, 103
+       114, 114, 196,
+       115, 122, 105
 };
-static const int lexer_goto_row117[] = {
+static const int lexer_goto_row119[] = {
        3,
        48, 109, -46,
-       110, 110, 194,
-       111, 122, 103
+       110, 110, 197,
+       111, 122, 105
 };
-static const int lexer_goto_row118[] = {
+static const int lexer_goto_row120[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row119[] = {
+static const int lexer_goto_row121[] = {
        4,
        48, 95, -35,
-       97, 111, 103,
-       112, 112, 195,
-       113, 122, 103
+       97, 111, 105,
+       112, 112, 198,
+       113, 122, 105
 };
-static const int lexer_goto_row120[] = {
+static const int lexer_goto_row122[] = {
        6,
        48, 95, -35,
-       97, 104, 103,
-       105, 105, 196,
-       106, 115, 103,
-       116, 116, 197,
-       117, 122, 103
+       97, 104, 105,
+       105, 105, 199,
+       106, 115, 105,
+       116, 116, 200,
+       117, 122, 105
 };
-static const int lexer_goto_row121[] = {
+static const int lexer_goto_row123[] = {
        5,
        48, 95, -35,
-       97, 97, 198,
-       98, 114, 103,
-       115, 115, 199,
-       116, 122, 103
+       97, 97, 201,
+       98, 114, 105,
+       115, 115, 202,
+       116, 122, 105
 };
-static const int lexer_goto_row122[] = {
+static const int lexer_goto_row124[] = {
        3,
        48, 97, -35,
-       98, 98, 200,
-       99, 122, 103
+       98, 98, 203,
+       99, 122, 105
 };
-static const int lexer_goto_row123[] = {
+static const int lexer_goto_row125[] = {
        3,
        48, 110, -38,
-       111, 111, 201,
-       112, 122, 103
+       111, 111, 204,
+       112, 122, 105
 };
-static const int lexer_goto_row124[] = {
+static const int lexer_goto_row126[] = {
        3,
-       48, 99, -107,
-       100, 100, 202,
-       101, 122, 103
+       48, 99, -109,
+       100, 100, 205,
+       101, 122, 105
 };
-static const int lexer_goto_row125[] = {
+static const int lexer_goto_row127[] = {
        4,
        48, 95, -35,
-       97, 118, 103,
-       119, 119, 203,
-       120, 122, 103
+       97, 118, 105,
+       119, 119, 206,
+       120, 122, 105
 };
-static const int lexer_goto_row126[] = {
+static const int lexer_goto_row128[] = {
        3,
-       48, 115, -115,
-       116, 116, 204,
-       117, 122, 103
+       48, 115, -117,
+       116, 116, 207,
+       117, 122, 105
 };
-static const int lexer_goto_row127[] = {
+static const int lexer_goto_row129[] = {
        3,
        48, 107, -37,
-       108, 108, 205,
-       109, 122, 103
+       108, 108, 208,
+       109, 122, 105
 };
-static const int lexer_goto_row128[] = {
+static const int lexer_goto_row130[] = {
        4,
        48, 95, -35,
-       97, 98, 103,
-       99, 99, 206,
-       100, 122, 103
+       97, 98, 105,
+       99, 99, 209,
+       100, 122, 105
 };
-static const int lexer_goto_row129[] = {
+static const int lexer_goto_row131[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row130[] = {
-       3,
-       48, 98, -129,
-       99, 99, 207,
-       100, 122, 103
-};
-static const int lexer_goto_row131[] = {
-       5,
-       48, 104, -121,
-       105, 105, 208,
-       106, 110, 103,
-       111, 111, 209,
-       112, 122, 103
-};
 static const int lexer_goto_row132[] = {
        3,
-       48, 97, -35,
-       98, 98, 210,
-       99, 122, 103
+       48, 98, -131,
+       99, 99, 210,
+       100, 122, 105
 };
 static const int lexer_goto_row133[] = {
        5,
-       48, 99, -107,
-       100, 100, 211,
-       101, 115, 103,
-       116, 116, 212,
-       117, 122, 103
+       48, 104, -123,
+       105, 105, 211,
+       106, 110, 105,
+       111, 111, 212,
+       112, 122, 105
 };
 static const int lexer_goto_row134[] = {
        3,
-       48, 107, -37,
-       108, 108, 213,
-       109, 122, 103
+       48, 97, -35,
+       98, 98, 213,
+       99, 122, 105
 };
 static const int lexer_goto_row135[] = {
-       3,
-       48, 111, -120,
-       112, 112, 214,
-       113, 122, 103
+       5,
+       48, 99, -109,
+       100, 100, 214,
+       101, 115, 105,
+       116, 116, 215,
+       117, 122, 105
 };
 static const int lexer_goto_row136[] = {
        3,
-       48, 100, -45,
-       101, 101, 215,
-       102, 122, 103
+       48, 107, -37,
+       108, 108, 216,
+       109, 122, 105
 };
 static const int lexer_goto_row137[] = {
-       4,
-       48, 95, -35,
-       97, 116, 103,
-       117, 117, 216,
-       118, 122, 103
+       3,
+       48, 111, -122,
+       112, 112, 217,
+       113, 122, 105
 };
 static const int lexer_goto_row138[] = {
        3,
-       48, 111, -120,
-       112, 112, 217,
-       113, 122, 103
+       48, 100, -45,
+       101, 101, 218,
+       102, 122, 105
 };
 static const int lexer_goto_row139[] = {
-       3,
-       48, 104, -121,
-       105, 105, 218,
-       106, 122, 103
+       4,
+       48, 95, -35,
+       97, 116, 105,
+       117, 117, 219,
+       118, 122, 105
 };
 static const int lexer_goto_row140[] = {
        3,
-       48, 113, -36,
-       114, 114, 219,
-       115, 122, 103
+       48, 111, -122,
+       112, 112, 220,
+       113, 122, 105
 };
 static const int lexer_goto_row141[] = {
        3,
-       48, 104, -121,
-       105, 105, 220,
-       106, 122, 103
+       48, 104, -123,
+       105, 105, 221,
+       106, 122, 105
 };
 static const int lexer_goto_row142[] = {
        3,
-       48, 115, -115,
-       116, 116, 221,
-       117, 122, 103
+       48, 113, -36,
+       114, 114, 222,
+       115, 122, 105
+};
+static const int lexer_goto_row143[] = {
+       3,
+       48, 104, -123,
+       105, 105, 223,
+       106, 122, 105
 };
 static const int lexer_goto_row144[] = {
+       3,
+       48, 115, -117,
+       116, 116, 224,
+       117, 122, 105
+};
+static const int lexer_goto_row146[] = {
        2,
        0, 123, -55,
-       124, 255, 143
+       124, 255, 145
 };
-static const int lexer_goto_row146[] = {
+static const int lexer_goto_row148[] = {
        3,
-       0, 9, 222,
-       11, 12, 222,
-       14, 255, 222
+       0, 9, 225,
+       11, 12, 225,
+       14, 255, 225
 };
-static const int lexer_goto_row148[] = {
+static const int lexer_goto_row150[] = {
        3,
        0, 124, -55,
-       125, 125, 223,
-       126, 255, 143
+       125, 125, 226,
+       126, 255, 145
 };
-static const int lexer_goto_row150[] = {
+static const int lexer_goto_row152[] = {
        11,
-       0, 9, 224,
-       10, 10, 225,
-       11, 12, 224,
-       13, 13, 226,
-       14, 33, 224,
-       34, 34, 227,
-       35, 91, 224,
-       92, 92, 228,
-       93, 122, 224,
-       123, 123, 229,
-       124, 255, 224
-};
-static const int lexer_goto_row151[] = {
+       0, 9, 227,
+       10, 10, 228,
+       11, 12, 227,
+       13, 13, 229,
+       14, 33, 227,
+       34, 34, 230,
+       35, 91, 227,
+       92, 92, 231,
+       93, 122, 227,
+       123, 123, 232,
+       124, 255, 227
+};
+static const int lexer_goto_row153[] = {
        1,
        0, 255, -59
 };
-static const int lexer_goto_row154[] = {
+static const int lexer_goto_row156[] = {
        9,
-       0, 9, 230,
-       10, 10, 231,
-       11, 12, 230,
-       13, 13, 232,
-       14, 38, 230,
-       39, 39, 233,
-       40, 91, 230,
-       92, 92, 234,
-       93, 255, 230
+       0, 9, 233,
+       10, 10, 234,
+       11, 12, 233,
+       13, 13, 235,
+       14, 38, 233,
+       39, 39, 236,
+       40, 91, 233,
+       92, 92, 237,
+       93, 255, 233
 };
-static const int lexer_goto_row155[] = {
+static const int lexer_goto_row157[] = {
        1,
-       39, 39, 235
-};
-static const int lexer_goto_row158[] = {
-       2,
-       48, 95, -79,
-       117, 117, 236
-};
-static const int lexer_goto_row159[] = {
-       1,
-       48, 117, -159
+       39, 39, 238
 };
 static const int lexer_goto_row160[] = {
-       1,
-       48, 117, -159
+       2,
+       48, 95, -80,
+       117, 117, 239
 };
 static const int lexer_goto_row161[] = {
        1,
-       48, 57, 162
+       48, 117, -161
 };
 static const int lexer_goto_row162[] = {
        1,
-       48, 57, 162
+       48, 117, -161
 };
 static const int lexer_goto_row163[] = {
        1,
-       48, 57, 162
+       48, 57, 164
 };
 static const int lexer_goto_row164[] = {
-       2,
-       48, 95, -81,
-       117, 117, 237
+       1,
+       48, 57, 164
 };
 static const int lexer_goto_row165[] = {
        1,
-       48, 117, -165
+       48, 57, 164
 };
 static const int lexer_goto_row166[] = {
        2,
-       48, 102, -82,
-       117, 117, 238
+       48, 95, -82,
+       117, 117, 240
 };
 static const int lexer_goto_row167[] = {
        1,
        48, 117, -167
 };
 static const int lexer_goto_row168[] = {
-       1,
-       48, 117, -167
+       2,
+       48, 102, -83,
+       117, 117, 241
 };
 static const int lexer_goto_row169[] = {
        1,
-       48, 117, -167
+       48, 117, -169
 };
-static const int lexer_goto_row174[] = {
+static const int lexer_goto_row170[] = {
        1,
-       101, 101, 239
+       48, 117, -169
 };
-static const int lexer_goto_row175[] = {
+static const int lexer_goto_row171[] = {
        1,
-       48, 122, -100
+       48, 117, -169
 };
-static const int lexer_goto_row176[] = {
+static const int lexer_goto_row172[] = {
        1,
-       48, 122, -100
+       48, 117, -84
 };
 static const int lexer_goto_row177[] = {
        1,
-       48, 122, -100
+       101, 101, 242
 };
 static const int lexer_goto_row178[] = {
        1,
-       48, 122, -100
+       48, 122, -102
 };
 static const int lexer_goto_row179[] = {
        1,
-       0, 255, -101
+       48, 122, -102
 };
 static const int lexer_goto_row180[] = {
        1,
-       0, 255, 240
+       48, 122, -102
 };
 static const int lexer_goto_row181[] = {
-       3,
-       0, 124, 241,
-       125, 125, 242,
-       126, 255, 241
+       1,
+       48, 122, -102
 };
 static const int lexer_goto_row182[] = {
+       1,
+       0, 255, -103
+};
+static const int lexer_goto_row183[] = {
+       1,
+       0, 255, 243
+};
+static const int lexer_goto_row184[] = {
+       3,
+       0, 124, 244,
+       125, 125, 245,
+       126, 255, 244
+};
+static const int lexer_goto_row185[] = {
        3,
        48, 113, -36,
-       114, 114, 243,
-       115, 122, 103
+       114, 114, 246,
+       115, 122, 105
 };
-static const int lexer_goto_row183[] = {
+static const int lexer_goto_row186[] = {
        3,
-       48, 115, -115,
-       116, 116, 244,
-       117, 122, 103
+       48, 115, -117,
+       116, 116, 247,
+       117, 122, 105
 };
-static const int lexer_goto_row184[] = {
+static const int lexer_goto_row187[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row185[] = {
+static const int lexer_goto_row188[] = {
        3,
        48, 100, -45,
-       101, 101, 245,
-       102, 122, 103
+       101, 101, 248,
+       102, 122, 105
 };
-static const int lexer_goto_row186[] = {
+static const int lexer_goto_row189[] = {
        3,
        48, 95, -35,
-       97, 97, 246,
-       98, 122, 103
+       97, 97, 249,
+       98, 122, 105
 };
-static const int lexer_goto_row187[] = {
+static const int lexer_goto_row190[] = {
        3,
-       48, 114, -108,
-       115, 115, 247,
-       116, 122, 103
+       48, 114, -110,
+       115, 115, 250,
+       116, 122, 105
 };
-static const int lexer_goto_row188[] = {
+static const int lexer_goto_row191[] = {
        3,
-       48, 115, -115,
-       116, 116, 248,
-       117, 122, 103
+       48, 115, -117,
+       116, 116, 251,
+       117, 122, 105
 };
-static const int lexer_goto_row189[] = {
+static const int lexer_goto_row192[] = {
        3,
        48, 100, -45,
-       101, 101, 249,
-       102, 122, 103
+       101, 101, 252,
+       102, 122, 105
 };
-static const int lexer_goto_row190[] = {
+static const int lexer_goto_row193[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row191[] = {
+static const int lexer_goto_row194[] = {
        4,
        48, 95, -35,
-       97, 108, 103,
-       109, 109, 250,
-       110, 122, 103
+       97, 108, 105,
+       109, 109, 253,
+       110, 122, 105
 };
-static const int lexer_goto_row192[] = {
+static const int lexer_goto_row195[] = {
        3,
        48, 100, -45,
-       101, 101, 251,
-       102, 122, 103
+       101, 101, 254,
+       102, 122, 105
 };
-static const int lexer_goto_row193[] = {
+static const int lexer_goto_row196[] = {
        3,
-       48, 114, -108,
-       115, 115, 252,
-       116, 122, 103
+       48, 114, -110,
+       115, 115, 255,
+       116, 122, 105
 };
-static const int lexer_goto_row194[] = {
+static const int lexer_goto_row197[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row195[] = {
+static const int lexer_goto_row198[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row196[] = {
+static const int lexer_goto_row199[] = {
        5,
        48, 107, -37,
-       108, 108, 253,
-       109, 110, 103,
-       111, 111, 254,
-       112, 122, 103
+       108, 108, 256,
+       109, 110, 105,
+       111, 111, 257,
+       112, 122, 105
 };
-static const int lexer_goto_row197[] = {
+static const int lexer_goto_row200[] = {
        3,
-       48, 115, -115,
-       116, 116, 255,
-       117, 122, 103
+       48, 115, -117,
+       116, 116, 258,
+       117, 122, 105
 };
-static const int lexer_goto_row198[] = {
+static const int lexer_goto_row201[] = {
        5,
        48, 100, -45,
-       101, 101, 256,
-       102, 113, 103,
-       114, 114, 257,
-       115, 122, 103
+       101, 101, 259,
+       102, 113, 105,
+       114, 114, 260,
+       115, 122, 105
 };
-static const int lexer_goto_row199[] = {
+static const int lexer_goto_row202[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row200[] = {
+static const int lexer_goto_row203[] = {
        3,
        48, 100, -45,
-       101, 101, 258,
-       102, 122, 103
+       101, 101, 261,
+       102, 122, 105
 };
-static const int lexer_goto_row201[] = {
+static const int lexer_goto_row204[] = {
        3,
        48, 100, -45,
-       101, 101, 259,
-       102, 122, 103
+       101, 101, 262,
+       102, 122, 105
 };
-static const int lexer_goto_row202[] = {
+static const int lexer_goto_row205[] = {
        3,
-       48, 111, -120,
-       112, 112, 260,
-       113, 122, 103
+       48, 111, -122,
+       112, 112, 263,
+       113, 122, 105
 };
-static const int lexer_goto_row203[] = {
+static const int lexer_goto_row206[] = {
        3,
-       48, 116, -138,
-       117, 117, 261,
-       118, 122, 103
+       48, 116, -140,
+       117, 117, 264,
+       118, 122, 105
 };
-static const int lexer_goto_row204[] = {
+static const int lexer_goto_row207[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row205[] = {
+static const int lexer_goto_row208[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row206[] = {
+static const int lexer_goto_row209[] = {
        3,
        48, 107, -37,
-       108, 108, 262,
-       109, 122, 103
+       108, 108, 265,
+       109, 122, 105
 };
-static const int lexer_goto_row207[] = {
+static const int lexer_goto_row210[] = {
        3,
        48, 100, -45,
-       101, 101, 263,
-       102, 122, 103
+       101, 101, 266,
+       102, 122, 105
 };
-static const int lexer_goto_row208[] = {
+static const int lexer_goto_row211[] = {
        4,
        48, 95, -35,
-       97, 106, 103,
-       107, 107, 264,
-       108, 122, 103
+       97, 106, 105,
+       107, 107, 267,
+       108, 122, 105
 };
-static const int lexer_goto_row209[] = {
+static const int lexer_goto_row212[] = {
        4,
        48, 95, -35,
-       97, 117, 103,
-       118, 118, 265,
-       119, 122, 103
-};
-static const int lexer_goto_row210[] = {
-       3,
-       48, 115, -115,
-       116, 116, 266,
-       117, 122, 103
-};
-static const int lexer_goto_row211[] = {
-       3,
-       48, 107, -37,
-       108, 108, 267,
-       109, 122, 103
-};
-static const int lexer_goto_row212[] = {
-       3,
-       48, 100, -45,
-       101, 101, 268,
-       102, 122, 103
+       97, 117, 105,
+       118, 118, 268,
+       119, 122, 105
 };
 static const int lexer_goto_row213[] = {
        3,
-       48, 116, -138,
-       117, 117, 269,
-       118, 122, 103
+       48, 115, -117,
+       116, 116, 269,
+       117, 122, 105
 };
 static const int lexer_goto_row214[] = {
        3,
-       48, 101, -42,
-       102, 102, 270,
-       103, 122, 103
+       48, 107, -37,
+       108, 108, 270,
+       109, 122, 105
 };
 static const int lexer_goto_row215[] = {
        3,
        48, 100, -45,
        101, 101, 271,
-       102, 122, 103
+       102, 122, 105
 };
 static const int lexer_goto_row216[] = {
        3,
-       48, 109, -46,
-       110, 110, 272,
-       111, 122, 103
+       48, 116, -140,
+       117, 117, 272,
+       118, 122, 105
 };
 static const int lexer_goto_row217[] = {
        3,
-       48, 100, -45,
-       101, 101, 273,
-       102, 122, 103
+       48, 101, -42,
+       102, 102, 273,
+       103, 122, 105
 };
 static const int lexer_goto_row218[] = {
        3,
        48, 100, -45,
        101, 101, 274,
-       102, 122, 103
+       102, 122, 105
 };
 static const int lexer_goto_row219[] = {
        3,
-       48, 117, -210,
-       118, 118, 275,
-       119, 122, 103
+       48, 109, -46,
+       110, 110, 275,
+       111, 122, 105
 };
 static const int lexer_goto_row220[] = {
-       1,
-       48, 122, -41
+       3,
+       48, 100, -45,
+       101, 101, 276,
+       102, 122, 105
 };
 static const int lexer_goto_row221[] = {
        3,
-       48, 107, -37,
-       108, 108, 276,
-       109, 122, 103
+       48, 100, -45,
+       101, 101, 277,
+       102, 122, 105
 };
 static const int lexer_goto_row222[] = {
        3,
-       48, 103, -50,
-       104, 104, 277,
-       105, 122, 103
+       48, 117, -213,
+       118, 118, 278,
+       119, 122, 105
 };
 static const int lexer_goto_row223[] = {
        1,
-       0, 255, -145
+       48, 122, -41
 };
 static const int lexer_goto_row224[] = {
-       11,
-       0, 9, 278,
-       10, 10, 279,
-       11, 12, 278,
-       13, 13, 280,
-       14, 33, 278,
-       34, 34, 281,
-       35, 91, 278,
-       92, 92, 282,
-       93, 122, 278,
-       123, 123, 283,
-       124, 255, 278
+       3,
+       48, 107, -37,
+       108, 108, 279,
+       109, 122, 105
 };
 static const int lexer_goto_row225[] = {
-       1,
-       0, 255, -151
+       3,
+       48, 103, -50,
+       104, 104, 280,
+       105, 122, 105
 };
 static const int lexer_goto_row226[] = {
        1,
-       0, 255, -151
+       0, 255, -147
 };
 static const int lexer_goto_row227[] = {
-       1,
-       0, 255, -151
+       11,
+       0, 9, 281,
+       10, 10, 282,
+       11, 12, 281,
+       13, 13, 283,
+       14, 33, 281,
+       34, 34, 284,
+       35, 91, 281,
+       92, 92, 285,
+       93, 122, 281,
+       123, 123, 286,
+       124, 255, 281
 };
 static const int lexer_goto_row228[] = {
-       5,
-       0, 33, -151,
-       34, 34, 284,
-       35, 122, -151,
-       123, 123, 285,
-       124, 255, 224
+       1,
+       0, 255, -153
 };
 static const int lexer_goto_row229[] = {
-       3,
-       0, 9, 286,
-       11, 12, 286,
-       14, 255, 286
+       1,
+       0, 255, -153
 };
 static const int lexer_goto_row230[] = {
+       1,
+       0, 255, -153
+};
+static const int lexer_goto_row231[] = {
        5,
-       0, 33, -151,
+       0, 33, -153,
        34, 34, 287,
-       35, 122, -151,
+       35, 122, -153,
        123, 123, 288,
-       124, 255, 224
-};
-static const int lexer_goto_row231[] = {
-       1,
-       0, 255, -155
+       124, 255, 227
 };
 static const int lexer_goto_row232[] = {
-       1,
-       0, 255, -155
+       3,
+       0, 9, 289,
+       11, 12, 289,
+       14, 255, 289
 };
 static const int lexer_goto_row233[] = {
-       1,
-       0, 255, -155
+       5,
+       0, 33, -153,
+       34, 34, 290,
+       35, 122, -153,
+       123, 123, 291,
+       124, 255, 227
 };
 static const int lexer_goto_row234[] = {
-       9,
-       0, 9, 289,
-       10, 10, 290,
-       11, 12, 289,
-       13, 13, 291,
-       14, 38, 289,
-       39, 39, 292,
-       40, 91, 289,
-       92, 92, 293,
-       93, 255, 289
+       1,
+       0, 255, -157
 };
 static const int lexer_goto_row235[] = {
-       3,
-       0, 9, 294,
-       11, 12, 294,
-       14, 255, 294
-};
-static const int lexer_goto_row237[] = {
        1,
-       56, 56, 295
+       0, 255, -157
 };
-static const int lexer_goto_row238[] = {
+static const int lexer_goto_row236[] = {
        1,
-       56, 56, 296
+       0, 255, -157
 };
-static const int lexer_goto_row239[] = {
-       1,
-       56, 56, 297
+static const int lexer_goto_row237[] = {
+       9,
+       0, 9, 292,
+       10, 10, 293,
+       11, 12, 292,
+       13, 13, 294,
+       14, 38, 292,
+       39, 39, 295,
+       40, 91, 292,
+       92, 92, 296,
+       93, 255, 292
+};
+static const int lexer_goto_row238[] = {
+       3,
+       0, 9, 297,
+       11, 12, 297,
+       14, 255, 297
 };
 static const int lexer_goto_row240[] = {
        1,
-       98, 98, 298
+       56, 56, 298
 };
 static const int lexer_goto_row241[] = {
        1,
-       0, 255, -101
+       56, 56, 299
 };
 static const int lexer_goto_row242[] = {
        1,
-       0, 255, -101
+       56, 56, 300
+};
+static const int lexer_goto_row243[] = {
+       1,
+       98, 98, 301
 };
 static const int lexer_goto_row244[] = {
-       3,
-       48, 115, -115,
-       116, 116, 299,
-       117, 122, 103
+       1,
+       0, 255, -103
 };
 static const int lexer_goto_row245[] = {
-       3,
-       48, 113, -36,
-       114, 114, 300,
-       115, 122, 103
-};
-static const int lexer_goto_row246[] = {
-       3,
-       48, 113, -36,
-       114, 114, 301,
-       115, 122, 103
+       1,
+       0, 255, -103
 };
 static const int lexer_goto_row247[] = {
        3,
-       48, 106, -209,
-       107, 107, 302,
-       108, 122, 103
+       48, 115, -117,
+       116, 116, 302,
+       117, 122, 105
 };
 static const int lexer_goto_row248[] = {
        3,
-       48, 114, -108,
-       115, 115, 303,
-       116, 122, 103
+       48, 113, -36,
+       114, 114, 303,
+       115, 122, 105
 };
 static const int lexer_goto_row249[] = {
        3,
-       48, 104, -121,
-       105, 105, 304,
-       106, 122, 103
+       48, 113, -36,
+       114, 114, 304,
+       115, 122, 105
 };
 static const int lexer_goto_row250[] = {
-       1,
-       48, 122, -41
+       3,
+       48, 106, -212,
+       107, 107, 305,
+       108, 122, 105
 };
 static const int lexer_goto_row251[] = {
-       1,
-       48, 122, -41
+       3,
+       48, 114, -110,
+       115, 115, 306,
+       116, 122, 105
 };
 static const int lexer_goto_row252[] = {
        3,
-       48, 113, -36,
-       114, 114, 305,
-       115, 122, 103
+       48, 104, -123,
+       105, 105, 307,
+       106, 122, 105
 };
 static const int lexer_goto_row253[] = {
-       3,
-       48, 100, -45,
-       101, 101, 306,
-       102, 122, 103
+       1,
+       48, 122, -41
 };
 static const int lexer_goto_row254[] = {
-       3,
-       48, 104, -121,
-       105, 105, 307,
-       106, 122, 103
+       1,
+       48, 122, -41
 };
 static const int lexer_goto_row255[] = {
        3,
        48, 113, -36,
        114, 114, 308,
-       115, 122, 103
+       115, 122, 105
 };
 static const int lexer_goto_row256[] = {
-       1,
-       48, 122, -41
+       3,
+       48, 100, -45,
+       101, 101, 309,
+       102, 122, 105
 };
 static const int lexer_goto_row257[] = {
        3,
-       48, 113, -36,
-       114, 114, 309,
-       115, 122, 103
+       48, 104, -123,
+       105, 105, 310,
+       106, 122, 105
 };
 static const int lexer_goto_row258[] = {
        3,
-       48, 116, -138,
-       117, 117, 310,
-       118, 122, 103
+       48, 113, -36,
+       114, 114, 311,
+       115, 122, 105
 };
 static const int lexer_goto_row259[] = {
-       3,
-       48, 115, -115,
-       116, 116, 311,
-       117, 122, 103
+       1,
+       48, 122, -41
 };
 static const int lexer_goto_row260[] = {
        3,
-       48, 107, -37,
-       108, 108, 312,
-       109, 122, 103
+       48, 113, -36,
+       114, 114, 312,
+       115, 122, 105
 };
 static const int lexer_goto_row261[] = {
-       1,
-       48, 122, -41
+       3,
+       48, 116, -140,
+       117, 117, 313,
+       118, 122, 105
 };
 static const int lexer_goto_row262[] = {
        3,
-       48, 107, -37,
-       108, 108, 313,
-       109, 122, 103
+       48, 115, -117,
+       116, 116, 314,
+       117, 122, 105
 };
 static const int lexer_goto_row263[] = {
        3,
-       48, 95, -35,
-       97, 97, 314,
-       98, 122, 103
+       48, 107, -37,
+       108, 108, 315,
+       109, 122, 105
 };
 static const int lexer_goto_row264[] = {
        1,
@@ -1378,450 +1379,450 @@ static const int lexer_goto_row264[] = {
 };
 static const int lexer_goto_row265[] = {
        3,
-       48, 95, -35,
-       97, 97, 315,
-       98, 122, 103
+       48, 107, -37,
+       108, 108, 316,
+       109, 122, 105
 };
 static const int lexer_goto_row266[] = {
        3,
        48, 95, -35,
-       97, 97, 316,
-       98, 122, 103
+       97, 97, 317,
+       98, 122, 105
 };
 static const int lexer_goto_row267[] = {
-       3,
-       48, 100, -45,
-       101, 101, 317,
-       102, 122, 103
+       1,
+       48, 122, -41
 };
 static const int lexer_goto_row268[] = {
        3,
-       48, 104, -121,
-       105, 105, 318,
-       106, 122, 103
+       48, 95, -35,
+       97, 97, 318,
+       98, 122, 105
 };
 static const int lexer_goto_row269[] = {
        3,
-       48, 101, -42,
-       102, 102, 319,
-       103, 122, 103
+       48, 95, -35,
+       97, 97, 319,
+       98, 122, 105
 };
 static const int lexer_goto_row270[] = {
        3,
-       48, 113, -36,
-       114, 114, 320,
-       115, 122, 103
+       48, 100, -45,
+       101, 101, 320,
+       102, 122, 105
 };
 static const int lexer_goto_row271[] = {
-       1,
-       48, 122, -41
+       3,
+       48, 104, -123,
+       105, 105, 321,
+       106, 122, 105
 };
 static const int lexer_goto_row272[] = {
        3,
-       48, 113, -36,
-       114, 114, 321,
-       115, 122, 103
+       48, 101, -42,
+       102, 102, 322,
+       103, 122, 105
 };
 static const int lexer_goto_row273[] = {
-       1,
-       48, 122, -41
+       3,
+       48, 113, -36,
+       114, 114, 323,
+       115, 122, 105
 };
 static const int lexer_goto_row274[] = {
        1,
        48, 122, -41
 };
 static const int lexer_goto_row275[] = {
-       1,
-       48, 122, -41
+       3,
+       48, 113, -36,
+       114, 114, 324,
+       115, 122, 105
 };
 static const int lexer_goto_row276[] = {
-       3,
-       48, 100, -45,
-       101, 101, 322,
-       102, 122, 103
+       1,
+       48, 122, -41
 };
 static const int lexer_goto_row277[] = {
-       3,
-       48, 100, -45,
-       101, 101, 323,
-       102, 122, 103
+       1,
+       48, 122, -41
 };
 static const int lexer_goto_row278[] = {
        1,
        48, 122, -41
 };
 static const int lexer_goto_row279[] = {
-       1,
-       0, 255, -225
+       3,
+       48, 100, -45,
+       101, 101, 325,
+       102, 122, 105
 };
 static const int lexer_goto_row280[] = {
-       11,
-       0, 9, 324,
-       10, 10, 279,
-       11, 12, 324,
-       13, 13, 280,
-       14, 33, 324,
-       34, 34, 325,
-       35, 91, 324,
-       92, 92, 326,
-       93, 122, 324,
-       123, 123, 327,
-       124, 255, 324
+       3,
+       48, 100, -45,
+       101, 101, 326,
+       102, 122, 105
 };
 static const int lexer_goto_row281[] = {
        1,
-       0, 255, -281
+       48, 122, -41
 };
 static const int lexer_goto_row282[] = {
-       5,
-       0, 33, -281,
-       34, 34, 328,
-       35, 122, -281,
-       123, 123, 329,
-       124, 255, 324
+       1,
+       0, 255, -228
 };
 static const int lexer_goto_row283[] = {
-       3,
-       0, 9, 330,
-       11, 12, 330,
-       14, 255, 330
+       11,
+       0, 9, 327,
+       10, 10, 282,
+       11, 12, 327,
+       13, 13, 283,
+       14, 33, 327,
+       34, 34, 328,
+       35, 91, 327,
+       92, 92, 329,
+       93, 122, 327,
+       123, 123, 330,
+       124, 255, 327
 };
 static const int lexer_goto_row284[] = {
+       1,
+       0, 255, -284
+};
+static const int lexer_goto_row285[] = {
        5,
-       0, 33, -281,
+       0, 33, -284,
        34, 34, 331,
-       35, 122, -281,
+       35, 122, -284,
        123, 123, 332,
-       124, 255, 324
-};
-static const int lexer_goto_row285[] = {
-       3,
-       0, 33, -151,
-       34, 34, 333,
-       35, 255, -229
+       124, 255, 327
 };
 static const int lexer_goto_row286[] = {
        3,
-       0, 122, -231,
-       123, 123, 334,
-       124, 255, 224
+       0, 9, 333,
+       11, 12, 333,
+       14, 255, 333
 };
 static const int lexer_goto_row287[] = {
-       1,
-       0, 255, -151
+       5,
+       0, 33, -284,
+       34, 34, 334,
+       35, 122, -284,
+       123, 123, 335,
+       124, 255, 327
 };
 static const int lexer_goto_row288[] = {
        3,
-       0, 33, -151,
-       34, 34, 335,
-       35, 255, -229
+       0, 33, -153,
+       34, 34, 336,
+       35, 255, -232
 };
 static const int lexer_goto_row289[] = {
        3,
-       0, 122, -231,
-       123, 123, 336,
-       124, 255, 224
+       0, 122, -234,
+       123, 123, 337,
+       124, 255, 227
 };
 static const int lexer_goto_row290[] = {
        1,
-       0, 255, -155
+       0, 255, -153
 };
 static const int lexer_goto_row291[] = {
-       1,
-       0, 255, -155
+       3,
+       0, 33, -153,
+       34, 34, 338,
+       35, 255, -232
 };
 static const int lexer_goto_row292[] = {
-       1,
-       0, 255, -155
+       3,
+       0, 122, -234,
+       123, 123, 339,
+       124, 255, 227
 };
 static const int lexer_goto_row293[] = {
-       9,
-       0, 9, 337,
-       10, 10, 338,
-       11, 12, 337,
-       13, 13, 339,
-       14, 38, 337,
-       39, 39, 340,
-       40, 91, 337,
-       92, 92, 341,
-       93, 255, 337
+       1,
+       0, 255, -157
 };
 static const int lexer_goto_row294[] = {
-       3,
-       0, 9, 342,
-       11, 12, 342,
-       14, 255, 342
+       1,
+       0, 255, -157
 };
 static const int lexer_goto_row295[] = {
        1,
-       0, 255, -155
+       0, 255, -157
+};
+static const int lexer_goto_row296[] = {
+       9,
+       0, 9, 340,
+       10, 10, 341,
+       11, 12, 340,
+       13, 13, 342,
+       14, 38, 340,
+       39, 39, 343,
+       40, 91, 340,
+       92, 92, 344,
+       93, 255, 340
+};
+static const int lexer_goto_row297[] = {
+       3,
+       0, 9, 345,
+       11, 12, 345,
+       14, 255, 345
+};
+static const int lexer_goto_row298[] = {
+       1,
+       0, 255, -157
 };
-static const int lexer_goto_row299[] = {
+static const int lexer_goto_row302[] = {
        1,
-       117, 117, 343
+       117, 117, 346
 };
-static const int lexer_goto_row300[] = {
+static const int lexer_goto_row303[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row301[] = {
+static const int lexer_goto_row304[] = {
        3,
        48, 95, -35,
-       97, 97, 344,
-       98, 122, 103
+       97, 97, 347,
+       98, 122, 105
 };
-static const int lexer_goto_row302[] = {
+static const int lexer_goto_row305[] = {
        3,
-       48, 115, -115,
-       116, 116, 345,
-       117, 122, 103
+       48, 115, -117,
+       116, 116, 348,
+       117, 122, 105
 };
-static const int lexer_goto_row303[] = {
+static const int lexer_goto_row306[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row304[] = {
+static const int lexer_goto_row307[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row305[] = {
+static const int lexer_goto_row308[] = {
        3,
        48, 109, -46,
-       110, 110, 346,
-       111, 122, 103
+       110, 110, 349,
+       111, 122, 105
 };
-static const int lexer_goto_row306[] = {
+static const int lexer_goto_row309[] = {
        3,
        48, 109, -46,
-       110, 110, 347,
-       111, 122, 103
+       110, 110, 350,
+       111, 122, 105
 };
-static const int lexer_goto_row307[] = {
+static const int lexer_goto_row310[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row308[] = {
+static const int lexer_goto_row311[] = {
        3,
        48, 100, -45,
-       101, 101, 348,
-       102, 122, 103
+       101, 101, 351,
+       102, 122, 105
 };
-static const int lexer_goto_row309[] = {
+static const int lexer_goto_row312[] = {
        3,
-       48, 115, -115,
-       116, 116, 349,
-       117, 122, 103
+       48, 115, -117,
+       116, 116, 352,
+       117, 122, 105
 };
-static const int lexer_goto_row310[] = {
+static const int lexer_goto_row313[] = {
        3,
        48, 101, -42,
-       102, 102, 350,
-       103, 122, 103
+       102, 102, 353,
+       103, 122, 105
 };
-static const int lexer_goto_row311[] = {
+static const int lexer_goto_row314[] = {
        3,
-       48, 99, -107,
-       100, 100, 351,
-       101, 122, 103
+       48, 99, -109,
+       100, 100, 354,
+       101, 122, 105
 };
-static const int lexer_goto_row312[] = {
+static const int lexer_goto_row315[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row313[] = {
+static const int lexer_goto_row316[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row314[] = {
+static const int lexer_goto_row317[] = {
        3,
        48, 100, -45,
-       101, 101, 352,
-       102, 122, 103
+       101, 101, 355,
+       102, 122, 105
 };
-static const int lexer_goto_row315[] = {
+static const int lexer_goto_row318[] = {
        3,
        48, 97, -35,
-       98, 98, 353,
-       99, 122, 103
+       98, 98, 356,
+       99, 122, 105
 };
-static const int lexer_goto_row316[] = {
+static const int lexer_goto_row319[] = {
        4,
        48, 95, -35,
-       97, 102, 103,
-       103, 103, 354,
-       104, 122, 103
+       97, 102, 105,
+       103, 103, 357,
+       104, 122, 105
 };
-static const int lexer_goto_row317[] = {
+static const int lexer_goto_row320[] = {
        3,
-       48, 115, -115,
-       116, 116, 355,
-       117, 122, 103
+       48, 115, -117,
+       116, 116, 358,
+       117, 122, 105
 };
-static const int lexer_goto_row318[] = {
+static const int lexer_goto_row321[] = {
        3,
-       48, 98, -129,
-       99, 99, 356,
-       100, 122, 103
+       48, 98, -131,
+       99, 99, 359,
+       100, 122, 105
 };
-static const int lexer_goto_row319[] = {
+static const int lexer_goto_row322[] = {
        3,
-       48, 98, -129,
-       99, 99, 357,
-       100, 122, 103
+       48, 98, -131,
+       99, 99, 360,
+       100, 122, 105
 };
-static const int lexer_goto_row320[] = {
+static const int lexer_goto_row323[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row321[] = {
+static const int lexer_goto_row324[] = {
        3,
        48, 109, -46,
-       110, 110, 358,
-       111, 122, 103
+       110, 110, 361,
+       111, 122, 105
 };
-static const int lexer_goto_row322[] = {
+static const int lexer_goto_row325[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row323[] = {
+static const int lexer_goto_row326[] = {
        3,
        48, 113, -36,
-       114, 114, 359,
-       115, 122, 103
+       114, 114, 362,
+       115, 122, 105
 };
-static const int lexer_goto_row324[] = {
+static const int lexer_goto_row327[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row325[] = {
-       1,
-       0, 255, -281
-};
-static const int lexer_goto_row326[] = {
-       1,
-       0, 255, -283
-};
-static const int lexer_goto_row327[] = {
-       3,
-       0, 9, 360,
-       11, 12, 360,
-       14, 255, 360
-};
 static const int lexer_goto_row328[] = {
        1,
-       0, 255, -285
+       0, 255, -284
 };
 static const int lexer_goto_row329[] = {
-       3,
-       0, 33, -281,
-       34, 34, 361,
-       35, 255, -283
+       1,
+       0, 255, -286
 };
 static const int lexer_goto_row330[] = {
        3,
-       0, 122, -285,
-       123, 123, 362,
-       124, 255, 324
+       0, 9, 363,
+       11, 12, 363,
+       14, 255, 363
 };
 static const int lexer_goto_row331[] = {
        1,
-       0, 255, -225
+       0, 255, -288
 };
 static const int lexer_goto_row332[] = {
        3,
-       0, 33, -281,
-       34, 34, 363,
-       35, 255, -283
+       0, 33, -284,
+       34, 34, 364,
+       35, 255, -286
 };
 static const int lexer_goto_row333[] = {
        3,
-       0, 122, -285,
-       123, 123, 364,
-       124, 255, 324
+       0, 122, -288,
+       123, 123, 365,
+       124, 255, 327
 };
 static const int lexer_goto_row334[] = {
        1,
-       34, 34, 365
+       0, 255, -228
 };
 static const int lexer_goto_row335[] = {
-       1,
-       0, 255, -290
+       3,
+       0, 33, -284,
+       34, 34, 366,
+       35, 255, -286
 };
 static const int lexer_goto_row336[] = {
-       1,
-       0, 255, -286
+       3,
+       0, 122, -288,
+       123, 123, 367,
+       124, 255, 327
 };
 static const int lexer_goto_row337[] = {
        1,
-       123, 123, 366
+       34, 34, 368
 };
 static const int lexer_goto_row338[] = {
        1,
-       0, 255, -155
+       0, 255, -293
 };
 static const int lexer_goto_row339[] = {
        1,
-       0, 255, -155
+       0, 255, -289
 };
 static const int lexer_goto_row340[] = {
        1,
-       0, 255, -155
+       123, 123, 369
 };
-static const int lexer_goto_row342[] = {
-       3,
-       0, 9, 367,
-       11, 12, 367,
-       14, 255, 367
+static const int lexer_goto_row341[] = {
+       1,
+       0, 255, -157
 };
-static const int lexer_goto_row343[] = {
+static const int lexer_goto_row342[] = {
        1,
-       0, 255, -155
+       0, 255, -157
 };
-static const int lexer_goto_row344[] = {
+static const int lexer_goto_row343[] = {
        1,
-       103, 103, 368
+       0, 255, -157
 };
 static const int lexer_goto_row345[] = {
        3,
-       48, 98, -129,
-       99, 99, 369,
-       100, 122, 103
+       0, 9, 370,
+       11, 12, 370,
+       14, 255, 370
 };
 static const int lexer_goto_row346[] = {
        1,
-       48, 122, -41
+       0, 255, -157
 };
 static const int lexer_goto_row347[] = {
-       3,
-       48, 116, -138,
-       117, 117, 370,
-       118, 122, 103
+       1,
+       103, 103, 371
 };
 static const int lexer_goto_row348[] = {
+       3,
+       48, 98, -131,
+       99, 99, 372,
+       100, 122, 105
+};
+static const int lexer_goto_row349[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row349[] = {
+static const int lexer_goto_row350[] = {
        3,
-       48, 114, -108,
-       115, 115, 371,
-       116, 122, 103
+       48, 116, -140,
+       117, 117, 373,
+       118, 122, 105
 };
-static const int lexer_goto_row350[] = {
+static const int lexer_goto_row351[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row351[] = {
-       3,
-       48, 95, -35,
-       97, 97, 372,
-       98, 122, 103
-};
 static const int lexer_goto_row352[] = {
        3,
-       48, 100, -45,
-       101, 101, 373,
-       102, 122, 103
+       48, 114, -110,
+       115, 115, 374,
+       116, 122, 105
 };
 static const int lexer_goto_row353[] = {
        1,
@@ -1829,114 +1830,116 @@ static const int lexer_goto_row353[] = {
 };
 static const int lexer_goto_row354[] = {
        3,
-       48, 107, -37,
-       108, 108, 374,
-       109, 122, 103
+       48, 95, -35,
+       97, 97, 375,
+       98, 122, 105
 };
 static const int lexer_goto_row355[] = {
        3,
        48, 100, -45,
-       101, 101, 375,
-       102, 122, 103
+       101, 101, 376,
+       102, 122, 105
 };
 static const int lexer_goto_row356[] = {
-       3,
-       48, 100, -45,
-       101, 101, 376,
-       102, 122, 103
+       1,
+       48, 122, -41
 };
 static const int lexer_goto_row357[] = {
        3,
-       48, 115, -115,
-       116, 116, 377,
-       117, 122, 103
+       48, 107, -37,
+       108, 108, 377,
+       109, 122, 105
 };
 static const int lexer_goto_row358[] = {
-       1,
-       48, 122, -41
+       3,
+       48, 100, -45,
+       101, 101, 378,
+       102, 122, 105
 };
 static const int lexer_goto_row359[] = {
-       1,
-       48, 122, -41
+       3,
+       48, 100, -45,
+       101, 101, 379,
+       102, 122, 105
 };
 static const int lexer_goto_row360[] = {
        3,
-       48, 114, -108,
-       115, 115, 378,
-       116, 122, 103
+       48, 115, -117,
+       116, 116, 380,
+       117, 122, 105
 };
 static const int lexer_goto_row361[] = {
        1,
-       0, 255, -281
+       48, 122, -41
 };
 static const int lexer_goto_row362[] = {
        1,
-       34, 34, 379
+       48, 122, -41
 };
 static const int lexer_goto_row363[] = {
-       1,
-       0, 255, -334
+       3,
+       48, 114, -110,
+       115, 115, 381,
+       116, 122, 105
 };
 static const int lexer_goto_row364[] = {
        1,
-       0, 255, -330
+       0, 255, -284
 };
 static const int lexer_goto_row365[] = {
        1,
-       123, 123, 380
+       34, 34, 382
 };
 static const int lexer_goto_row366[] = {
        1,
-       34, 34, 365
+       0, 255, -337
 };
 static const int lexer_goto_row367[] = {
        1,
-       123, 123, 366
+       0, 255, -333
 };
 static const int lexer_goto_row368[] = {
        1,
-       0, 255, -155
+       123, 123, 383
 };
 static const int lexer_goto_row369[] = {
        1,
-       95, 95, 381
+       34, 34, 368
 };
 static const int lexer_goto_row370[] = {
-       3,
-       48, 115, -115,
-       116, 116, 382,
-       117, 122, 103
+       1,
+       123, 123, 369
 };
 static const int lexer_goto_row371[] = {
-       3,
-       48, 100, -45,
-       101, 101, 383,
-       102, 122, 103
+       1,
+       0, 255, -157
 };
 static const int lexer_goto_row372[] = {
        1,
-       48, 122, -41
+       95, 95, 384
 };
 static const int lexer_goto_row373[] = {
        3,
-       48, 98, -129,
-       99, 99, 384,
-       100, 122, 103
+       48, 115, -117,
+       116, 116, 385,
+       117, 122, 105
 };
 static const int lexer_goto_row374[] = {
-       1,
-       48, 122, -41
-};
-static const int lexer_goto_row375[] = {
        3,
        48, 100, -45,
-       101, 101, 385,
-       102, 122, 103
+       101, 101, 386,
+       102, 122, 105
 };
-static const int lexer_goto_row376[] = {
+static const int lexer_goto_row375[] = {
        1,
        48, 122, -41
 };
+static const int lexer_goto_row376[] = {
+       3,
+       48, 98, -131,
+       99, 99, 387,
+       100, 122, 105
+};
 static const int lexer_goto_row377[] = {
        1,
        48, 122, -41
@@ -1944,66 +1947,80 @@ static const int lexer_goto_row377[] = {
 static const int lexer_goto_row378[] = {
        3,
        48, 100, -45,
-       101, 101, 386,
-       102, 122, 103
+       101, 101, 388,
+       102, 122, 105
 };
 static const int lexer_goto_row379[] = {
-       3,
-       48, 95, -35,
-       97, 97, 387,
-       98, 122, 103
+       1,
+       48, 122, -41
 };
 static const int lexer_goto_row380[] = {
        1,
-       34, 34, 379
+       48, 122, -41
 };
 static const int lexer_goto_row381[] = {
-       1,
-       123, 123, 380
+       3,
+       48, 100, -45,
+       101, 101, 389,
+       102, 122, 105
 };
 static const int lexer_goto_row382[] = {
-       1,
-       95, 95, 388
+       3,
+       48, 95, -35,
+       97, 97, 390,
+       98, 122, 105
 };
 static const int lexer_goto_row383[] = {
        1,
-       48, 122, -41
+       34, 34, 382
 };
 static const int lexer_goto_row384[] = {
        1,
-       48, 122, -41
+       123, 123, 383
 };
 static const int lexer_goto_row385[] = {
-       3,
-       48, 100, -45,
-       101, 101, 389,
-       102, 122, 103
+       1,
+       95, 95, 391
 };
 static const int lexer_goto_row386[] = {
        1,
        48, 122, -41
 };
 static const int lexer_goto_row387[] = {
-       3,
-       48, 99, -107,
-       100, 100, 390,
-       101, 122, 103
+       1,
+       48, 122, -41
 };
 static const int lexer_goto_row388[] = {
        3,
-       48, 107, -37,
-       108, 108, 391,
-       109, 122, 103
+       48, 100, -45,
+       101, 101, 392,
+       102, 122, 105
 };
-static const int lexer_goto_row390[] = {
+static const int lexer_goto_row389[] = {
        1,
        48, 122, -41
 };
+static const int lexer_goto_row390[] = {
+       3,
+       48, 99, -109,
+       100, 100, 393,
+       101, 122, 105
+};
 static const int lexer_goto_row391[] = {
+       3,
+       48, 107, -37,
+       108, 108, 394,
+       109, 122, 105
+};
+static const int lexer_goto_row393[] = {
+       1,
+       48, 122, -41
+};
+static const int lexer_goto_row394[] = {
        1,
        48, 122, -41
 };
-static const int lexer_goto_row392[] = {
+static const int lexer_goto_row395[] = {
        1,
        48, 122, -41
 };
@@ -2095,19 +2112,19 @@ const int* const lexer_goto_table[] = {
        lexer_goto_row84,
        lexer_goto_row85,
        lexer_goto_row86,
-       lexer_goto_row_null,
+       lexer_goto_row87,
        lexer_goto_row88,
-       lexer_goto_row89,
+       lexer_goto_row_null,
+       lexer_goto_row90,
+       lexer_goto_row91,
        lexer_goto_row_null,
        lexer_goto_row_null,
-       lexer_goto_row92,
-       lexer_goto_row93,
        lexer_goto_row94,
        lexer_goto_row95,
        lexer_goto_row96,
-       lexer_goto_row_null,
+       lexer_goto_row97,
        lexer_goto_row98,
-       lexer_goto_row99,
+       lexer_goto_row_null,
        lexer_goto_row100,
        lexer_goto_row101,
        lexer_goto_row102,
@@ -2151,7 +2168,7 @@ const int* const lexer_goto_table[] = {
        lexer_goto_row140,
        lexer_goto_row141,
        lexer_goto_row142,
-       lexer_goto_row_null,
+       lexer_goto_row143,
        lexer_goto_row144,
        lexer_goto_row_null,
        lexer_goto_row146,
@@ -2159,15 +2176,15 @@ const int* const lexer_goto_table[] = {
        lexer_goto_row148,
        lexer_goto_row_null,
        lexer_goto_row150,
-       lexer_goto_row151,
+       lexer_goto_row_null,
+       lexer_goto_row152,
+       lexer_goto_row153,
        lexer_goto_row_null,
        lexer_goto_row_null,
-       lexer_goto_row154,
-       lexer_goto_row155,
+       lexer_goto_row156,
+       lexer_goto_row157,
        lexer_goto_row_null,
        lexer_goto_row_null,
-       lexer_goto_row158,
-       lexer_goto_row159,
        lexer_goto_row160,
        lexer_goto_row161,
        lexer_goto_row162,
@@ -2178,13 +2195,13 @@ const int* const lexer_goto_table[] = {
        lexer_goto_row167,
        lexer_goto_row168,
        lexer_goto_row169,
+       lexer_goto_row170,
+       lexer_goto_row171,
+       lexer_goto_row172,
        lexer_goto_row_null,
        lexer_goto_row_null,
        lexer_goto_row_null,
        lexer_goto_row_null,
-       lexer_goto_row174,
-       lexer_goto_row175,
-       lexer_goto_row176,
        lexer_goto_row177,
        lexer_goto_row178,
        lexer_goto_row179,
@@ -2244,17 +2261,17 @@ const int* const lexer_goto_table[] = {
        lexer_goto_row233,
        lexer_goto_row234,
        lexer_goto_row235,
-       lexer_goto_row_null,
+       lexer_goto_row236,
        lexer_goto_row237,
        lexer_goto_row238,
-       lexer_goto_row239,
+       lexer_goto_row_null,
        lexer_goto_row240,
        lexer_goto_row241,
        lexer_goto_row242,
-       lexer_goto_row_null,
+       lexer_goto_row243,
        lexer_goto_row244,
        lexer_goto_row245,
-       lexer_goto_row246,
+       lexer_goto_row_null,
        lexer_goto_row247,
        lexer_goto_row248,
        lexer_goto_row249,
@@ -2304,12 +2321,12 @@ const int* const lexer_goto_table[] = {
        lexer_goto_row293,
        lexer_goto_row294,
        lexer_goto_row295,
+       lexer_goto_row296,
+       lexer_goto_row297,
+       lexer_goto_row298,
        lexer_goto_row_null,
        lexer_goto_row_null,
        lexer_goto_row_null,
-       lexer_goto_row299,
-       lexer_goto_row300,
-       lexer_goto_row301,
        lexer_goto_row302,
        lexer_goto_row303,
        lexer_goto_row304,
@@ -2349,10 +2366,10 @@ const int* const lexer_goto_table[] = {
        lexer_goto_row338,
        lexer_goto_row339,
        lexer_goto_row340,
-       lexer_goto_row_null,
+       lexer_goto_row341,
        lexer_goto_row342,
        lexer_goto_row343,
-       lexer_goto_row344,
+       lexer_goto_row_null,
        lexer_goto_row345,
        lexer_goto_row346,
        lexer_goto_row347,
@@ -2397,14 +2414,17 @@ const int* const lexer_goto_table[] = {
        lexer_goto_row386,
        lexer_goto_row387,
        lexer_goto_row388,
-       lexer_goto_row_null,
+       lexer_goto_row389,
        lexer_goto_row390,
        lexer_goto_row391,
-       lexer_goto_row392
+       lexer_goto_row_null,
+       lexer_goto_row393,
+       lexer_goto_row394,
+       lexer_goto_row395
 };
 
 const int lexer_accept_table[] = {
-       -1,0,1,1,0,94,114,2,80,83,-1,53,54,77,75,57,76,74,79,100,100,58,96,87,60,90,95,97,55,56,82,-1,-1,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,81,114,84,1,86,114,109,-1,110,2,2,2,65,69,115,115,115,78,63,61,62,73,108,64,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,59,89,88,85,91,92,97,97,97,97,68,-1,99,-1,98,98,98,98,98,98,47,98,98,98,16,98,98,98,98,98,98,23,98,29,15,98,98,98,98,98,98,98,31,98,98,98,98,98,98,98,98,98,98,98,98,98,67,114,112,-1,111,114,109,114,114,2,113,114,115,66,72,102,102,102,-1,-1,108,103,103,101,101,101,101,104,70,93,71,-1,99,99,99,99,-1,-1,-1,98,98,30,98,98,98,98,98,10,98,98,98,28,11,98,98,98,40,98,98,98,98,39,32,98,98,98,98,98,98,98,98,98,98,98,98,98,98,17,98,98,114,114,114,114,114,-1,-1,-1,114,114,114,-1,-1,113,-1,-1,-1,-1,-1,-1,116,98,98,98,98,98,98,25,9,98,98,98,98,13,98,98,98,98,27,98,46,41,98,98,98,98,98,98,43,98,24,44,12,98,98,51,114,-1,-1,112,-1,111,-1,-1,114,-1,-1,114,114,114,-1,-1,114,106,107,105,-1,37,98,98,36,6,98,98,45,98,98,98,98,49,50,98,98,98,98,98,98,14,98,42,98,26,-1,-1,-1,-1,-1,-1,114,-1,-1,109,-1,-1,110,114,114,114,109,-1,114,-1,98,38,98,18,98,5,98,98,4,98,98,98,98,19,34,98,-1,112,-1,-1,111,109,110,114,-1,98,98,33,98,22,98,3,21,98,98,112,111,-1,7,35,98,48,98,98,52,8,20,9
+       -1,0,1,1,0,94,114,2,80,83,-1,53,54,77,75,57,76,74,79,100,100,58,96,87,60,90,95,97,55,56,82,-1,-1,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,81,114,84,1,86,114,109,-1,110,2,2,2,65,69,115,115,115,78,63,61,62,73,108,64,-1,100,-1,-1,-1,-1,100,-1,-1,-1,-1,-1,59,89,88,85,91,92,97,97,97,97,68,-1,99,-1,98,98,98,98,98,98,47,98,98,98,16,98,98,98,98,98,98,23,98,29,15,98,98,98,98,98,98,98,31,98,98,98,98,98,98,98,98,98,98,98,98,98,67,114,112,-1,111,114,109,114,114,2,113,114,115,66,72,102,102,102,-1,-1,108,103,103,101,101,101,101,100,104,70,93,71,-1,99,99,99,99,-1,-1,-1,98,98,30,98,98,98,98,98,10,98,98,98,28,11,98,98,98,40,98,98,98,98,39,32,98,98,98,98,98,98,98,98,98,98,98,98,98,98,17,98,98,114,114,114,114,114,-1,-1,-1,114,114,114,-1,-1,113,-1,-1,-1,-1,-1,-1,116,98,98,98,98,98,98,25,9,98,98,98,98,13,98,98,98,98,27,98,46,41,98,98,98,98,98,98,43,98,24,44,12,98,98,51,114,-1,-1,112,-1,111,-1,-1,114,-1,-1,114,114,114,-1,-1,114,106,107,105,-1,37,98,98,36,6,98,98,45,98,98,98,98,49,50,98,98,98,98,98,98,14,98,42,98,26,-1,-1,-1,-1,-1,-1,114,-1,-1,109,-1,-1,110,114,114,114,109,-1,114,-1,98,38,98,18,98,5,98,98,4,98,98,98,98,19,34,98,-1,112,-1,-1,111,109,110,114,-1,98,98,33,98,22,98,3,21,98,98,112,111,-1,7,35,98,48,98,98,52,8,20,9
 };
 
 static int parser_action_row1[] = {
index b21c85e..8a1bb4c 100644 (file)
@@ -16,13 +16,16 @@ import standard::kernel
 
 assert 0b1001 == 0x09
 assert 0o715 == 0x1CD
-assert 461 == 0o715
+assert 46_1 == 0o715
 assert 0b111001101 == 0o715
-assert 256 == 0x100
-assert 0o400 == 256
+assert 2_56 == 0x100
+assert 0o400 == 2_56
 assert 0b1_1100_1101 == 0o715
 assert 0b1_1100_1101 == 0x1_CD
 assert 0b1000_1001 == 0x89
 assert 0b1000_1001u8 == 0x89u8
 assert 0o151u8 == 0b0110_1001u8
 assert 0x69u8 == 0o151u8
+assert 12_125 == 0x2F5D
+assert 0o27_535 == 1212_5
+assert 2_55u8 == 0xFFu8
index 9718dc3..ad78ced 100644 (file)
@@ -29,3 +29,4 @@ input
 first_letter_last_letter
 fibonacci_word
 shootout_nsieve
+test_ropebuffer
index 9718dc3..ad78ced 100644 (file)
@@ -29,3 +29,4 @@ input
 first_letter_last_letter
 fibonacci_word
 shootout_nsieve
+test_ropebuffer
index a74724b..a376c79 100644 (file)
@@ -1,3 +1,3 @@
-base_error_literal.nit:17,9--11: Error: invalid binary literal
-base_error_literal.nit:18,9--11: Error: invalid hexadecimal literal
-base_error_literal.nit:19,9--11: Error: invalid octal literal
+base_error_literal.nit:17,9--11: Error: invalid literal `0b_`
+base_error_literal.nit:18,9--11: Error: invalid literal `0x_`
+base_error_literal.nit:19,9--11: Error: invalid literal `0o_`
diff --git a/tests/sav/checker.res b/tests/sav/checker.res
new file mode 100644 (file)
index 0000000..e6fde82
--- /dev/null
@@ -0,0 +1 @@
+Usage: checker xml_file
index 8e55697..f9e2cbb 100644 (file)
@@ -1,4 +1,4 @@
-../lib/standard/stream.nit:426,6--17: Documentation warning: Undocumented property `buffer_reset`
+../lib/standard/stream.nit:451,6--17: Documentation warning: Undocumented property `buffer_reset`
 test_advice_repeated_types.nit:36,15--20: Warning: useless type repetition on redefined attribute `_a`
 test_advice_repeated_types.nit:37,18--20: Warning: useless type repetition on parameter `b1` for redefined method `b`
 test_advice_repeated_types.nit:38,18--20: Warning: useless type repetition on parameter `c1` for redefined method `c`
diff --git a/tests/test_ropebuffer.nit b/tests/test_ropebuffer.nit
new file mode 100644 (file)
index 0000000..aa21a5e
--- /dev/null
@@ -0,0 +1,20 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var rb = new RopeBuffer
+
+for i in [0 .. 1000000[ do
+       rb.add 'S'
+       var s = rb.to_s
+end