Changeset 12697


Ignore:
Timestamp:
May 2, 2019 8:42:46 AM (7 months ago)
Author:
randersson
Message:

Reverted r12694 and r12695

Location:
trunk/Compiler/ModelicaFrontEnd
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Compiler/ModelicaFrontEnd/src/java/org/jmodelica/util/QualifiedName.java

    r12695 r12697  
    1616package org.jmodelica.util;
    1717
    18 import java.io.IOException;
    19 import java.io.StringReader;
    2018import java.util.ArrayList;
    21 import java.util.Iterator;
     19import java.util.regex.Matcher;
     20import java.util.regex.Pattern;
    2221
    23 import org.jmodelica.modelica.parser.ModelicaParser.Terminals;
    24 import org.jmodelica.modelica.parser.ModelicaScanner;
    2522import org.jmodelica.util.exceptions.NameFormatException;
    26 
    27 import beaver.Scanner.Exception;
    28 import beaver.Symbol;
    2923
    3024/**
     
    3226 */
    3327public class QualifiedName {
    34     private final boolean isGlobal;
    35     private final ArrayList<String> names = new ArrayList<>();
    36     private final boolean isUnQualifiedImport;
    37     private final Iterator<String> iterator;
     28    private boolean isGlobal;
     29    private int i = 0;
     30    ArrayList<String> names;
     31    private boolean isUnQualifiedImport;
    3832
    3933    public QualifiedName(String name) {
     34        if (name.length() == 0) {
     35            throw new NameFormatException("A name must have atleast one caracter");
     36        }
    4037        isUnQualifiedImport = name.endsWith(".*");
    4138        isGlobal = name.startsWith(".");
    42         splitQualifiedClassName(name);
    43         iterator = names.iterator();
     39        names = splitQualifiedClassName(name);
    4440    }
    4541
    46     // Interpret name as global or not regardless of dot form or not.
     42    // Interpret name as global or not regardless or dot form or not.
    4743    public QualifiedName(String name, boolean isGlobal) {
    48         isUnQualifiedImport = name.endsWith(".*");
    49         splitQualifiedClassName(name);
    50         this.isGlobal = isGlobal; // Note: must be set after splitting
    51         iterator = names.iterator();
     44        if (name.length() == 0) {
     45            throw new NameFormatException("A name must have atleast one caracter");
     46        }
     47        names = splitQualifiedClassName(name);
     48        this.isGlobal = isGlobal;
     49    }
     50
     51    public boolean hasNext() {
     52        return i < names.size();
    5253    }
    5354
     
    5556        return names.size();
    5657    }
    57    
    58     public boolean hasNext() {
    59         return iterator.hasNext();
    60     }
    61    
    62     public String next() {
    63         return iterator.next();
     58
     59    /**
     60     * Only parse if the name is not simple, don't store the actual parts.
     61     * Skips some work.
     62     * @return if the name has only a single part.
     63     */
     64    public static int numberOfParts(String name) {
     65        boolean isGlobal = name.startsWith(".");
     66        if (isGlobal) {
     67            name = name.substring(1, name.length());
     68        }
     69        Matcher m = p.matcher(name);
     70        ArrayList<Integer> nameSeparations = new ArrayList<Integer>();
     71        findNameSeparations(m, nameSeparations);
     72        return nameSeparations.size() + 1;
    6473    }
    6574
    66     /**
    67      * Checks if the name is a valid and simple (unqualified) identifier.
    68      * @param name The name.
    69      * @param allowGlobal If <code>true</code>, then takes 'global' notation with a leading dot into account by
    70      * ignoring such a character.
    71      * @return Whether or not <code>name</code> is a valid identifier.
    72      */
    73     public static boolean isValidSimpleIdentifier(String name, boolean allowGlobal) {
    74         if (allowGlobal && name.startsWith(".")) {
    75             name = name.substring(1, name.length());
    76         }
    77         ModelicaScanner ms = new ModelicaScanner(new StringReader(name));
    78         try {
    79            if (ms.nextToken().getId() != Terminals.ID)
    80                return false;
    81            if (ms.nextToken().getId() != Terminals.EOF)
    82                return false;
    83            return true;
    84         } catch (IOException e) {
    85             // This shouldn't happen when using a StringReader.
    86             throw new RuntimeException("Unhandled internal error", e);
    87         } catch (Exception e) {
    88             // Scanner cannot handle this, so this is not a valid identifier.
    89             return false;
    90         }
     75    public String next() {
     76        return names.get(i++);
     77    }
     78
     79    public ArrayList<String> getNames() {
     80        return names;
    9181    }
    9282
    9383    @Override
    9484    public String toString() {
    95         return (isGlobal ? "(global) " : "") + (isUnQualifiedImport ? ".* " : "") + names.toString();
     85        return names.toString();
    9686    }
    9787
     
    10090    }
    10191
     92    static final Pattern p = Pattern.compile("(?<![\\\\])['.]");
     93
     94    private static void checkNameLength(int start,int end) {
     95        if (end - start < 2)
     96            throw new NameFormatException("Names must have a length greater than zero");
     97    }
     98
     99    private static void findNameSeparations(Matcher m, ArrayList<Integer> list) {
     100        boolean inquoted = false;
     101        int prev = -1;
     102        while (m.find()) {
     103            String token = m.group();
     104            if (token.equals("'")) {
     105                if (inquoted) {
     106                    checkNameLength(prev, m.start());
     107                } else {
     108                    if (m.start() - prev > 2) {
     109                        throw new NameFormatException("Quotes not allowed inside unqouted name");
     110                    }
     111                }
     112                prev = inquoted ? prev : m.start();
     113                inquoted = !inquoted;
     114            } else if (!inquoted) {
     115                checkNameLength(prev, m.start());
     116                prev = m.start();
     117                list.add(m.start() + 1);
     118            }
     119        }
     120        if (inquoted) {
     121            throw new NameFormatException("Qualified Name couldn't be interpreted due to unmatched quotes");
     122        }
     123    }
     124
    102125    /**
    103      * Splits a composite class name into all its partial accesses
     126     * Splits a composite class name into all the partial access
     127     *
     128     * @param name
     129     * @return array with the names of all accessed classes.
    104130     */
    105     private final void splitQualifiedClassName(String name) {
    106         if (name.length() == 0) {
    107             throw new NameFormatException("A name must have at least one caracter");
    108         }
     131    private final ArrayList<String> splitQualifiedClassName(String name) {
    109132        if (isGlobal || isUnQualifiedImport) {
    110133            int start = isGlobal ? 1 : 0;
     
    112135            name = name.substring(start, end);
    113136        }
    114         ModelicaScanner ms = new ModelicaScanner(new StringReader(name));
    115         try {
    116             Symbol sym;
    117             do {
    118                 sym = ms.nextToken();
    119                 if (sym.getId() != Terminals.ID)
    120                     throw new NameFormatException("The qualified name is not valid");
    121                 names.add((String)sym.value);
    122             } while ((sym = ms.nextToken()).getId() == Terminals.DOT);
    123             if (sym.getId() != Terminals.EOF)
    124                 throw new NameFormatException("Invalid name: " + name);
    125         } catch (IOException e) {
    126             // This shouldn't happen when using a StringReader.
    127             throw new RuntimeException("Unhandled internal error", e);
    128         } catch (Exception e) {
    129             // Identifier not valid.
    130             throw new NameFormatException("Invalid name: " + name);
     137        Matcher m = p.matcher(name);
     138        ArrayList<Integer> nameSeparations = new ArrayList<Integer>();
     139        findNameSeparations(m, nameSeparations);
     140        nameSeparations.add(name.length() + 1);
     141        ArrayList<String> parts = new ArrayList<String>();
     142        int partEnd = 0;
     143        for (int namePart = 0; namePart < nameSeparations.size() ; namePart++) {
     144            parts.add(name.substring(partEnd, nameSeparations.get(namePart) - 1));
     145            partEnd = nameSeparations.get(namePart);
    131146        }
     147        return parts;
    132148    }
    133149}
  • trunk/Compiler/ModelicaFrontEnd/test/junit/org/jmodelica/test/common/QualifiedNameTest.java

    r12694 r12697  
    22
    33import static org.junit.Assert.assertEquals;
    4 import static org.junit.Assert.assertTrue;
    5 import static org.junit.Assert.assertFalse;
    64
    75import org.jmodelica.util.QualifiedName;
     
    1311    @Test
    1412    public void globalWithQuotedContainingExcapedDot() {
    15         assertEquals("(global) ['quotedWith.Dot\\'.', secondPart]",
     13        assertEquals("['quotedWith.Dot\\'.', secondPart]",
    1614                new QualifiedName(".'quotedWith.Dot\\'.'.secondPart").toString());
    1715    }
     
    1917    @Test
    2018    public void globalDotted()  {
    21         assertEquals("(global) [first, second, third]",
     19        assertEquals("[first, second, third]",
    2220                new QualifiedName(".first.second.third").toString());
    2321    }
     
    2523    @Test
    2624    public void global() {
    27         assertEquals("(global) [global]",
     25        assertEquals("[global]",
    2826                new QualifiedName(".global").toString());
    2927    }
     
    5452    @Test
    5553    public void countNumberOfParts() {
    56         assertEquals(4, new QualifiedName("A.'B'.C.D").numberOfParts());
     54        assertEquals(4, new QualifiedName(("A.'B'.C.D")).numberOfParts());
    5755    }
    5856
    5957    @Test
    6058    public void nonSimpleNameParts() {
    61         assertEquals(4, new QualifiedName(".A.'B'.C.D").numberOfParts());
     59        assertEquals(4, QualifiedName.numberOfParts(".A.'B'.C.D"));
    6260    }
    6361   
    6462    @Test
    6563    public void globalSimpleNameParts() {
    66         assertTrue(QualifiedName.isValidSimpleIdentifier(".'A'", true));
     64        assertEquals(1, QualifiedName.numberOfParts(".'A'"));
    6765    }
    68 
    69     @Test
    70     public void globalSimpleNamePartsNegative() {
    71         assertFalse(QualifiedName.isValidSimpleIdentifier(".'A'", false));
    72     }
    73 
     66   
    7467    @Test
    7568    public void nameFromUnqualifiedImport() {
    76         assertEquals(".* [A, B, C]", new QualifiedName("A.B.C.*").toString());
     69        assertEquals("[A, B, C]", new QualifiedName("A.B.C.*").toString());
    7770    }
    7871
Note: See TracChangeset for help on using the changeset viewer.