Commit ca14743b authored by Niklas Fors's avatar Niklas Fors
Browse files

Inital commit (parsing working)

parents
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/generated">
<attributes>
<attribute name="ignore_optional_problems" value="true"/>
</attributes>
</classpathentry>
<classpathentry including="**" kind="src" path="src/resource"/>
<classpathentry kind="src" path="src/java"/>
<classpathentry kind="lib" path="tools/beaver.jar"/>
<classpathentry kind="lib" path="tools/junit-4.11-SNAPSHOT.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>
.DS_Store
.class
.vimrc
.*.swp
*.relast
/.settings
/bin/
/ant-bin/
/compiler.jar
/src/generated/
/.gradle
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>rel-rag</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
<project name="RelAstCompiler" default="build" basedir=".">
<property name="srcdir" value="${basedir}/src" />
<property name="resourcedir" value="${srcdir}/resource" />
<property name="gendir" value="${srcdir}/generated" />
<property name="bindir" value="${basedir}/ant-bin" />
<property name="docdir" value="${basedir}/doc" />
<property name="tools" value="${basedir}/tools"/>
<property name="test-reports.dir" location="report-tests"/>
<property name="jarfile" value="compiler.jar" />
<property name="junitjar" value="${tools}/junit-4.11-SNAPSHOT.jar" />
<!-- "package" is the directory where generated files will be stored -->
<property name="package" value="org.jastadd.relast.ast"/>
<loadresource property="package.path">
<propertyresource name="package"/>
<filterchain>
<tokenfilter>
<filetokenizer/>
<replacestring from="." to="/"/>
</tokenfilter>
</filterchain>
</loadresource>
<!-- Define Ant tasks -->
<taskdef name="jastadd" classname="org.jastadd.JastAddTask" classpath="${tools}/jastadd2.jar"/>
<taskdef name="jflex" classname="jflex.anttask.JFlexTask" classpath="${tools}/JFlex.jar"/>
<taskdef name="beaver" classname="beaver.comp.run.AntTask" classpath="${tools}/beaver.jar"/>
<!-- compile sources -->
<target name="build" depends="gen">
<mkdir dir="${bindir}" />
<javac
debug="true"
nowarn="true"
srcdir="${basedir}"
destdir="${bindir}"
includes="src/**/*.java"
classpath=".:${tools}/beaver-rt.jar:${junitjar}"
fork="true"
includeAntRuntime="false"
memoryMaximumSize="128M"
target="8"
source="8"
/>
<copy todir="${bindir}/">
<fileset dir="${resourcedir}"/>
</copy>
</target>
<!-- generate compiler source files -->
<target name="gen" depends="scanner,parser">
<!-- create AST node types and weave aspect modules -->
<echo message = "Running JastAdd"/>
<jastadd package="${package}" rewrite="cnta" safeLazy="true" beaver="true" visitcheck="false"
lazyMaps="true" outdir="${gendir}" cache="all" lineColumnNumbers="true">
<fileset dir=".">
<include name="spec/jastadd/*.ast"/>
<include name="spec/jastadd/*.jadd"/>
<include name="spec/jastadd/*.jrag"/>
</fileset>
</jastadd>
</target>
<target name="scanner">
<jflex file="spec/scanner/RelAst.flex" outdir="${gendir}/${package.path}" InputStreamCtor="false" nobak="yes"/>
</target>
<target name="parser" depends="scanner">
<concat destfile="${gendir}/${package.path}/RelAstParser.all" binary="true" force="false">
<!-- we use filelist because the order is important -->
<filelist dir="spec/parser/">
<file name="Preamble.parser"/>
<file name="RelAstBase.parser"/>
</filelist>
</concat>
<!-- generate the parser phase 1, translating .parser to .beaver -->
<java classpath="${tools}/JastAddParser.jar:${tools}/beaver-rt.jar" classname="Main" fork="true">
<arg value="--no-beaver-symbol" />
<arg value="${gendir}/${package.path}/RelAstParser.all" />
<arg value="${gendir}/${package.path}/RelAstParser.beaver" />
</java>
<!-- generate the parser phase 2, translating .beaver to .java -->
<beaver file="${gendir}/${package.path}/RelAstParser.beaver" terminalNames="yes" compress="no" useSwitch="yes"/>
</target>
<!-- remove generated source files and .class files -->
<target name="clean">
<delete dir="${gendir}" />
<mkdir dir="${gendir}" />
<delete dir="${bindir}" />
<delete file="${jarfile}" />
<delete>
<fileset dir="." includes="**/*.class" excludes="bin/" />
<fileset dir="testfiles/code_generation/" includes="*.c *.executable *.out"/>
</delete>
</target>
<target name="test" depends="build">
<mkdir dir="${test-reports.dir}"/>
<junit>
<classpath>
<pathelement path="${bindir}:${junitjar}:${tools}/beaver-rt.jar" />
</classpath>
<formatter type="brief" usefile="false" />
<batchtest todir="${test-reports.dir}">
<fileset dir="src/java">
<include name="org/jastadd/relast/tests/*.java" />
<include name="org/jastadd/relast/tests/codegen/*.java" />
</fileset>
</batchtest>
<formatter type="xml" />
</junit>
</target>
<target name="jar" depends="build">
<jar destfile="${jarfile}">
<fileset dir="${bindir}" includes="**/*.class,resource/" excludes="org/jastadd/relast/tests/*" />
<fileset dir="${srcdir}/java" includes="**/*.java" excludes="org/jastadd/relast/tests/*" />
<fileset dir="${resourcedir}" includes="**" />
<fileset dir="${gendir}" includes="**/*.java" />
<zipfileset includes="**/*.class" src="${tools}/beaver-rt.jar"/>
<manifest>
<attribute name="Main-Class" value="org.jastadd.relast.compiler.Compiler" />
</manifest>
</jar>
</target>
<target name="doc" depends="build" description="generate documentation">
<mkdir dir="${docdir}"/>
<javadoc
classpath="${gendir}:${tools}/beaver.jar"
destdir="${docdir}"
docletpath="${tools}/RagDoll.jar"
doclet="ragdoll.RagDollDoclet"
sourcepath="${gendir}">
<arg value="-linksource"/>
<arg value="-ragroot"/>
<arg value="."/>
</javadoc>
</target>
<!-- Run DrAST. Clone and build DrAST if it's not there -->
<target name="drast" depends="drast-init" >
<java jar="drast/DrAST-1.2.0.jar" fork="true" spawn="true" />
</target>
<target name="drast-init" depends="drast-check" unless="drast.exists" >
<exec executable="git">
<arg value="clone"/>
<arg value="git@bitbucket.org:jastadd/drast.git"/>
</exec>
<exec dir="drast" executable="./gradlew" />
</target>
<target name="drast-check">
<condition property="drast.exists">
<available file="drast" type="dir" />
</condition>
</target>
<target name="drast-update">
<delete dir="drast" />
<antcall target="drast-init" />
</target>
</project>
import java.util.*;
aspect Analysis {
}
\ No newline at end of file
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
// We have been careful to not import many types here because the imports are added for
// _ALL_ AST nodes and can cause collisions in the abstract grammar namespace.
aspect DumpTree {
private static final String ASTNode.DUMP_TREE_INDENT = " ";
public String ASTNode.dumpTree() {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
dumpTree(new PrintStream(bytes));
return bytes.toString();
}
public void ASTNode.dumpTree(PrintStream out) {
dumpTree(out, "");
out.flush();
}
public void ASTNode.dumpTree(PrintStream out, String indent) {
out.print(indent + getClass().getSimpleName());
out.println(getTokens());
String childIndent = indent + DUMP_TREE_INDENT;
for (ASTNode child : astChildren()) {
if (child == null) {
out.println(childIndent + "null");
} else {
child.dumpTree(out, childIndent);
}
}
}
public String ASTNode.getTokens() {
java.util.TreeSet<java.lang.reflect.Method> methods = new java.util.TreeSet<>(
new java.util.Comparator<java.lang.reflect.Method>() {
public int compare(java.lang.reflect.Method m1, java.lang.reflect.Method m2) {
return m1.getName().compareTo(m2.getName());
}
});
methods.addAll(java.util.Arrays.asList(getClass().getMethods()));
String result = "";
for (java.lang.reflect.Method method : methods) {
ASTNodeAnnotation.Token token = method.getAnnotation(ASTNodeAnnotation.Token.class);
if (token != null) {
try {
result += String.format(" %s=\"%s\"", token.name(), method.invoke(this));
} catch (IllegalAccessException ignored) {
} catch (InvocationTargetException ignored) {
}
}
}
return result;
}
}
\ No newline at end of file
import java.util.Set;
import java.util.TreeSet;
import java.util.LinkedList;
aspect Errors {
// coll Set<ErrorMessage> Program.errors()
// [new TreeSet<ErrorMessage>()]
// root Program;
}
aspect HelpAttributes {
// inh Program ASTNode.program();
// eq Program.getChild().program() = this;
}
aspect ErrorMessage {
public class ErrorMessage implements Comparable<ErrorMessage> {
private final ASTNode node;
private final int line;
private final int col;
private final String message;
public ErrorMessage(ASTNode node, String message) {
this.node = node;
this.line = node.getStartLine();
this.col = node.getStartColumn();
this.message = message;
}
public ASTNode getNode() {
return node;
}
public int getLine() {
return line;
}
public int getCol() {
return col;
}
public String getMessage() {
return message;
}
public String toString() {
return "Line " + line + ", column " + col + ": " + message;
}
@Override
public int compareTo(ErrorMessage err) {
int n = line - err.line;
if (n != 0) {
return n;
}
n = col-err.col;
if (n != 0) {
return n;
}
return message.compareTo(err.message);
}
}
protected ErrorMessage ASTNode.error(String message) {
return new ErrorMessage(this, message);
}
}
\ No newline at end of file
Program ::= TypeDecl* Relation*;
TypeDecl ::= <ID> <Abstract:boolean> [Super:TypeUse] Component*;
abstract Component ::= <ID> TypeUse;
NormalComponent : Component;
ListComponent : Component;
TokenComponent : Component;
OptComponent : Component;
TypeUse ::= <ID>;
Relation ::= Left:RelationSide Direction Right:RelationSide;
abstract RelationSide ::= TypeUse <ID>;
OneRelationSide : RelationSide;
OptionalRelationSide : RelationSide;
ManyRelationSide : RelationSide;
abstract Direction;
RightDirection : Direction;
Bidirectional : Direction;
\ No newline at end of file
%header {:
package org.jastadd.relast.ast;
:};
%goal goal;
\ No newline at end of file
Program goal =
type_decls.t relations.r {: return new Program(t, r); :}
| STRING_LITERAL STAR {: return new Program(); :}
;
List type_decls =
/* empty */ {: return new List(); :}
| type_decls.l type_decl.d {: return l.add(d); :}
;
TypeDecl type_decl =
ID type_decl_super.s components_opt.c SCOL
{: return new TypeDecl(ID, false, s, c); :}
| ABSTRACT ID type_decl_super.s components_opt.c SCOL
{: return new TypeDecl(ID, true, s, c); :}
;
Opt type_decl_super =
/* empty */ {: return new Opt(); :}
| COL type_use.u {: return new Opt(u); :}
;
TypeUse type_use =
ID {: return new TypeUse(ID); :}
;
List components_opt =
/* empty */ {: return new List(); :}
| ASSIGN components.l {: return l; :}
;
List components =
{: return new List(); :}
| components.l component.c {: return l.add(c); :}
;
Component component =
ID COL type_use.u {: return new NormalComponent(ID, u); :}
| type_use.u {: return new NormalComponent(u.getID(), u); :}
// List
| ID COL type_use.u STAR {: return new ListComponent(ID, u); :}
| type_use.u STAR {: return new ListComponent(u.getID(), u); :}
// Opt
| LBRACKET ID COL type_use.u RBRACKET {: return new OptComponent(ID, u); :}
| LBRACKET type_use.u RBRACKET {: return new OptComponent(u.getID(), u); :}
// Token
| LT ID COL type_use.u GT {: return new TokenComponent(ID, u); :}
| LT ID GT {: return new TokenComponent(ID, new TypeUse("String")); :}
;
List relations =
/* empty */ {: return new List(); :}
| relations.l relation.r {: return l.add(r); :}
;
Relation relation =
RELATION relation_side.l direction relation_side.r SCOL
{: return new Relation(l, direction, r); :}
;
RelationSide relation_side =
// One
type_use.u DOT ID {: return new OneRelationSide(u, ID); :}
| type_use.u {: return new OneRelationSide(u, ""); :}
// Optional
| LBRACKET type_use.u DOT ID RBRACKET {: return new OptionalRelationSide(u, ID); :}
| LBRACKET type_use.u RBRACKET {: return new OptionalRelationSide(u, ""); :}
// Many
| type_use.u STAR DOT ID {: return new ManyRelationSide(u, ID); :}
| type_use.u STAR {: return new ManyRelationSide(u, ""); :}
;
Direction direction =
RIGHT {: return new RightDirection(); :}
| BIDIRECTIONAL {: return new Bidirectional(); :}
;
\ No newline at end of file
package org.jastadd.relast.ast;
import org.jastadd.relast.ast.RelAstParser.Terminals;
%%
%public
%final
%class RelAstScanner
%extends beaver.Scanner
%type beaver.Symbol
%function nextToken
%yylexthrow beaver.Scanner.Exception
%scanerror RelAstScanner.ScannerError
%line
%column
%{
private StringBuilder stringLitSb = new StringBuilder();
private beaver.Symbol sym(short id) {
return new beaver.Symbol(id, yyline + 1, yycolumn + 1, yylength(), yytext());
}
private beaver.Symbol sym(short id, String text) {
return new beaver.Symbol(id, yyline + 1, yycolumn + 1, yylength(), text);
}
public static class ScannerError extends Error {
public ScannerError(String message) {
super(message);
}
}
%}
WhiteSpace = [ ] | \t | \f | \n | \r | \r\n
TraditionalComment = "/*" [^*] ~"*/" | "/*" "*"+ "/"
EndOfLineComment = "//" [^\n|\r|\r\n]*
Comment = {TraditionalComment} | {EndOfLineComment}
ID = [a-zA-Z$][a-zA-Z0-9$_]*
FLOAT = -?[0-9]+ \. [0-9]+ {Exponent}?
Exponent = [eE] [+-]? [0-9]+
NUM = -?[0-9]+
%state STRING
%%
<YYINITIAL> {
{WhiteSpace} { /* ignore */ }
{Comment} { /* ignore */ }
"abstract" { return sym(Terminals.ABSTRACT); }
"rel" { return sym(Terminals.RELATION); }
";" { return sym(Terminals.SCOL); }
":" { return sym(Terminals.COL); }
"::=" { return sym(Terminals.ASSIGN); }
"*" { return sym(Terminals.STAR); }
"." { return sym(Terminals.DOT); }
"<" { return sym(Terminals.LT); }
">" { return sym(Terminals.GT); }
"[" { return sym(Terminals.LBRACKET); }
"]" { return sym(Terminals.RBRACKET); }
"->" { return sym(Terminals.RIGHT); }
"<->" { return sym(Terminals.BIDIRECTIONAL); }
// ID
{ID} { return sym(Terminals.ID); }
\" { stringLitSb.setLength(0); yybegin(STRING); }
<<EOF>> { return sym(Terminals.EOF); }
}
<STRING> {
\" { yybegin(YYINITIAL); return sym(Terminals.STRING_LITERAL, stringLitSb.toString()); }
[^\n\r\"\\]+ { stringLitSb.append( yytext() ); }
\\t { stringLitSb.append('\t'); }
\\n { stringLitSb.append('\n'); }
\\r { stringLitSb.append('\r'); }
\\\" { stringLitSb.append('\"'); }
\\ { stringLitSb.append('\\'); }
}
[^] { throw new ScannerError((yyline+1) +"," + (yycolumn+1) + ": Illegal character <"+yytext()+">"); }
package org.jastadd.relast.compiler;
import org.jastadd.relast.ast.*;
import static org.jastadd.relast.compiler.Utils.filterToList;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.regex.Pattern;
import org.jastadd.relast.compiler.options.CommandLine;
import org.jastadd.relast.compiler.options.EnumOption;
import org.jastadd.relast.compiler.options.FlagOption;
import org.jastadd.relast.compiler.options.Option;
import org.jastadd.relast.compiler.options.StringOption;
import org.jastadd.relast.compiler.options.CommandLine.CommandLineException;
import beaver.Parser;
public class Compiler {
protected ArrayList<Option<?>> options;
protected FlagOption optionPrintDot;
protected FlagOption optionFlatPrettyPrint;
protected CommandLine commandLine;
public Compiler(String args[]) throws CommandLineException {
options = new ArrayList<>();
addOptions();
commandLine = new CommandLine(options);
commandLine.parse(args);
Program p = parseProgram(commandLine.getArguments().get(0));
System.out.println(p.dumpTree());
/*if (!p.errors().isEmpty()) {
System.err.println("Errors:");
for (ErrorMessage e: p.errors()) {
System.err.println(e);
}
System.exit(1);
} else {
if (optionPrintDot.isSet()) {
System.out.println(p.genDot());
} else if (optionFlatPrettyPrint.isSet()) {
System.out.println(p.flatPrettyPrint());
} else {
System.out.println("# AST");
System.out.println(p.dumpTree());
FlatState s = p.stoppingState();
for (FlatDependency d: s.getDependencyList()) {
System.out.println(d.sourceDecl());
System.out.println(d.sourceDecl().getAccess() + " " + d.targetDecl().getAccess());
}
for (Node n: s.getNodes()) {
System.out.println(n + ", succ: " + n.succ());
}
System.out.println(s.startingNodes());
System.out.println(s.endingNodes());
System.out.println("# Transitive reduction");
System.out.println(p.startingState().transitiveReduction());
}
}*/
}
protected void addOptions() {
optionPrintDot = addOption(new FlagOption("dot", "print DOT format"));
optionFlatPrettyPrint = addOption(new FlagOption("flat", "flat pretty print"));
}
protected <OptionType extends Option<?>> OptionType addOption(OptionType option) {
options.add(option);
return option;
}
private Program parseProgram(String file) {
FileReader reader = null;
try {
reader = new FileReader(file);
} catch (FileNotFoundException e) {
System.err.println(e.getMessage());