Index: EcnlProtoTool/trunk/asp3_dcre/tecsgen/tecslib/core/bnf.y.rb
===================================================================
--- EcnlProtoTool/trunk/asp3_dcre/tecsgen/tecslib/core/bnf.y.rb	(revision 321)
+++ EcnlProtoTool/trunk/asp3_dcre/tecsgen/tecslib/core/bnf.y.rb	(revision 429)
@@ -4,5 +4,5 @@
 #      Generator for TOPPERS Embedded Component System
 #  
-#   Copyright (C) 2008-2016 by TOPPERS Project
+#   Copyright (C) 2008-2018 by TOPPERS Project
 #--
 #   上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
@@ -378,5 +378,7 @@
         | STRUCT
 		{
-			result = StructType.new()
+			# tag が無い場合、内部名を与える
+			result = StructType.new( :"TAG__#{@@no_struct_tag_num}__" )
+			@@no_struct_tag_num += 1
 			StructType.set_define( true )
 		}
@@ -709,4 +711,5 @@
         : component_description specified_statement
         | component_description location_information
+        | component_description tool_info
         | 
 
@@ -738,5 +741,5 @@
         | import
         | import_C
-        | signature_plugin
+        | generate_statement
         | error   # エラー回復ポイント
 
@@ -797,8 +800,8 @@
 
 region_name_list
-        : IDENTIFIER
-		{	result = [val[0].val]		}
-        | region_name_list ',' IDENTIFIER
-		{	result << val[2].val		}
+        : namespace_identifier
+		{	result = [val[0]]		}
+        | region_name_list ',' namespace_identifier
+		{	result << val[2]		}
 
 const_statement
@@ -832,5 +835,5 @@
 		{ Import.new( val[2], true ) }
 
-signature_plugin
+generate_statement
 #        : GENERATE '(' plugin_name ',' namespace_identifier ',' STRING_LITERAL ')' ';'  #1ok signature plugin
         : GENERATE '(' plugin_name ',' namespace_identifier ',' plugin_arg ')' ';'  #1ok signature plugin
@@ -1301,4 +1304,9 @@
 			result = [ val[0] ]
 		}
+        | composite_celltype_statement_specifier_list ',' composite_celltype_statement_specifier
+		{
+			Generator.add_statement_specifier val[2]
+			result = val[0] << val[2]
+		}
 
 composite_celltype_statement_specifier
@@ -1350,4 +1358,5 @@
         | internal_join_list specified_join
         | internal_join_list external_join
+        | internal_join_list reverse_join
 
 external_join  # cell 内に記述する呼び口の外部結合
@@ -1499,4 +1508,25 @@
 
 
+#  JSON object
+tool_info        : TOOL_INFO '(' JSON_string ')' JSON_object { TOOL_INFO.new( val[2].to_sym, val[4] ) }
+JSON_object      : '{' JSON_property_list   '}'              {  result = val[1] }
+JSON_property_list : JSON_string ':' JSON_value              { result = { val[0].to_sym => val[2] } }
+                 | JSON_property_list ',' JSON_string ':' JSON_value
+                                                             { val[0][ val[2].to_sym ] = val[4] }
+JSON_value       : JSON_string | JSON_number | JSON_object | JSON_array
+                 | TRUE { result=val[0].val } | FALSE  { result=val[0].val } # JSON_NULL # null not suppoted
+JSON_array       : '[' JSON_array_list ']'                   { result = val[1]  }
+                 | '['  ']'                                  { result = []  }
+JSON_array_list  : JSON_value                                { result = [ val[0] ] }
+                 | JSON_array_list ',' JSON_value            { val[0] << val[2] }
+JSON_string      : STRING_LITERAL                            { result = val[0].val.gsub!( /\"(.*)\"/, "\\1" ) }
+JSON_number      : INTEGER_CONSTANT                          { result = val[0].val.to_i }
+                 | FLOATING_CONSTANT                         { result = val[0].val.to_f }
+                 | '-' INTEGER_CONSTANT                      { result = - val[0].val.to_i }
+                 | '-' FLOATING_CONSTANT                     { result = - val[0].val.to_f }
+                 | '+' INTEGER_CONSTANT                      { result = val[0].val.to_i }
+                 | '+' FLOATING_CONSTANT                     { result = val[0].val.to_f }
+
+
 end
 
@@ -1523,4 +1553,5 @@
     'import_C' => :IMPORT_C,
     'generate' => :GENERATE,
+    '__tool_info__' => :TOOL_INFO,
 
     # types
@@ -1658,4 +1689,7 @@
   # すべての構文解析が完了した
   @@b_end_all_parse = false
+
+  # tag なし struct
+  @@no_struct_tag_num = 0
 
   def self.parse( file_name, plugin = nil, b_reuse = false )
@@ -1773,5 +1807,5 @@
                   string += line
                   # この位置では error メソッドは使えない (token 読出し前)
-                  puts "error: #{file} line #{lineno}: string literal has newline without escape"
+                  puts "#{file}:#{lineno}:#{col}: error: string literal has newline without escape"
                   @@n_error += 1
                 end
@@ -1814,8 +1848,9 @@
                   b_in_string = true
                   # この位置では error メソッドは使えない (token 読出し前) # mikan cdl_error ではない
-                  puts "error: #{file} line #{lineno}: string literal has newline without escape"
+                  puts "#{file}:#{lineno}:#{col}: error: string literal has newline without escape"
                   @@n_error += 1
                 # 山括弧で囲まれた文字列
-                when /\A<[0-9A-Za-z_\. \/]+>/   # AB: angle bracke
+                # when /\A<[0-9A-Za-z_\. \/]+>/   # AB: angle bracke
+                when /\A<(?:[^>\\]|\\.)*>/   # これはうまく行くようだ
                   @q << [:AB_STRING_LITERAL, Token.new($&, file, lineno, col)]
                 # 行コメント
@@ -1913,4 +1948,5 @@
   @@n_error = 0
   @@n_warning = 0
+  @@n_info = 0
 
   # このメソッドは構文解析、意味解析からのみ呼出し可（コード生成でエラー発生は不適切）
@@ -1946,5 +1982,5 @@
       end
       if locale then
-        Console.puts "error: #{locale[0]}: line #{locale[1]} #{msg}"
+        Console.puts "#{locale[0]}:#{locale[1]}:#{locale[2]}: error: #{msg}"
       else
         Console.puts "error: #{msg}"
@@ -1979,5 +2015,5 @@
       end
       if locale then
-        Console.puts "warning: #{locale[0]}: line #{locale[1]} #{msg}"
+        Console.puts "#{locale[0]}:#{locale[1]}:#{locale[2]}: warning: #{msg}"
       else
         Console.puts "warning: #{msg}"
@@ -1986,4 +2022,37 @@
   end
 
+  # このメソッドは構文解析、意味解析からのみ呼出し可
+  def self.info( msg, *arg )
+    locale = nil
+    self.info2( locale, msg, *arg )
+  end
+
+  def self.info2( locale, msg, *arg )
+    @@n_info += 1
+
+    msg = TECSMsg.get_info_message( msg )
+    # $1, $2, ... を arg で置換
+    count = 1
+    arg.each{ |a|
+      str = TECSIO.str_code_convert( msg, a.to_s )
+      msg.sub!( /\$#{count}/, str )
+      count += 1
+    }
+
+    # import_C の中でのウォーニング？
+    if @@import_C then
+      C_parser.info( msg )
+    else
+      if @@b_end_all_parse == false || locale == nil then
+        locale = @@current_locale[ @@generator_nest ]
+      end
+      if locale then
+        Console.puts "#{locale[0]}:#{locale[1]}:#{locale[2]}: info: #{msg}"
+      else
+        Console.puts "info: #{msg}"
+      end
+    end
+  end
+
   def self.get_n_error
     @@n_error
@@ -1994,6 +2063,14 @@
   end
 
+  def self.get_n_info
+    @@n_info
+  end
+
   def self.get_nest
     @@generator_nest
+  end
+
+  def self.parsing_C?
+    @@import_C
   end
 
