summaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorkrasimir <krasimir@chalmers.se>2009-10-24 10:38:21 +0000
committerkrasimir <krasimir@chalmers.se>2009-10-24 10:38:21 +0000
commit02bb6cc073efc44a8a25be352510eee3e6aa7cb4 (patch)
tree9afc4b98fed029a5e42e463f54267dd42e518d7b /src/server
parent59172a0380cc0c9553b2146af1600bbcacde0b2a (diff)
added tree visualizations in TranslateApp
Diffstat (limited to 'src/server')
-rw-r--r--src/server/FastCGIUtils.hs8
-rw-r--r--src/server/PGFService.hs51
-rw-r--r--src/server/gwt/src/se/chalmers/cs/gf/gwt/client/FridgeApp.java4
-rw-r--r--src/server/gwt/src/se/chalmers/cs/gf/gwt/client/JSONRequestBuilder.java6
-rw-r--r--src/server/gwt/src/se/chalmers/cs/gf/gwt/client/PGF.java35
-rw-r--r--src/server/gwt/src/se/chalmers/cs/gf/gwt/client/PGFWrapper.java42
-rw-r--r--src/server/gwt/src/se/chalmers/cs/gf/gwt/client/TranslateApp.java126
-rw-r--r--src/server/gwt/src/se/chalmers/cs/gf/gwt/public/Translate.css31
-rw-r--r--src/server/gwt/src/se/chalmers/cs/gf/gwt/public/align-btn.pngbin0 -> 138 bytes
-rw-r--r--src/server/gwt/src/se/chalmers/cs/gf/gwt/public/tree-btn.pngbin0 -> 149 bytes
10 files changed, 271 insertions, 32 deletions
diff --git a/src/server/FastCGIUtils.hs b/src/server/FastCGIUtils.hs
index 4c720e216..603ca0db3 100644
--- a/src/server/FastCGIUtils.hs
+++ b/src/server/FastCGIUtils.hs
@@ -2,7 +2,8 @@
module FastCGIUtils (initFastCGI, loopFastCGI,
throwCGIError, handleCGIErrors,
stderrToFile,
- outputJSONP,
+ outputJSONP,
+ outputPNG,
splitBy) where
import Control.Concurrent
@@ -164,6 +165,11 @@ outputJSONP x =
setHeader "Content-Type" "text/json; charset=utf-8"
outputStrict $ UTF8.encodeString str
+outputPNG :: String -> CGI CGIResult
+outputPNG x = do
+ setHeader "Content-Type" "image/png"
+ outputStrict x
+
outputStrict :: String -> CGI CGIResult
outputStrict x | x == x = output x
| otherwise = fail "I am the pope."
diff --git a/src/server/PGFService.hs b/src/server/PGFService.hs
index d0fac03d9..c4290b7da 100644
--- a/src/server/PGFService.hs
+++ b/src/server/PGFService.hs
@@ -19,6 +19,7 @@ import qualified Data.Map as Map
import Data.Maybe
import System.Directory
import System.FilePath
+import System.Process
logFile :: FilePath
logFile = "pgf-error.log"
@@ -37,18 +38,20 @@ cgiMain cache =
do path <- getVarWithDefault "SCRIPT_FILENAME" ""
pgf <- liftIO $ readCache cache path
command <- liftM (maybe "grammar" (urlDecodeUnicode . UTF8.decodeString)) (getInput "command")
- jsonp <- pgfMain pgf command
- outputJSONP jsonp
+ pgfMain pgf command
-pgfMain :: PGF -> String -> CGI JSValue
+pgfMain :: PGF -> String -> CGI CGIResult
pgfMain pgf command =
case command of
- "parse" -> return (doParse pgf) `ap` getText `ap` getCat `ap` getFrom
- "complete" -> return (doComplete pgf) `ap` getText `ap` getCat `ap` getFrom `ap` getLimit
- "linearize" -> return (doLinearize pgf) `ap` getTree `ap` getTo
- "random" -> getCat >>= \c -> getLimit >>= liftIO . doRandom pgf c
- "translate" -> return (doTranslate pgf) `ap` getText `ap` getCat `ap` getFrom `ap` getTo
- "grammar" -> return (doGrammar pgf) `ap` requestAcceptLanguage
+ "parse" -> return (doParse pgf) `ap` getText `ap` getCat `ap` getFrom >>= outputJSONP
+ "complete" -> return (doComplete pgf) `ap` getText `ap` getCat `ap` getFrom `ap` getLimit >>= outputJSONP
+ "linearize" -> return (doLinearize pgf) `ap` getTree `ap` getTo >>= outputJSONP
+ "random" -> getCat >>= \c -> getLimit >>= liftIO . doRandom pgf c >>= outputJSONP
+ "translate" -> return (doTranslate pgf) `ap` getText `ap` getCat `ap` getFrom `ap` getTo >>= outputJSONP
+ "grammar" -> return (doGrammar pgf) `ap` requestAcceptLanguage >>= outputJSONP
+ "abstrtree" -> getTree >>= liftIO . doGraphvizAbstrTree pgf >>= outputPNG
+ "parsetree" -> getTree >>= \t -> getFrom >>= \(Just l) -> liftIO (doGraphvizParseTree pgf l t) >>= outputPNG
+ "alignment" -> getTree >>= liftIO . doGraphvizAlignment pgf >>= outputPNG
_ -> throwCGIError 400 "Unknown command" ["Unknown command: " ++ show command]
where
getText :: CGI String
@@ -68,7 +71,7 @@ pgfMain pgf command =
Just cat -> case PGF.readType cat of
Nothing -> throwCGIError 400 "Bad category" ["Bad category: " ++ cat]
Just typ | typ `elem` PGF.categories pgf -> return $ Just typ
- | otherwise -> throwCGIError 400 "Unknown category" ["Unknown category: " ++ show typ]
+ | otherwise -> throwCGIError 400 "Unknown category" ["Unknown category: " ++ PGF.showType [] typ]
getFrom :: CGI (Maybe PGF.Language)
getFrom = getLang "from"
@@ -98,11 +101,15 @@ doListGrammars =
return $ showJSON $ map toJSObject [[("name", f)] | f <- fs]
doTranslate :: PGF -> String -> Maybe PGF.Type -> Maybe PGF.Language -> Maybe PGF.Language -> JSValue
-doTranslate pgf input mcat mfrom mto = showJSON $ map toJSObject
- [[("from", PGF.showLanguage from),("to", PGF.showLanguage to),("text",output)]
+doTranslate pgf input mcat mfrom mto =
+ showJSON
+ [toJSObject [("from", showJSON (PGF.showLanguage from)),
+ ("tree", showJSON tree),
+ ("linearizations",showJSON [toJSObject [("to", PGF.showLanguage to),("text",output)]
+ | (to,output) <- linearize' pgf mto tree])
+ ]
| (from,trees) <- parse' pgf input mcat mfrom,
- tree <- trees,
- (to,output) <- linearize' pgf mto tree]
+ tree <- trees]
doParse :: PGF -> String -> Maybe PGF.Type -> Maybe PGF.Language -> JSValue
doParse pgf input mcat mfrom = showJSON $ map toJSObject
@@ -141,10 +148,26 @@ doGrammar pgf macc = showJSON $ toJSObject
| l <- PGF.languages pgf]
categories = map toJSObject [[("cat", PGF.showType [] cat)] | cat <- PGF.categories pgf]
+doGraphvizAbstrTree pgf tree = do
+ let dot = PGF.graphvizAbstractTree pgf (True,True) tree
+ readProcess "dot" ["-T","png"] dot
+
+doGraphvizParseTree pgf lang tree = do
+ let dot = PGF.graphvizParseTree pgf lang tree
+ readProcess "dot" ["-T","png"] (UTF8.encodeString dot)
+
+doGraphvizAlignment pgf tree = do
+ let dot = PGF.graphvizAlignment pgf tree
+ readProcess "dot" ["-T","png"] (UTF8.encodeString dot)
+
instance JSON PGF.CId where
readJSON x = readJSON x >>= maybe (fail "Bad language.") return . PGF.readLanguage
showJSON = showJSON . PGF.showLanguage
+instance JSON PGF.Expr where
+ readJSON x = readJSON x >>= maybe (fail "Bad expression.") return . PGF.readExpr
+ showJSON = showJSON . PGF.showExpr []
+
-- * PGF utilities
cat :: PGF -> Maybe PGF.Type -> PGF.Type
diff --git a/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/FridgeApp.java b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/FridgeApp.java
index 6938fae49..c0bfc376e 100644
--- a/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/FridgeApp.java
+++ b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/FridgeApp.java
@@ -58,7 +58,9 @@ public class FridgeApp implements EntryPoint {
public void onResult (PGF.Translations translations) {
outputPanel.removeStyleDependentName("working");
for (PGF.Translation t : translations.iterable()) {
- outputPanel.add(createTranslation(t.getTo(), t.getText()));
+ for (PGF.Linearization l : t.getLinearizations().iterable()) {
+ outputPanel.add(createTranslation(l.getTo(), l.getText()));
+ }
}
}
public void onError (Throwable e) {
diff --git a/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/JSONRequestBuilder.java b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/JSONRequestBuilder.java
index 5453bf8a3..6ddd74ee8 100644
--- a/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/JSONRequestBuilder.java
+++ b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/JSONRequestBuilder.java
@@ -25,7 +25,7 @@ public class JSONRequestBuilder {
}
public static <T extends JavaScriptObject> JSONRequest sendRequest (String base, List<Arg> vars, final JSONCallback<T> callback) {
- String url = base + "?" + buildQueryString(vars);
+ String url = getQueryURL(base,vars);
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);
builder.setTimeoutMillis(30000);
builder.setHeader("Accept","text/plain, text/html;q=0.5, */*;q=0.1");
@@ -57,8 +57,10 @@ public class JSONRequestBuilder {
return eval('(' + json + ')');
}-*/;
- private static String buildQueryString(List<Arg> args) {
+ public static String getQueryURL(String base, List<Arg> args) {
StringBuffer sb = new StringBuffer();
+ sb.append(base);
+ sb.append("?");
if (args != null) {
for (Arg arg : args) {
if (arg.value != null) {
diff --git a/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/PGF.java b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/PGF.java
index 9d62c2ea7..80af107bb 100644
--- a/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/PGF.java
+++ b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/PGF.java
@@ -60,8 +60,19 @@ public class PGF {
protected Translation() { }
public final native String getFrom() /*-{ return this.from; }-*/;
+ public final native String getTree() /*-{ return this.tree; }-*/;
+ public final native Linearizations getLinearizations() /*-{ return this.linearizations; }-*/;
+ }
+
+ public static class Linearizations extends IterableJsArray<Linearization> {
+ protected Linearizations() { }
+ }
+
+ public static class Linearization extends JavaScriptObject {
+ protected Linearization() { }
+
public final native String getTo() /*-{ return this.to; }-*/;
- public final native String getText() /*-{ return this.text; }-*/;
+ public final native String getText() /*-{ return this.text; }-*/;
}
/* Completion */
@@ -118,6 +129,28 @@ public class PGF {
public final native String getTree() /*-{ return this.tree; }-*/;
}
+ public String graphvizAbstractTree(String pgfURL, String abstractTree) {
+ List<Arg> args = new ArrayList<Arg>();
+ args.add(new Arg("command", "abstrtree"));
+ args.add(new Arg("tree", abstractTree));
+ return JSONRequestBuilder.getQueryURL(pgfURL,args);
+ }
+
+ public String graphvizParseTree(String pgfURL, String abstractTree, String lang) {
+ List<Arg> args = new ArrayList<Arg>();
+ args.add(new Arg("command", "parsetree"));
+ args.add(new Arg("tree", abstractTree));
+ args.add(new Arg("from", lang));
+ return JSONRequestBuilder.getQueryURL(pgfURL,args);
+ }
+
+ public String graphvizAlignment(String pgfURL, String abstractTree) {
+ List<Arg> args = new ArrayList<Arg>();
+ args.add(new Arg("command", "alignment"));
+ args.add(new Arg("tree", abstractTree));
+ return JSONRequestBuilder.getQueryURL(pgfURL,args);
+ }
+
/* Common */
public <T extends JavaScriptObject> JSONRequest sendGrammarRequest(String pgfURL, String resource, List<Arg> args, final JSONCallback<T> callback) {
diff --git a/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/PGFWrapper.java b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/PGFWrapper.java
index 40d766c10..329ae5f32 100644
--- a/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/PGFWrapper.java
+++ b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/PGFWrapper.java
@@ -12,10 +12,12 @@ public class PGFWrapper {
private String baseURL;
- private PGF pgf;
+ private String grammarURL;
private String pgfName = null;
+ private PGF pgf;
+
private String inputLanguage = null;
private String outputLanguage = null;
@@ -39,6 +41,10 @@ public class PGFWrapper {
private List<SettingsListener> listeners = new LinkedList<SettingsListener>();
+ public PGFWrapper() {
+ this.baseURL = null;
+ this.pgf = new PGF();
+ }
public PGFWrapper(String baseURL) {
this.baseURL = baseURL;
@@ -93,7 +99,7 @@ public class PGFWrapper {
protected void updateSelectedGrammar () {
clearCachedInfo();
- pgf.grammar(baseURL+"/"+pgfName, new PGF.GrammarCallback() {
+ pgf.grammar(grammarURL, new PGF.GrammarCallback() {
public void onResult(PGF.Grammar grammar) {
userLanguage = grammar.getUserLanguage();
languages = new LinkedHashMap<String,PGF.Language>();
@@ -119,15 +125,27 @@ public class PGFWrapper {
//
public JSONRequest translate (String input, final PGF.TranslateCallback callback) {
- return pgf.translate(baseURL+"/"+pgfName, input, inputLanguage, cat, outputLanguage, callback);
+ return pgf.translate(grammarURL, input, inputLanguage, cat, outputLanguage, callback);
}
public JSONRequest complete (String input, int limit, final PGF.CompleteCallback callback) {
- return pgf.complete(baseURL+"/"+pgfName, input, inputLanguage, cat, limit, callback);
+ return pgf.complete(grammarURL, input, inputLanguage, cat, limit, callback);
}
public JSONRequest parse (String input, final PGF.ParseCallback callback) {
- return pgf.parse(baseURL+"/"+pgfName, input, inputLanguage, cat, callback);
+ return pgf.parse(grammarURL, input, inputLanguage, cat, callback);
+ }
+
+ public String graphvizAbstractTree(String abstractTree) {
+ return pgf.graphvizAbstractTree(grammarURL,abstractTree);
+ }
+
+ public String graphvizParseTree(String abstractTree, String lang) {
+ return pgf.graphvizParseTree(grammarURL,abstractTree,lang);
+ }
+
+ public String graphvizAlignment(String abstractTree) {
+ return pgf.graphvizAlignment(grammarURL,abstractTree);
}
//
@@ -140,6 +158,20 @@ public class PGFWrapper {
public void setPGFName(String pgfName) {
this.pgfName = pgfName;
+ this.grammarURL = baseURL + "/" + pgfName;
+ this.inputLanguage = null;
+ this.outputLanguage = null;
+ this.cat = null;
+ updateSelectedGrammar();
+ }
+
+ public String getGrammarURL() {
+ return grammarURL;
+ }
+
+ public void setGrammarURL(String grammarURL) {
+ this.pgfName = null;
+ this.grammarURL = grammarURL;
this.inputLanguage = null;
this.outputLanguage = null;
this.cat = null;
diff --git a/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/TranslateApp.java b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/TranslateApp.java
index 2370d484c..14aa2da2d 100644
--- a/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/TranslateApp.java
+++ b/src/server/gwt/src/se/chalmers/cs/gf/gwt/client/TranslateApp.java
@@ -6,10 +6,7 @@ import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.HistoryListener;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.user.client.ui.*;
public class TranslateApp implements EntryPoint {
@@ -47,7 +44,24 @@ public class TranslateApp implements EntryPoint {
outputPanel.clear();
outputPanel.removeStyleDependentName("working");
for (PGF.Translation t : translations.iterable()) {
- outputPanel.add(createTranslation(t.getTo(), t.getText()));
+ HorizontalPanel hPanel = new HorizontalPanel();
+ hPanel.addStyleName("my-translation-frame");
+ VerticalPanel linsPanel = new VerticalPanel();
+ linsPanel.addStyleName("my-translation-bar");
+ hPanel.add(linsPanel);
+ HorizontalPanel btnPanel = new HorizontalPanel();
+ btnPanel.addStyleName("my-translation-btns");
+ btnPanel.setSpacing(4);
+ btnPanel.add(createAbsTreeButton(t.getTree()));
+ btnPanel.add(createAlignButton(t.getTree()));
+ hPanel.add(btnPanel);
+ hPanel.setCellHorizontalAlignment(btnPanel,
+ HasHorizontalAlignment.ALIGN_RIGHT);
+ outputPanel.add(hPanel);
+
+ for (PGF.Linearization l : t.getLinearizations().iterable()) {
+ linsPanel.add(createTranslation(l.getTo(), t.getTree(), l.getText()));
+ }
}
}
public void onError (Throwable e) {
@@ -56,13 +70,113 @@ public class TranslateApp implements EntryPoint {
});
}
- protected Widget createTranslation(String language, String text) {
+ protected Widget createAbsTreeButton(final String abstractTree) {
+ Image treeBtn = new Image("se.chalmers.cs.gf.gwt.TranslateApp/tree-btn.png");
+ treeBtn.addClickListener(
+ new ClickListener() {
+ public void onClick(Widget sender) {
+ // Create a dialog box and set the caption text
+ final DialogBox dialogBox = new DialogBox();
+ dialogBox.setText("Abstract Syntax Tree");
+
+ // Create a table to layout the content
+ HorizontalPanel dialogContents = new HorizontalPanel();
+ dialogContents.setSpacing(4);
+ dialogBox.setWidget(dialogContents);
+
+ // Add an image to the dialog
+
+ Frame image = new Frame(pgf.graphvizAbstractTree(abstractTree));
+ image.addStyleName("my-treeimage");
+ dialogContents.add(image);
+
+ // Add a close button at the bottom of the dialog
+ Button closeButton = new Button("Close",
+ new ClickListener() {
+ public void onClick(Widget sender) {
+ dialogBox.hide();
+ }
+ });
+ dialogContents.add(closeButton);
+
+ dialogBox.center();
+ dialogBox.show();
+ }
+ });
+ return treeBtn;
+ }
+
+ protected Widget createAlignButton(final String abstractTree) {
+ Image alignBtn = new Image("se.chalmers.cs.gf.gwt.TranslateApp/align-btn.png");
+ alignBtn.addClickListener(
+ new ClickListener() {
+ public void onClick(Widget sender) {
+ // Create a dialog box and set the caption text
+ final DialogBox dialogBox = new DialogBox();
+ dialogBox.setText("Word Alignment");
+
+ // Create a table to layout the content
+ HorizontalPanel dialogContents = new HorizontalPanel();
+ dialogContents.setSpacing(4);
+ dialogBox.setWidget(dialogContents);
+
+ // Add an image to the dialog
+ Frame image = new Frame(pgf.graphvizAlignment(abstractTree));
+ image.addStyleName("my-alignmentimage");
+ dialogContents.add(image);
+
+ // Add a close button at the bottom of the dialog
+ Button closeButton = new Button("Close",
+ new ClickListener() {
+ public void onClick(Widget sender) {
+ dialogBox.hide();
+ }
+ });
+ dialogContents.add(closeButton);
+
+ dialogBox.center();
+ dialogBox.show();
+ }
+ });
+ return alignBtn;
+ }
+
+ protected Widget createTranslation(final String language, final String abstractTree, String text) {
Label l = new Label(text);
l.addStyleName("my-translation");
String lang = pgf.getLanguageCode(language);
if (lang != null) {
l.getElement().setLang(lang);
}
+ l.addClickListener(new ClickListener() {
+ public void onClick(Widget sender) {
+ // Create a dialog box and set the caption text
+ final DialogBox dialogBox = new DialogBox();
+ dialogBox.setText("Parse Tree");
+
+ // Create a table to layout the content
+ HorizontalPanel dialogContents = new HorizontalPanel();
+ dialogContents.setSpacing(4);
+ dialogBox.setWidget(dialogContents);
+
+ // Add an image to the dialog
+ Frame image = new Frame(pgf.graphvizParseTree(abstractTree, language));
+ image.addStyleName("my-treeimage");
+ dialogContents.add(image);
+
+ // Add a close button at the bottom of the dialog
+ Button closeButton = new Button("Close",
+ new ClickListener() {
+ public void onClick(Widget sender) {
+ dialogBox.hide();
+ }
+ });
+ dialogContents.add(closeButton);
+
+ dialogBox.center();
+ dialogBox.show();
+ }
+ });
return l;
}
diff --git a/src/server/gwt/src/se/chalmers/cs/gf/gwt/public/Translate.css b/src/server/gwt/src/se/chalmers/cs/gf/gwt/public/Translate.css
index 9a904c228..90fcc75ea 100644
--- a/src/server/gwt/src/se/chalmers/cs/gf/gwt/public/Translate.css
+++ b/src/server/gwt/src/se/chalmers/cs/gf/gwt/public/Translate.css
@@ -23,13 +23,40 @@
.my-translations {
margin-top: 1em;
}
-
+
+.my-translation-frame {
+ width: 100%;
+ margin: 0.5em;
+ background: #D0E4F6;
+}
+
+.my-translation-bar {
+ padding-left: 25px;
+ padding-right: 25px;
+ width: 100%;
+}
+
.my-translation {
margin: 0.2em;
- padding-left: 25px;
font-size: 150%;
background-repeat: no-repeat;
background-position: 0% 50%;
+ cursor:pointer;
+}
+
+.my-translation-btns {
+ background: #DDDDDD;
+ cursor:pointer;
+}
+
+.my-treeimage {
+ width: 650px;
+ height: 520px;
+}
+
+.my-alignmentimage {
+ width: 450px;
+ height: 300px;
}
/*
diff --git a/src/server/gwt/src/se/chalmers/cs/gf/gwt/public/align-btn.png b/src/server/gwt/src/se/chalmers/cs/gf/gwt/public/align-btn.png
new file mode 100644
index 000000000..ca6a391c1
--- /dev/null
+++ b/src/server/gwt/src/se/chalmers/cs/gf/gwt/public/align-btn.png
Binary files differ
diff --git a/src/server/gwt/src/se/chalmers/cs/gf/gwt/public/tree-btn.png b/src/server/gwt/src/se/chalmers/cs/gf/gwt/public/tree-btn.png
new file mode 100644
index 000000000..ebd243617
--- /dev/null
+++ b/src/server/gwt/src/se/chalmers/cs/gf/gwt/public/tree-btn.png
Binary files differ