rascal

Writing Semantic Checks with TypePal


I am trying to write semantic checks for my for my model using TypePal. Here is my model

Property(b => b.name)
      .ColumnOrder(3)
      .ColumnName("Name")
      .ColumnType(varchar(45))
      .ColumnType(date)
;

syntax Property
  = property: "Property" "(" Expr e ")" PropertyType*
;

syntax PropertyType
  = columnName: "." "ColumnName" "(" Expr e ")"
  | columnOrder: "." "ColumnOrder" "(" Expr e ")"
  | columnType: "." "ColumnType" "(" ColumnType c ")"
;

syntax ColumnType
  = intColumn: "int" 
  | varcharColumn: "varchar" "(" Expr e ")"
  | dateColumn: "date" 
;

How do I write a rule with TypePal that enforces the requirement that a given PropertyType can not be repeated. I want each PropertyType to be used at most once. In the example above ColumnType was used twice I want this flagged as a semantic error.


Solution

  • here is what I came up with.

     map[str, int] m = ();
    
        for (PropertyType pt <- p){
            switch(pt){
                case (PropertyType) `. ColumnType ( <ColumnType _>)` : {
                  if ("ColumnType" notin m){
                     m = m + ("ColumnType" : 1);
                  }
                  else{
                   c.report(error(p, "Duplicate occurrence of %v", "ColumnType"));
                  }
                }
                case (PropertyType) `. ColumnName ( <Expr _>)` : {
                   if ("ColumnName" notin m){
                     m = m + ("ColumnName" : 1);
                   }
                   else{
                     c.report(error(p, "Duplicate occurrence of %v", "ColumnName"));
                  }
                }
                default : {
                  if ("ColumnOrder" notin m){
                    m = m + ("ColumnOrder" : 1);
                  }
                  else{
                    c.report(error(p, "Duplicate occurrence of %v", "ColumnOrder"));
                  }
                }
            }
        }