Search in sources :

Example 6 with OutputModelObject

use of us.parr.bookish.model.OutputModelObject in project bookish by parrt.

the class Tool method translateString.

public String translateString(Translator trans, String markdown, String startRule) throws Exception {
    CharStream input = CharStreams.fromString(markdown);
    BookishLexer lexer = new BookishLexer(input);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    BookishParser parser = new BookishParser(tokens, null, 0);
    Method startMethod = BookishParser.class.getMethod(startRule, (Class[]) null);
    ParseTree doctree = (ParseTree) startMethod.invoke(parser, (Object[]) null);
    // get single chapter
    OutputModelObject omo = trans.visit(doctree);
    ModelConverter converter = new ModelConverter(trans.templates);
    ST outputST = converter.walk(omo);
    return outputST.render();
}
Also used : BookishLexer(us.parr.bookish.parse.BookishLexer) CommonTokenStream(org.antlr.v4.runtime.CommonTokenStream) ST(org.stringtemplate.v4.ST) OutputModelObject(us.parr.bookish.model.OutputModelObject) Method(java.lang.reflect.Method) CharStream(org.antlr.v4.runtime.CharStream) ParseTree(org.antlr.v4.runtime.tree.ParseTree) ModelConverter(us.parr.bookish.translate.ModelConverter) BookishParser(us.parr.bookish.parse.BookishParser)

Example 7 with OutputModelObject

use of us.parr.bookish.model.OutputModelObject in project bookish by parrt.

the class ModelConverter method walk.

public ST walk(OutputModelObject omo) {
    if (omo == null)
        return null;
    // CREATE TEMPLATE FOR THIS OUTPUT OBJECT
    Class<? extends OutputModelObject> cl = omo.getClass();
    String templateName = cl.getSimpleName();
    if (templateName == null) {
        System.err.println("no model to template mapping for " + cl.getSimpleName());
        return new ST("[" + templateName + " invalid]");
    }
    ST st = templates.getInstanceOf(templateName);
    if (st == null) {
        System.err.println("no model to template mapping for " + cl.getSimpleName());
        return new ST("[" + templateName + " invalid]");
    }
    if (st.impl.formalArguments == null) {
        System.err.println("no formal arguments for " + templateName);
        return st;
    }
    // LinkedHashMap
    Map<String, FormalArgument> formalArgs = st.impl.formalArguments;
    // PASS IN OUTPUT MODEL OBJECT TO TEMPLATE AS FIRST ARG
    Set<String> argNames = formalArgs.keySet();
    Iterator<String> arg_it = argNames.iterator();
    // ordered so this is first arg
    String modelArgName = arg_it.next();
    st.add(modelArgName, omo);
    Field[] allAnnotatedFields = getAllAnnotatedFields(cl);
    List<Field> modelFields = new ArrayList<>();
    for (Field fi : allAnnotatedFields) {
        ModelElement annotation = fi.getAnnotation(ModelElement.class);
        if (annotation != null) {
            modelFields.add(fi);
        }
    }
    // Make sure all @ModelElement fields are public (ST won't see otherwise)
    for (Field fi : allAnnotatedFields) {
        ModelElement annotation = fi.getAnnotation(ModelElement.class);
        if (annotation != null && !Modifier.isPublic(fi.getModifiers())) {
            System.err.println("non-public @ModelElement in " + templateName + ": " + fi.getName());
        }
    }
    // Ensure that @ModelElement fields match up with the parameters
    {
        List<String> fieldNames = map(modelFields, Field::getName);
        Set<String> t = new HashSet<>(argNames);
        t.remove(modelArgName);
        if (!t.equals(new HashSet<>(fieldNames))) {
            System.err.println("mismatch in template " + templateName + " between arguments and @ModelElement fields: " + t + "!=" + fieldNames);
        }
    }
    // COMPUTE STs FOR EACH NESTED MODEL OBJECT MARKED WITH @ModelElement AND MAKE ST ATTRIBUTE
    Set<String> usedFieldNames = new HashSet<>();
    for (Field fi : modelFields) {
        ModelElement annotation = fi.getAnnotation(ModelElement.class);
        if (annotation == null) {
            continue;
        }
        String fieldName = fi.getName();
        if (!usedFieldNames.add(fieldName)) {
            System.err.println("Model object " + omo.getClass().getSimpleName() + " has multiple fields named '" + fieldName + "'");
            continue;
        }
        // Just don't set @ModelElement fields w/o formal arg in target ST
        if (formalArgs.get(fieldName) == null)
            continue;
        try {
            Object o = fi.get(omo);
            if (o instanceof OutputModelObject) {
                // SINGLE MODEL OBJECT?
                OutputModelObject nestedOmo = (OutputModelObject) o;
                ST nestedST = walk(nestedOmo);
                // System.out.println("set ModelElement "+fieldName+"="+nestedST+" in "+templateName);
                st.add(fieldName, nestedST);
            } else if (o instanceof Collection || o instanceof OutputModelObject[]) {
                // LIST OF MODEL OBJECTS?
                if (o instanceof OutputModelObject[]) {
                    o = Arrays.asList((OutputModelObject[]) o);
                }
                Collection<?> nestedOmos = (Collection<?>) o;
                for (Object nestedOmo : nestedOmos) {
                    if (nestedOmo == null)
                        continue;
                    ST nestedST = walk((OutputModelObject) nestedOmo);
                    // System.out.println("set ModelElement "+fieldName+"="+nestedST+" in "+templateName);
                    st.add(fieldName, nestedST);
                }
            } else if (o instanceof Map) {
                Map<?, ?> nestedOmoMap = (Map<?, ?>) o;
                Map<Object, ST> m = new LinkedHashMap<Object, ST>();
                for (Map.Entry<?, ?> entry : nestedOmoMap.entrySet()) {
                    ST nestedST = walk((OutputModelObject) entry.getValue());
                    // System.out.println("set ModelElement "+fieldName+"="+nestedST+" in "+templateName);
                    m.put(entry.getKey(), nestedST);
                }
                st.add(fieldName, m);
            } else if (o != null) {
                System.err.println("type of " + fieldName + "'s model element isn't recognized: " + o.getClass().getSimpleName());
            }
        } catch (IllegalAccessException iae) {
            System.err.printf("code generation template <%s> has missing, misnamed, or incomplete arg list; missing <%s>\n", templateName, fieldName);
        }
    }
    // st.impl.dump();
    return st;
}
Also used : OutputModelObject(us.parr.bookish.model.OutputModelObject) Set(java.util.Set) HashSet(java.util.HashSet) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) FormalArgument(org.stringtemplate.v4.compiler.FormalArgument) Field(java.lang.reflect.Field) ModelElement(us.parr.bookish.model.ModelElement) ArrayList(java.util.ArrayList) List(java.util.List) HashSet(java.util.HashSet) ST(org.stringtemplate.v4.ST) Collection(java.util.Collection) OutputModelObject(us.parr.bookish.model.OutputModelObject) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Aggregations

OutputModelObject (us.parr.bookish.model.OutputModelObject)7 ArrayList (java.util.ArrayList)6 ParseTree (org.antlr.v4.runtime.tree.ParseTree)6 Paragraph (us.parr.bookish.model.Paragraph)3 ST (org.stringtemplate.v4.ST)2 Join (us.parr.bookish.model.Join)2 PreAbstract (us.parr.bookish.model.PreAbstract)2 EntityDef (us.parr.bookish.model.entity.EntityDef)2 BookishParser (us.parr.bookish.parse.BookishParser)2 Field (java.lang.reflect.Field)1 Method (java.lang.reflect.Method)1 Collection (java.util.Collection)1 HashSet (java.util.HashSet)1 LinkedHashMap (java.util.LinkedHashMap)1 List (java.util.List)1 Map (java.util.Map)1 Set (java.util.Set)1 CharStream (org.antlr.v4.runtime.CharStream)1 CommonTokenStream (org.antlr.v4.runtime.CommonTokenStream)1 FormalArgument (org.stringtemplate.v4.compiler.FormalArgument)1