Don't include . in IDENTIFIER characters

We want to parse qualified names deliberately, not everywhere we need a
name.

Change-Id: Id20fc7e6fd8d3e4b54a5048bb54c6dccc4128f40
Test: Full Android Build
Bug: 24913789
Signed-off-by: Casey Dahlin <sadmac@google.com>
diff --git a/aidl_language.cpp b/aidl_language.cpp
index 94aa38b..0eaf0c9 100644
--- a/aidl_language.cpp
+++ b/aidl_language.cpp
@@ -110,6 +110,12 @@
   yylex_init(&scanner_);
 }
 
+AidlParcelable::AidlParcelable(AidlQualifiedName* name, unsigned line,
+                               const std::string& package)
+    : AidlParcelable(name->GetDotName(), line, package) {
+  delete name;
+}
+
 AidlParcelable::AidlParcelable(const std::string& name, unsigned line,
                                const std::string& package)
     : name_(name),
@@ -132,6 +138,16 @@
   delete methods;
 }
 
+AidlQualifiedName::AidlQualifiedName(std::string term,
+                                     std::string comments)
+    : terms_({term}),
+      comments_(comments) {
+}
+
+void AidlQualifiedName::AddTerm(std::string term) {
+  terms_.push_back(term);
+}
+
 AidlImport::AidlImport(const std::string& from,
                        const std::string& needed_class, unsigned line)
     : from_(from),
@@ -185,35 +201,8 @@
   error_ = 1;
 }
 
-void Parser::AddImport(std::vector<std::string>* terms, unsigned line) {
-  std::string data;
-  bool first = true;
-
-  /* NOTE: This string building code is duplicated from below. We haven't
-   * factored it out into a function because it's hoped that when import_info
-   * becomes a class we won't need this anymore.
-   **/
-  for (const auto& term : *terms) {
-      if (first)
-          data = term;
-      else
-          data += '.' + term;
-  }
-
-  imports_.emplace_back(new AidlImport(this->FileName(), data, line));
-
-  delete terms;
-}
-
-void Parser::SetPackage(std::vector<std::string> *terms) {
-    bool first = true;
-
-    for (const auto& term : *terms) {
-        if (first)
-            package_ = term;
-        else
-            package_ += '.' + term;
-    }
-
-    delete terms;
+void Parser::AddImport(AidlQualifiedName* name, unsigned line) {
+  imports_.emplace_back(new AidlImport(this->FileName(),
+                                       name->GetDotName(), line));
+  delete name;
 }
diff --git a/aidl_language.h b/aidl_language.h
index c42224b..1be49e6 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -6,6 +6,7 @@
 #include <vector>
 
 #include <base/macros.h>
+#include <base/strings.h>
 
 #include <io_delegate.h>
 
@@ -161,10 +162,30 @@
   DISALLOW_COPY_AND_ASSIGN(AidlDocumentItem);
 };
 
+class AidlQualifiedName : public AidlNode {
+ public:
+  AidlQualifiedName(std::string term, std::string comments);
+  virtual ~AidlQualifiedName() = default;
+
+  const std::vector<std::string>& GetTerms() const { return terms_; }
+  const std::string& GetComments() const { return comments_; }
+  std::string GetDotName() const { return android::base::Join(terms_, '.'); }
+
+  void AddTerm(std::string term);
+
+ private:
+  std::vector<std::string> terms_;
+  std::string comments_;
+
+  DISALLOW_COPY_AND_ASSIGN(AidlQualifiedName);
+};
+
 class AidlParcelable : public AidlDocumentItem {
  public:
   AidlParcelable(const std::string& name, unsigned line,
                  const std::string& package);
+  AidlParcelable(AidlQualifiedName* name, unsigned line,
+                 const std::string& package);
   virtual ~AidlParcelable() = default;
 
   const std::string& GetName() const { return name_; }
@@ -208,9 +229,6 @@
   DISALLOW_COPY_AND_ASSIGN(AidlInterface);
 };
 
-
-void init_buffer_type(buffer_type* buf, int lineno);
-
 class AidlImport : public AidlNode {
  public:
   AidlImport(const std::string& from, const std::string& needed_class,
@@ -250,8 +268,11 @@
 
   void SetDocument(AidlDocumentItem* items) { document_ = items; };
 
-  void AddImport(std::vector<std::string>* terms, unsigned line);
-  void SetPackage(std::vector<std::string>* terms);
+  void AddImport(AidlQualifiedName* name, unsigned line);
+  void SetPackage(AidlQualifiedName* name) {
+    package_ = name->GetDotName();
+    delete name;
+  }
 
   AidlDocumentItem* GetDocument() const { return document_; }
   const std::vector<std::unique_ptr<AidlImport>>& GetImports() { return imports_; }
diff --git a/aidl_language_l.l b/aidl_language_l.l
index cd349ec..e22e1a2 100644
--- a/aidl_language_l.l
+++ b/aidl_language_l.l
@@ -35,7 +35,7 @@
 
 %x COPYING LONG_COMMENT
 
-identifier  [_a-zA-Z][_a-zA-Z0-9\.]*
+identifier  [_a-zA-Z][_a-zA-Z0-9]*
 whitespace  ([ \t\r]+)
 idvalue     (0|[1-9][0-9]*)
 
diff --git a/aidl_language_y.y b/aidl_language_y.y
index ad2111d..0202f20 100644
--- a/aidl_language_y.y
+++ b/aidl_language_y.y
@@ -29,7 +29,7 @@
     std::vector<std::unique_ptr<AidlArgument>>* arg_list;
     AidlMethod* method;
     std::vector<std::unique_ptr<AidlMethod>>* methods;
-    std::vector<std::string>* strvec;
+    AidlQualifiedName* qname;
     AidlInterface* interface_obj;
     AidlParcelable* user_data;
 }
@@ -37,7 +37,7 @@
 %token<buffer> IDENTIFIER IDVALUE INTERFACE ONEWAY
 
 %token '(' ')' ',' '=' '[' ']' '<' '>' '.' '{' '}' ';'
-%token IN OUT INOUT PACKAGE IMPORT PARCELABLE 
+%token IN OUT INOUT PACKAGE IMPORT PARCELABLE
 
 %type<user_data> parcelable_decl parcelable_decls
 %type<methods> methods
@@ -48,7 +48,7 @@
 %type<arg> arg
 %type<direction> direction
 %type<str> generic_list
-%type<strvec> package_name
+%type<qname> qualified_name
 
 %type<buffer> error
 %%
@@ -60,7 +60,7 @@
 
 package
  : {}
- | PACKAGE package_name ';'
+ | PACKAGE qualified_name ';'
   { ps->SetPackage($2); };
 
 imports
@@ -68,16 +68,18 @@
  | import imports {};
 
 import
- : IMPORT package_name ';'
+ : IMPORT qualified_name ';'
   { ps->AddImport($2, @1.begin.line); };
 
-package_name
+qualified_name
  : IDENTIFIER {
-    $$ = new std::vector<std::string>();
-    $$->push_back($1.data);
+    $$ = new AidlQualifiedName($1.data,
+                               android::aidl::gather_comments($1.extra));
   }
- | package_name '.' IDENTIFIER
-  { $$->push_back($3.data); };
+ | qualified_name '.' IDENTIFIER
+  { $$ = $1;
+    $$->AddTerm($3.data);
+  };
 
 parcelable_decls
  :
@@ -98,8 +100,8 @@
   };
 
 parcelable_decl
- : PARCELABLE IDENTIFIER ';' {
-    $$ = new AidlParcelable($2.data, @2.begin.line, ps->Package());
+ : PARCELABLE qualified_name ';' {
+    $$ = new AidlParcelable($2, @2.begin.line, ps->Package());
   }
  | PARCELABLE ';' {
     fprintf(stderr, "%s:%d syntax error in parcelable declaration. Expected type name.\n",
@@ -187,27 +189,32 @@
   { $$ = new AidlArgument($1, $2.data, @2.begin.line); };
 
 type
- : IDENTIFIER {
-    $$ = new AidlType($1.data, @1.begin.line,
-                      android::aidl::gather_comments($1.extra), false);
+ : qualified_name {
+    $$ = new AidlType($1->GetDotName(), @1.begin.line, $1->GetComments(),
+                      false);
+    delete $1;
   }
- | IDENTIFIER '[' ']' {
-    $$ = new AidlType($1.data,
-                      @1.begin.line, android::aidl::gather_comments($1.extra),
+ | qualified_name '[' ']' {
+    $$ = new AidlType($1->GetDotName(), @1.begin.line, $1->GetComments(),
                       true);
+    delete $1;
   }
- | IDENTIFIER '<' generic_list '>' {
-    $$ = new AidlType(std::string($1.data) + "<" + *$3 + ">", @1.begin.line,
-                      android::aidl::gather_comments($1.extra), false);
+ | qualified_name '<' generic_list '>' {
+    $$ = new AidlType($1->GetDotName() + "<" + *$3 + ">", @1.begin.line,
+                      $1->GetComments(), false);
+    delete $1;
     delete $3;
   };
 
 generic_list
- : IDENTIFIER
-  { $$ = new std::string($1.data); }
- | generic_list ',' IDENTIFIER {
-    $$ = new std::string(*$1 + "," + std::string($3.data));
+ : qualified_name {
+    $$ = new std::string($1->GetDotName());
     delete $1;
+  }
+ | generic_list ',' qualified_name {
+    $$ = new std::string(*$1 + "," + $3->GetDotName());
+    delete $1;
+    delete $3;
   };
 
 direction
@@ -223,7 +230,7 @@
 #include <ctype.h>
 #include <stdio.h>
 
-void yy::parser::error(const yy::parser::location_type& l, const std::string& errstr)
-{
+void yy::parser::error(const yy::parser::location_type& l,
+                       const std::string& errstr) {
   ps->ReportError(errstr);
 }