Commit 1deba8b2 authored by Sebastian Pretscher's avatar Sebastian Pretscher

Merge branch 'master' of git@github.com:jroith/cup-eclipse.git

parents 9a0cb463 4623f7c9
......@@ -140,6 +140,9 @@ action code {:
protected String multipart_name = new String();
protected Stack multipart_names = new Stack();
// TODO: this is a hack, since we can't store the CODE_STRING offsets properly.
private int prod_part_offset;
/** table of declared symbols -- contains production parts indexed by name */
protected Hashtable symbols = new Hashtable();
......@@ -413,7 +416,7 @@ code_parts ::=
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
action_code_part ::=
ACTION CODE CODE_STRING : user_code opt_semi
ACTION : act CODE CODE_STRING : user_code opt_semi : smi
{:
if (context.action_code!=null)
errMan.Warning(ErrorSource.Parser,
......@@ -423,12 +426,13 @@ action_code_part ::=
context.action_code = user_code;
int debug_id = get_new_debug_id();
// TODO: attach inner range! based on user_codexleft, user_codexright
parserResult.actionCode = new SpecialCodeBlock(
debug_id,
SpecialCodeBlock.BlockType.Action,
user_code,
new Range(Position.fromLocation(user_codexleft),
Position.fromLocation(user_codexright)));
new Range(Position.fromLocation(actxleft),
Position.fromLocation(smixright)));
}
:}
;
......@@ -436,7 +440,7 @@ action_code_part ::=
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
parser_code_part ::=
PARSER CODE CODE_STRING:user_code opt_semi
PARSER : prs CODE CODE_STRING:user_code opt_semi : smi
{:
if (context.parser_code!=null)
errMan.Warning(ErrorSource.Parser,
......@@ -449,8 +453,8 @@ parser_code_part ::=
debug_id,
SpecialCodeBlock.BlockType.Parser,
user_code,
new Range(Position.fromLocation(user_codexleft),
Position.fromLocation(user_codexright)));
new Range(Position.fromLocation(prsxleft),
Position.fromLocation(smixright)));
}
:}
;
......@@ -458,7 +462,7 @@ parser_code_part ::=
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
init_code ::=
INIT WITH CODE_STRING:user_code opt_semi
INIT : init WITH CODE_STRING:user_code opt_semi : smi
{:
if (context.init_code!=null)
errMan.Warning(ErrorSource.Parser, "Redundant init code (skipping)",
......@@ -470,8 +474,8 @@ init_code ::=
debug_id,
SpecialCodeBlock.BlockType.Init,
user_code,
new Range(Position.fromLocation(user_codexleft),
Position.fromLocation(user_codexright)));
new Range(Position.fromLocation(initxleft),
Position.fromLocation(smixright)));
}
:}
;
......@@ -479,7 +483,7 @@ init_code ::=
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
scan_code ::=
SCAN WITH CODE_STRING:user_code opt_semi
SCAN : scan WITH CODE_STRING:user_code opt_semi : smi
{:
if (context.scan_code!=null)
errMan.Warning(ErrorSource.Parser, "Redundant scan code (skipping)",
......@@ -492,8 +496,8 @@ scan_code ::=
debug_id,
SpecialCodeBlock.BlockType.Scan,
user_code,
new Range(Position.fromLocation(user_codexleft),
Position.fromLocation(user_codexright)));
new Range(Position.fromLocation(scanxleft),
Position.fromLocation(smixright)));
}
:}
......@@ -665,7 +669,7 @@ terminal_list ::= terminal_list:lst COMMA terminal_id:trm
{:
Range range = new Range(Position.fromLocation(trmxleft),
Position.fromLocation(trmxright));
((List<Terminal>) lst).add(new Terminal(new Name (trm, range), range));
((List<Terminal>) lst).add(new Terminal(new Name (trm, range), (Range) range.clone()));
RESULT = lst;
:}
|
......@@ -674,7 +678,7 @@ terminal_list ::= terminal_list:lst COMMA terminal_id:trm
Range range = new Range(Position.fromLocation(trmxleft),
Position.fromLocation(trmxright));
List<Terminal> lst = new ArrayList<Terminal>();
lst.add(new Terminal(new Name (trm, range), range));
lst.add(new Terminal(new Name (trm, range), (Range) range.clone()));
RESULT = lst;
:}
;
......@@ -735,7 +739,7 @@ start_spec ::=
Range innerRange = new Range(Position.fromLocation(start_namexleft),
Position.fromLocation(start_namexright));
parserResult.startWith = new StartWith(new NonTerminal (
new Name (start_name, innerRange), innerRange), range);
new Name (start_name, innerRange), (Range) innerRange.clone()), range);
}
:}
|
......@@ -927,7 +931,13 @@ rhs ::=
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
prod_part_list ::= prod_part_list prod_part | empty;
prod_part_list ::= prod_part_list {:
// TODO: This is not quite correct, but it seems that we can't get the correct offset
// of CODE_STRING below. So we get the offset of the previous token here.
//
prod_part_offset = ((ComplexSymbol) cur_token).xright.getOffset();
:} prod_part | empty;
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
......@@ -951,22 +961,33 @@ prod_part ::=
Range range = new Range (Position.fromLocation(symidxleft),
Position.fromLocation(symidxright));
if (labid == null)
ref = new ProductionSymbolRef(new Name(symid, range), range);
ref = new ProductionSymbolRef(new Name(symid, range), (Range) range.clone());
else
ref = new LabeledProductionSymbolRef(new Name(symid, range), labid, range);
ref = new LabeledProductionSymbolRef(new Name(symid, range), labid, (Range) range.clone());
ast_add_rhs_part(ref);
}
:}
|
CODE_STRING : code_str
| CODE_STRING : code_str
{:
/* add a new production part */
int debug_id = get_new_debug_id();
add_rhs_part(new action_part(attach_debug_symbol(debug_id, code_str)));
// TODO: assign inner range as well: code_strxleft, code_strxright
// TODO: this is a quick and dirty workaround.
// it means, however, that the columns and offsets don't properly match up!
int offsetEnd = prod_part_offset + code_str.length();
Position pos1 = new Position(
code_strxleft.getLine(), code_strxleft.getColumn(), prod_part_offset);
Position pos2 = new Position(
code_strxright.getLine(), code_strxright.getColumn(), offsetEnd);
ast_add_rhs_part(new ActionCodeBlock(debug_id, code_str,
Range.fromLocations(code_strxleft, code_strxright)
)); // jrTODO: positions
new Range(pos1, pos2)
));
:}
;
......@@ -1071,7 +1092,7 @@ new_term_id ::=
Range range = new Range(Position.fromLocation(term_idxleft),
Position.fromLocation(term_idxright));
RESULT = new Terminal(new Name(term_id, range), range);
RESULT = new Terminal(new Name(term_id, range), (Range) range.clone());
}
:}
......@@ -1108,7 +1129,7 @@ new_non_term_id ::=
// jrTODO: non_term_id vs. multipart_name
Range range = new Range(Position.fromLocation(non_term_idxleft),
Position.fromLocation(non_term_idxright));
RESULT = new NonTerminal(new Name(non_term_id, range), range);
RESULT = new NonTerminal(new Name(non_term_id, range), (Range) range.clone());
}
:}
;
......
......@@ -25,12 +25,6 @@ class Demo
// System.out.println(res);
System.out.println("\nLocationPatchVisitor:");
long ms = System.currentTimeMillis();
LocationPatchVisitor locVisitor = new LocationPatchVisitor(new Position(0,0,0), 0, 0);
res.accept(locVisitor, null);
System.out.println("millis: " + (System.currentTimeMillis() - ms));
System.out.println("\nDeclarationVisitor:");
Declarations oldDecl = null;
......
......@@ -11,12 +11,26 @@ public class Position {
public int getLine() { return line; }
public int getColumn() { return column; }
public int getOffsetFromStart() { return offsetFromStart; }
public void move(int diffLines, int diffColumns, int diffOffset) {
if (this.line >= 0)
this.line += diffLines;
if (this.column >= 0)
this.column += diffColumns;
if (this.offsetFromStart >= 0)
this.offsetFromStart += diffOffset;
}
public Position(int line, int column, int offsetFromStart) {
this.line = line;
this.column = column;
this.offsetFromStart = offsetFromStart;
}
@Override
public Object clone() {
return new Position(line, column, offsetFromStart);
}
@Override
public String toString() {
......@@ -24,6 +38,8 @@ public class Position {
builder.append(line);
builder.append("/");
builder.append(column);
builder.append("/");
builder.append(offsetFromStart);
return builder.toString();
}
......@@ -35,6 +51,10 @@ public class Position {
builder.append(column);
return builder.toString();
}
public static Position fromOffset(int offset) {
return new Position(-1, -1, offset);
}
public static Position fromLocation(Location loc) {
return new Position(loc.getLine(),
......
......@@ -13,11 +13,29 @@ public class Range {
public Position getEnd() {
return end;
}
public int getLength() {
if (begin == null
|| end == null
|| begin.getOffsetFromStart() < 0
|| end.getOffsetFromStart() < 0)
{
return 0;
}
return end.getOffsetFromStart() - begin.getOffsetFromStart();
}
public Range(Position begin, Position end) {
this.begin = begin;
this.end = end;
}
@Override
public Object clone() {
return new Range(
(begin != null) ? (Position) begin.clone() : null,
(end != null) ? (Position) end.clone() : null);
}
public boolean contains(Position pos) {
return contains(pos, 0);
......@@ -26,26 +44,36 @@ public class Range {
public boolean contains(Position pos, int removedLength) {
if (pos == null || begin == null || end == null)
return false;
if (pos.getLine() >= begin.getLine() && pos.getLine() <= end.getLine()) {
if (pos.getLine() == begin.getLine()
&& pos.getColumn() < begin.getColumn())
return false;
// we are certainly past the start.
if (pos.getLine() < 0 || pos.getColumn() < 0) {
// do an offset-based comparison.
if (pos.getOffsetFromStart() >= begin.getOffsetFromStart() &&
pos.getOffsetFromStart() <= end.getOffsetFromStart())
return true;
return false;
} else {
// do a line-based comparison.
if (pos.getLine() >= begin.getLine() && pos.getLine() <= end.getLine()) {
if (pos.getLine() == begin.getLine()
&& pos.getColumn() < begin.getColumn())
return false;
// we are certainly past the start.
if (pos.getLine() == end.getLine()
&& pos.getColumn() > end.getColumn())
return false;
// we are certainly not past the end.
if (pos.getLine() == end.getLine()
&& pos.getColumn() > end.getColumn())
return false;
// we are certainly not past the end.
if (removedLength == 0) {
return true;
} else {
throw new RuntimeException("not implemented!");
// TODO: we really should check, that the amount of code
// remove is not too much.
// return true;
if (removedLength == 0) {
return true;
} else {
throw new RuntimeException("not implemented!");
// TODO: we really should check, that the amount of code
// remove is not too much.
// return true;
}
}
}
return false;
......
......@@ -4,7 +4,7 @@ import de.in.tum.www2.cup.Position;
import de.in.tum.www2.cup.Range;
import de.in.tum.www2.cup.ast.*;
public class FindAtPositionVisitor extends Visitor<Object>
public class FindAtPositionVisitor extends WildcardVisitor<Object>
{
private AbstractNode result;
private Position pos;
......@@ -20,36 +20,43 @@ public class FindAtPositionVisitor extends Visitor<Object>
this.pos = pos;
}
// TODO: does not work for all elements, yet ...
private void updateIfMatch(AbstractNode node) {
Range range = node.getRange();
if (range == null)
private void updateIfNewAndMatch(AbstractNode node) {
if (result != null || node == null || node.getRange() == null)
return;
if (range.contains(pos)) {
if (node.getRange().contains(pos))
result = node;
}
}
/*
@Override
public void postVisit (ActionCodeBlock node, Object data) {
if (node == null)
return;
updateIfMatch(node);
updateIfNewAndMatch(node);
}
@Override
public void postVisit (SpecialCodeBlock node, Object data) {
if (node == null)
return;
updateIfMatch(node);
updateIfNewAndMatch(node);
}
@Override
public void postVisit (Name node, Object data) {
if (node == null)
return;
updateIfMatch(node);
updateIfNewAndMatch(node);
}
*/
@Override
public Object preVisitWildcard(AbstractNode node, Object data) {
return null;
}
@Override
public void postVisitWildcard(AbstractNode node, Object data) {
updateIfNewAndMatch(node);
}
}
......@@ -5,68 +5,43 @@ import de.in.tum.www2.cup.ast.*;
public class LocationPatchVisitor extends WildcardVisitor<Object>
{
private boolean foundLocation;
private Position oldRemovedFrom;
private int oldRemovedLength;
private int newLength;
// TODO: in case we are already past the position, we could really
// cancel early, if the pattern would support it.
private int fixAfterOffset;
private int fixColumnUntilOffset;
private int diffLines;
private int diffColumns;
private int diffOffset;
public LocationPatchVisitor(int fixAfterOffset, int fixColumnUntilOffset,
int diffLines, int diffColumns, int diffOffset) {
this.fixAfterOffset = fixAfterOffset;
this.fixColumnUntilOffset = fixColumnUntilOffset;
this.diffLines = diffLines;
this.diffColumns = diffColumns;
this.diffOffset = diffOffset;
}
// TODO: this still can't deal with new/removed lines!
public LocationPatchVisitor(Position oldRemovedFrom, int oldRemovedLength, int newLength) {
this.oldRemovedFrom = oldRemovedFrom;
this.oldRemovedLength = oldRemovedLength;
this.newLength = newLength;
private void fixPosition(String comment, AbstractNode node, Position pos) {
if (pos != null && pos.getOffsetFromStart() >= fixAfterOffset) {
int cols = diffColumns;
if (fixColumnUntilOffset != -1 && pos.getOffsetFromStart() >= fixColumnUntilOffset)
cols = 0;
// System.out.print("fixing (diffColumns: " + diffColumns + ", cols: " + cols + ") " + comment + "..." + node.getClass().getName() + " from " + pos);
pos.move(diffLines, cols, diffOffset);
// System.out.println(" to " + pos);
}
}
@Override
public Object preVisitWildcard(AbstractNode node, Object data) {
if (foundLocation) {
// we are now processing an object that comes after the patch point.
}
return data;
}
@Override
public void postVisitWildcard(AbstractNode node, Object data) {
}
// TODO: first, assume there is no new line.
// TODO: for special nodes:
// - check if the edited location falls within the correct part of the range.
// - if so: check if the edit completes a close-symbol.
// - if not: perform the edit and update the end-range(s).
// - set a flag, so all future visited nodes push their locations forward,
// if they are on the same line.
@Override
public void postVisit (ActionCodeBlock node, Object data) {
if (!foundLocation) {
// try to detect, we the edit happens in here.
// TODO: ensure the range is the correct one!
}
}
@Override
public void postVisit (SpecialCodeBlock node, Object data) {
if (!foundLocation) {
if (node.getRange().contains(oldRemovedFrom, oldRemovedLength)) {
// we found our change point.
foundLocation = true;
// now, let's patch our own object, first.
// -> update string.
// -> update all locations.
// next, all objects visited from here must be patched.
}
if (node != null) {
fixPosition("begin", node, node.getBegin());
fixPosition("end", node, node.getEnd());
}
}
}
......@@ -68,44 +68,56 @@ public class RefResolutionVisitor extends Visitor<Object>
@Override public Object preVisit (NonTerminalDeclaration node, Object data) {
if (node == null)
return data;
for(NonTerminal nt : node.getNonTerminals()) {
String name = nt.getNameStringOrNull();
declarations.put(name, nt);
resolveDefinitionFrom(name, nt);
}
if (node != null)
for(NonTerminal nt : node.getNonTerminals()) {
if (nt != null) {
String name = nt.getNameStringOrNull();
declarations.put(name, nt);
resolveDefinitionFrom(name, nt);
}
}
return data;
}
@Override public Object preVisit (TerminalDeclaration node, Object data) {
if (node == null)
return data;
for(Terminal t : node.getTerminals())
declarations.put(t.getNameStringOrNull(), t);
if (node != null)
for(Terminal t : node.getTerminals())
if (t != null)
declarations.put(t.getNameStringOrNull(), t);
return data;
}
@Override public Object preVisit (TypedNonTerminalDeclaration node, Object data) {
if (node == null)
return data;
for(NonTerminal nt : node.getNonTerminals()) {
String name = nt.getNameStringOrNull();
declarations.put(name, nt);
resolveDefinitionFrom(name, nt);
}
if (node.getNonTerminals() != null)
for(NonTerminal nt : node.getNonTerminals()) {
if (nt != null) {
String name = nt.getNameStringOrNull();
declarations.put(name, nt);
resolveDefinitionFrom(name, nt);
}
}
return data;
}
@Override public Object preVisit (TypedTerminalDeclaration node, Object data) {
for(Terminal t : node.getTerminals())
declarations.put(t.getNameStringOrNull(), t);
if (node.getTerminals() != null)
for(Terminal t : node.getTerminals())
if (t != null)
declarations.put(t.getNameStringOrNull(), t);
return data;
}
@Override public Object preVisit (Precedence node, Object data) {
if (node == null)
return data;
for(Terminal t : node.getTerminals())
resolveDeclarationFrom(t.getNameStringOrNull(), t);
if (node.getTerminals() != null)
for(Terminal t : node.getTerminals())
if (t != null)
resolveDeclarationFrom(t.getNameStringOrNull(), t);
return data;
}
......
......@@ -22,7 +22,8 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.jdt.debug;bundle-version="3.8.101",
org.eclipse.jdt.core;bundle-version="3.10.0",
org.eclipse.jdt.ui;bundle-version="3.10.1",
org.eclipse.ant.core;bundle-version="3.3.0"
org.eclipse.ant.core;bundle-version="3.3.0",
org.eclipse.text
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .
package de.tum.in.www2.cupplugin.controller;
import java.awt.Event;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
......@@ -10,6 +12,7 @@ import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITypedRegion;
......@@ -108,11 +111,13 @@ public class DocumentDidChangeJob extends Job {
jobs.remove(JobsToDo.locationPatch);
}
if (jobs.contains(JobsToDo.locationPatch)) {
LocationPatchJob locPatch = new LocationPatchJob();
// TODO: the location patcher need to always run, even when only comments or
// new lines were edited.
// if (jobs.contains(JobsToDo.locationPatch)) {
LocationPatchJob locPatch = new LocationPatchJob(documentEvents);
locPatch.setSystem(true);
locPatch.schedule();
}
// }
IFile file = ((FileEditorInput) myEditor.getEditorInput()).getFile();
CupEditorErrorReporter errorReporter = new CupEditorErrorReporter(file);
......@@ -132,10 +137,7 @@ public class DocumentDidChangeJob extends Job {
e.printStackTrace();
}
// errorReporter.pushToUIThread();
// TODO
// errorReporter.pushToUIThread();
errorReporter.pushToUIThread();
if (result != null) {
// System.out.println(result.toString());
......@@ -174,7 +176,7 @@ public class DocumentDidChangeJob extends Job {
// errorReporter.pushToUIThread();
if (lalrResult != null) {
LaLrResultJob resultLaLrModelJob = new LaLrResultJob(
LaLrResultJob resultLaLrModelJob = new LaLrResultJob(myEditor,
lalrResult, revNumber, context);
resultLaLrModelJob.setSystem(true);
resultLaLrModelJob.schedule();
......@@ -188,6 +190,9 @@ public class DocumentDidChangeJob extends Job {
return Status.CANCEL_STATUS;
}
}
errorReporter.pushToUIThread();
System.out.println(jobs);
......@@ -203,7 +208,7 @@ public class DocumentDidChangeJob extends Job {
return Status.OK_STATUS;
}
class CallbackJob extends UIJob {
static class CallbackJob extends UIJob {
CupTextEditor myEditor = null;
public CallbackJob(CupTextEditor editor) {
......@@ -246,48 +251,53 @@ public class DocumentDidChangeJob extends Job {
}
}
class LaLrResultJob extends UIJob {
LALRResult lalrResult;
long lalrResulRevisionNumber;
CupContext lalrContext;
public LaLrResultJob(LALRResult result, long revisionNumber,
CupContext context) {
super("LaLr Result UI Job");
this.lalrResult = result;
this.lalrResulRevisionNumber = revisionNumber;
this.lalrContext = context;
}
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
IDocumentProvider provider = myEditor.getDocumentProvider();
if (provider != null) {
IDocument document = provider.getDocument(myEditor
.getEditorInput());
if (document != null) {
Model model = Model.getInstanceForDocument(document);
model.setLaLrResultModel(this.lalrResult,
lalrResulRevisionNumber, lalrContext);
return Status.OK_STATUS;
}
}
return Status.CANCEL_STATUS;
}
}
class LocationPatchJob extends UIJob {
public LocationPatchJob() {
private List<DocumentEvent> documentEvents;
// TODO: can we be sure that we are the only one accessing the documentEvents list?
public LocationPatchJob(List<DocumentEvent> documentEvents) {
super("Location Patch Job");
this.documentEvents = new ArrayList<DocumentEvent> (documentEvents);
}
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
/*
System.out.println("RUNNING LocationPatchJob: ");
// TODO: combine consecutive 1-character insert events.
for (DocumentEvent event : documentEvents) {
System.out.println("PROCESSING DocumentEvent: ");
System.out.println(" Offset: " + event.getOffset());
System.out.println(" Replaced: " + event.getLength());
System.out.println(" New: " + event.getText().length());