From 558b6d2ff1be15f93ff13ffcd9bcc0e7c40cae45 Mon Sep 17 00:00:00 2001
From: Johannes Mey <johannes.mey@tu-dresden.de>
Date: Thu, 7 May 2020 21:46:00 +0200
Subject: [PATCH] parse comments and whitespace (outside declarations)

---
 src/main/jastadd/RelAst.relast                |  9 ++++-
 src/main/jastadd/backend/AbstractGrammar.jadd | 40 +++++++++++++++----
 src/main/jastadd/parser/RelAst.parser         | 27 ++++++++++---
 src/main/jastadd/scanner/Header.flex          |  3 ++
 src/main/jastadd/scanner/Keywords.flex        |  6 ++-
 src/main/jastadd/scanner/Macros.flex          | 10 ++---
 src/main/jastadd/scanner/RulesPostamble.flex  | 11 +++--
 src/main/jastadd/scanner/RulesPreamble.flex   | 15 ++++++-
 src/main/jastadd/scanner/Symbols.flex         | 32 ++++++++-------
 9 files changed, 110 insertions(+), 43 deletions(-)

diff --git a/src/main/jastadd/RelAst.relast b/src/main/jastadd/RelAst.relast
index 2168413..01adb18 100644
--- a/src/main/jastadd/RelAst.relast
+++ b/src/main/jastadd/RelAst.relast
@@ -5,7 +5,8 @@ Program ::= GrammarFile *;
 abstract Grammar ::= Declaration*;
 GrammarFile : Grammar ::= <FileName> ;
 
-abstract Declaration;
+abstract Declaration ::= Comment*;
+EmptyDeclaration : Declaration;
 
 TypeDecl:Declaration ::= <Name> <Abstract:boolean>  Component*;
 
@@ -46,4 +47,8 @@ UnnamedRole : Role ;
 rel Role.Type <-> TypeDecl.Role*;
 
 // comments
-Comment : Declaration ::= <Text>;
+abstract Comment ::= <Text>;
+WhitespaceComment : Comment;
+SingleLineComment : Comment;
+MultiLineComment : Comment;
+DocComment : Comment;
diff --git a/src/main/jastadd/backend/AbstractGrammar.jadd b/src/main/jastadd/backend/AbstractGrammar.jadd
index 870132c..88c7421 100644
--- a/src/main/jastadd/backend/AbstractGrammar.jadd
+++ b/src/main/jastadd/backend/AbstractGrammar.jadd
@@ -29,10 +29,14 @@ aspect BackendAbstractGrammar {
     }
   }
 
-  abstract public void Declaration.generateAbstractGrammar(StringBuilder b);
+  public void Declaration.generateAbstractGrammar(StringBuilder b) {
+    for (Comment comment : getCommentList()) {
+      comment.generateAbstractGrammar(b);
+    }
+  }
 
-  public void Comment.generateAbstractGrammar(StringBuilder b) {
-    b.append(getText()).append("\n");
+  public void EmptyDeclaration.generateAbstractGrammar(StringBuilder b) {
+    super.generateAbstractGrammar(b);
   }
 
   public void TypeDecl.generateAbstractGrammar(StringBuilder b) {
@@ -48,7 +52,8 @@ aspect BackendAbstractGrammar {
       b.append(" ");
       component.generateAbstractGrammar(b);
     }
-    b.append(";\n");
+    b.append(";");
+    super.generateAbstractGrammar(b);
   }
 
   public abstract void Component.generateAbstractGrammar(StringBuilder b);
@@ -130,14 +135,17 @@ aspect BackendAbstractGrammar {
     b.append(">");
   }
 
-  abstract public void Relation.generateAbstractGrammar(StringBuilder b);
+  public void Relation.generateAbstractGrammar(StringBuilder b) {
+    super.generateAbstractGrammar(b);
+  }
 
   public void DirectedRelation.generateAbstractGrammar(StringBuilder b) {
     b.append("rel ");
     getSource().generateAbstractGrammar(b);
     b.append(" -> ");
     getTarget().generateAbstractGrammar(b);
-    b.append(";\n");
+    b.append(";");
+    super.generateAbstractGrammar(b);
   }
 
   public void BidirectionalRelation.generateAbstractGrammar(StringBuilder b) {
@@ -145,7 +153,8 @@ aspect BackendAbstractGrammar {
     getLeft().generateAbstractGrammar(b);
     b.append(" <-> ");
     getRight().generateAbstractGrammar(b);
-    b.append(";\n");
+    b.append(";");
+    super.generateAbstractGrammar(b);
   }
 
   abstract public void Role.generateAbstractGrammar(StringBuilder b);
@@ -166,5 +175,22 @@ aspect BackendAbstractGrammar {
     b.append(getType().getName());
   }
 
+  abstract public void Comment.generateAbstractGrammar(StringBuilder b);
+
+  public void WhitespaceComment.generateAbstractGrammar(StringBuilder b) {
+    b.append(getText());
+  }
+
+  public void SingleLineComment.generateAbstractGrammar(StringBuilder b) {
+    b.append("//").append(getText()).append("\n");
+  }
+
+  public void MultiLineComment.generateAbstractGrammar(StringBuilder b) {
+    b.append("/*").append(getText()).append("*/");
+  }
+
+  public void DocComment.generateAbstractGrammar(StringBuilder b) {
+    b.append("/**").append(getText()).append("*/");
+  }
 
 }
diff --git a/src/main/jastadd/parser/RelAst.parser b/src/main/jastadd/parser/RelAst.parser
index f94fbef..77eeb6c 100644
--- a/src/main/jastadd/parser/RelAst.parser
+++ b/src/main/jastadd/parser/RelAst.parser
@@ -1,16 +1,31 @@
 GrammarFile goal
-  = declaration.d goal.p     {: p.getDeclarationList().insertChild(d, 0); return p; :}
-  |                          {: return new GrammarFile(); :}
+  = comment_list.c       {: return new EmptyDeclaration(c); :}
+  | grammar_file
+;
+
+GrammarFile grammar_file
+  = declaration.d grammar_file.f {: f.getDeclarationList().insertChild(d, 0); return f; :}
+  |                              {: return new GrammarFile(); :}
 ;
 
 Declaration declaration
-  = type_decl
-  | relation
-  | comment
+  = type_decl.d comment_list.c {: d.setCommentList(c); return d; :}
+  | relation.r  comment_list.c {: r.setCommentList(c); return r; :}
+;
+
+// this method would be create by the JAstAddParser from a usage of
+// 'comment+' in a rule, but only for the standard list class 'List'.
+JastAddList comment_list
+  = comment.n {: return new JastAddList().add(n); :}
+  | comment_list.l comment.n {: return l.add(n); :}
 ;
 
 Comment comment
-  = COMMENT  {: return new Comment(COMMENT); :};
+  = WHITESPACE.c        {: return new WhitespaceComment(c); :}
+  | MULTILINECOMMENT.c  {: return new MultiLineComment(c.substring(2,c.length()-2));  :}
+  | DOCCOMMENT.c        {: return new DocComment(c.substring(3,c.length()-2));        :}
+  | SINGLELINECOMMENT.c {: return new SingleLineComment(c.substring(2)); :}
+;
 
 TypeDecl type_decl
   = ID components_opt.c SCOL
diff --git a/src/main/jastadd/scanner/Header.flex b/src/main/jastadd/scanner/Header.flex
index 7312065..c343dcd 100644
--- a/src/main/jastadd/scanner/Header.flex
+++ b/src/main/jastadd/scanner/Header.flex
@@ -13,5 +13,8 @@ import org.jastadd.relast.parser.RelAstParser.Terminals;
 %yylexthrow beaver.Scanner.Exception
 %scanerror RelAstScanner.ScannerError
 
+%x COMMENT
+%s DECLARATION
+
 %line
 %column
diff --git a/src/main/jastadd/scanner/Keywords.flex b/src/main/jastadd/scanner/Keywords.flex
index 76e6359..76397b9 100644
--- a/src/main/jastadd/scanner/Keywords.flex
+++ b/src/main/jastadd/scanner/Keywords.flex
@@ -1,2 +1,4 @@
-"abstract"   { return sym(Terminals.ABSTRACT); }
-"rel"        { return sym(Terminals.RELATION); }
+<YYINITIAL,DECLARATION> {
+  "abstract"            { yybegin(DECLARATION); return sym(Terminals.ABSTRACT); }
+  "rel"                 { yybegin(DECLARATION); return sym(Terminals.RELATION); }
+}
diff --git a/src/main/jastadd/scanner/Macros.flex b/src/main/jastadd/scanner/Macros.flex
index 167f51b..f67e926 100644
--- a/src/main/jastadd/scanner/Macros.flex
+++ b/src/main/jastadd/scanner/Macros.flex
@@ -1,5 +1,5 @@
-WhiteSpace = [ ] | \t | \f | \n | \r | \r\n
-ID = [a-zA-Z$_][a-zA-Z0-9$_]*
-TraditionalComment   = [/][*][^*]*[*]+([^*/][^*]*[*]+)*[/]
-EndOfLineComment = "//" [^\n\r]*
-Comment = {TraditionalComment} | {EndOfLineComment}
+WhiteSpace        = [ ] | \t | \f | \n | \r | \r\n
+ID                = [a-zA-Z$_][a-zA-Z0-9$_]*
+MultiLineComment  = [/][*][^*]+[*]+([^*/][^*]*[*]+)*[/]
+DocComment        = [/][*][*][^*]*[*]+([^*/][^*]*[*]+)*[/]
+SingleLineComment = [/][/] [^\n\r]* (\n | \r | \r\n)
diff --git a/src/main/jastadd/scanner/RulesPostamble.flex b/src/main/jastadd/scanner/RulesPostamble.flex
index 1ae39c6..5460a0b 100644
--- a/src/main/jastadd/scanner/RulesPostamble.flex
+++ b/src/main/jastadd/scanner/RulesPostamble.flex
@@ -1,4 +1,7 @@
-{ID}         { return sym(Terminals.ID); }
-<<EOF>>      { return sym(Terminals.EOF); }
-
-[^]            { throw new ScannerError((yyline+1) +"," + (yycolumn+1) + ": Illegal character <"+yytext()+">"); }
+<YYINITIAL,DECLARATION> {
+  {ID}                  { yybegin(DECLARATION); return sym(Terminals.ID); }
+  [^]                   { throw new ScannerError((yyline+1) +"," + (yycolumn+1) + ": Illegal character <"+yytext()+">"); }
+}
+<YYINITIAL,DECLARATION,COMMENT> {
+  <<EOF>>               { return sym(Terminals.EOF); }
+}
diff --git a/src/main/jastadd/scanner/RulesPreamble.flex b/src/main/jastadd/scanner/RulesPreamble.flex
index a55876d..63081de 100644
--- a/src/main/jastadd/scanner/RulesPreamble.flex
+++ b/src/main/jastadd/scanner/RulesPreamble.flex
@@ -1,5 +1,16 @@
 
 %%
 
-{WhiteSpace} { /* ignore */ }
-{Comment}    { return sym(Terminals.COMMENT); }
+<DECLARATION> {
+  {WhiteSpace}          { /* ignore */ }
+  {MultiLineComment}    { /* ignore */ }
+  {DocComment}          { /* ignore */ }
+  {SingleLineComment}   { /* ignore */ }
+}
+
+<YYINITIAL,COMMENT> {
+  {WhiteSpace}+         { yybegin(YYINITIAL); return sym(Terminals.WHITESPACE); }
+  {MultiLineComment}    { yybegin(YYINITIAL); return sym(Terminals.MULTILINECOMMENT); }
+  {DocComment}          { yybegin(YYINITIAL); return sym(Terminals.DOCCOMMENT); }
+  {SingleLineComment}   { yybegin(YYINITIAL); return sym(Terminals.SINGLELINECOMMENT); }
+}
diff --git a/src/main/jastadd/scanner/Symbols.flex b/src/main/jastadd/scanner/Symbols.flex
index 2990e99..7f05c11 100644
--- a/src/main/jastadd/scanner/Symbols.flex
+++ b/src/main/jastadd/scanner/Symbols.flex
@@ -1,15 +1,17 @@
-";"          { return sym(Terminals.SCOL); }
-":"          { return sym(Terminals.COL); }
-"::="        { return sym(Terminals.ASSIGN); }
-"*"          { return sym(Terminals.STAR); }
-"."          { return sym(Terminals.DOT); }
-","          { return sym(Terminals.COMMA); }
-"<"          { return sym(Terminals.LT); }
-">"          { return sym(Terminals.GT); }
-"["          { return sym(Terminals.LBRACKET); }
-"]"          { return sym(Terminals.RBRACKET); }
-"/"          { return sym(Terminals.SLASH); }
-"?"          { return sym(Terminals.QUESTION_MARK); }
-"->"         { return sym(Terminals.RIGHT); }
-"<-"         { return sym(Terminals.LEFT); }
-"<->"        { return sym(Terminals.BIDIRECTIONAL); }
+<YYINITIAL,DECLARATION> {
+  ";"                   { yybegin(COMMENT);     return sym(Terminals.SCOL); }
+  ":"                   { yybegin(DECLARATION); return sym(Terminals.COL); }
+  "::="                 { yybegin(DECLARATION); return sym(Terminals.ASSIGN); }
+  "*"                   { yybegin(DECLARATION); return sym(Terminals.STAR); }
+  "."                   { yybegin(DECLARATION); return sym(Terminals.DOT); }
+  ","                   { yybegin(DECLARATION); return sym(Terminals.COMMA); }
+  "<"                   { yybegin(DECLARATION); return sym(Terminals.LT); }
+  ">"                   { yybegin(DECLARATION); return sym(Terminals.GT); }
+  "["                   { yybegin(DECLARATION); return sym(Terminals.LBRACKET); }
+  "]"                   { yybegin(DECLARATION); return sym(Terminals.RBRACKET); }
+  "/"                   { yybegin(DECLARATION); return sym(Terminals.SLASH); }
+  "?"                   { yybegin(DECLARATION); return sym(Terminals.QUESTION_MARK); }
+  "->"                  { yybegin(DECLARATION); return sym(Terminals.RIGHT); }
+  "<-"                  { yybegin(DECLARATION); return sym(Terminals.LEFT); }
+  "<->"                 { yybegin(DECLARATION); return sym(Terminals.BIDIRECTIONAL); }
+}
-- 
GitLab