我正在尝试创建一个函数,该函数执行以下操作:
假设代码输入是"(a 1 2(b3 4 5(C6)x 7)8 9“,其中管道符号是光标的位置,
函数返回:字符串“b3 4 5(C6) 7”,表示游标范围内的代码。
一个int 8,表示相对于输入的字符串的开始索引。
表示字符串相对于输入的结束索引的int 30。
我已经有了正确返回的工作代码。然而,问题在于忽略注释,同时跟踪上下文(例如字符串、我自己的文字分隔符等等)。
下面是跟踪上下文的代码:
public static void applyContext(Context context, String s, String snext, String sprev) {
if (s.equals("\"")) {
if (context.context == Context.Contexts.MAIN) {
context.context = Context.Contexts.STRING;
context.stringDelimiterIsADoubleQuote = true;
} else if (context.context == Context.Contexts.STRING && context.stringDelimiterIsADoubleQuote && !sprev.equals("\\"))
context.context = Context.Contexts.MAIN;
} else if (s.equals("\'")) {
if (context.context == Context.Contexts.MAIN) {
context.context = Context.Contexts.STRING;
context.stringDelimiterIsADoubleQuote = false;
} else if (context.context == Context.Contexts.STRING && !context.stringDelimiterIsADoubleQuote && !sprev.equals("\""))
context.context = Context.Contexts.MAIN;
} else if (s.equals("/") && snext.equals("/")) {
if (context.context == Context.Contexts.MAIN)
context.context = Context.Contexts.COMMENT;
} else if (s.equals("\n")) {
if(context.context == Context.Contexts.COMMENT)
context.context = Context.Contexts.MAIN;
}
else if (s.equals("\\")) {
if(context.context == Context.Contexts.MAIN)
context.context = Context.Contexts.PATTERN;
else if(context.context == Context.Contexts.PATTERN)
context.context = Context.Contexts.MAIN;
}
}首先,我将使用上述函数,如下所示:
String sampleCode = "(a b "cdef" g \c4 bb2 eb4 g4v0.75\)";
Context c = new Context(Context.Contexts.MAIN);
for(int i = 0; i < sampleCode.length(); i++) {
String s = String.valueOf(sampleCode.charAt(i));
String snext = *nullcheck* ? String.valueOf(sampleCode.charAt(i + 1)) : "";
String sprev = *nullcheck* ? String.valueOf(sampleCode.charAt(i - 1)) : "";
applyContext(c, s, snext, sprev);
if(c.context == blahlbah) doBlah();
}第二,我将使用这两种方法向后转发,因为当前执行描述顶部所述函数的方法如下(以伪代码表示):
function returnCodeInScopeOfCursor(theWholeCode::String, cursorIndex::int) {
var depthOfCodeAtCursorPosition::int = getDepth(theWholeCode, cursorIndex);
Context c = new Context(getContextAt(theWholeCode, cursorIndex));
var currDepth::int = depthOfCodeAtCursorPosition;
var startIndex::int, endIndex::int;
for(i = cursorIndex; i >= 0; i--) {//going backwards
s = .....
snext = ......
sprev = ......
applyContext(c, s, snext, sprev);
if(c.context == Context.MAIN) {
if s = "(" then currDepth --;
if s = ")" then currDepth ++;
}
when currDepth < depthOfCodeAtCursorPosition
startIndex = i + 1;
break;
}
currDepth = depthOfCodeAtCursorPosition;//reset
for(i = cursorIndex; i < theWholeCode.length; i++) {//going forwards
s = ...
snex......
sprev.....
applyContext(c, s, snext, sprev);
if(c.context == Context.MAIN) {
if s = "(" then currDepth ++;
if s = ")" then currDepth --;
}
when currDepth < depthOfCodeAtCursorPosition
endIndex = i - 1;
break;
}
var returnedStr = theWholeCode->from startIndex->to endIndex
return new IndexedCode(returnedStr, startIndex, endIndex);如您所见,这个函数可以向前工作,也可以反向工作。或者至少大部分。唯一的问题是,如果我向后使用这个函数,对注释的正确扫描(用标准的ECMA双斜杠“//”表示)就会乱了套。
如果我要为反向上下文应用程序创建一个单独的函数,并递归地检查每一行是否有一个双斜杠,那么在“//”之后的所有内容都是注释(或者在函数的使用方向上,在//之前的所有内容),这将花费太多的处理时间,因为我想将它用作音乐的livecoding环境。
另外,在尝试执行returnCodeInScopeOfCursor方法之前删除注释可能是不可行的.因为我需要跟踪代码的索引以及其他不需要的内容。如果我要删除注释,所有的代码位置都会乱七八糟,并跟踪我到底在哪里删除了什么,删除了多少个字符等等……我所使用的文本区域输入图形用户界面(RichTextFX)不支持行-查跟踪,所以所有事情都只使用char索引进行跟踪,因此出现了问题…
所以..。对于如何处理我当前的代码,我完全感到困惑。任何帮助、建议、建议等..。我们会非常感激的。
发布于 2016-03-04 17:05:13
您是否可以将注释从// This is a comment<CR>预转换为{ This is a comment}<CR>,然后您可以使用一种可以向后走的语言--和前进。
在进场时应用此转换,并在退出时将其反转,一切都应该是好的。注意,我们将//...替换为{...},因此保留所有charaqcter偏移量。
发布于 2016-03-05 07:33:30
无论如何,在对OldCurmudgeon的想法做了一些实验之后,我想出了一个单独的函数来获得代码的上下文。
public static void applyContextBackwards(Context context, String entireCode, int caretPos) {
String s = String.valueOf(entireCode.charAt(caretPos));
//So far this is not used
//String snext = caretPos + 1 < entireCode.length() ? String.valueOf(entireCode.charAt(caretPos + 1)) : "";
String sprev = caretPos - 1 >= 0 ? String.valueOf(entireCode.charAt(caretPos - 1)) : "";
//Check for all the flags and what not...
if(context.commentedCharsLeft > 0) {
context.commentedCharsLeft--;
if(context.commentedCharsLeft == 0)
context.context = Context.Contexts.MAIN;//The comment is over
}
if(context.expectingEndOfString){
context.context = Context.Contexts.MAIN;
context.expectingEndOfString = false;
}
if(context.expectingEndOfPattern) {
context.context = Context.Contexts.MAIN;
context.expectingEndOfPattern = false;
}
//After all the flags are cleared, do this
if(context.commentedCharsLeft == 0) {
if (s.equals("\"")) {
if (context.context == Context.Contexts.MAIN) {
context.context = Context.Contexts.STRING;
context.stringDelimiterIsADoubleQuote = true;
} else if (context.context == Context.Contexts.STRING && context.stringDelimiterIsADoubleQuote && !sprev.equals("\\"))
context.expectingEndOfString = true;//Change the next char to a MAIN, cuz this one's still part of the string
} else if (s.equals("\'")) {
if (context.context == Context.Contexts.MAIN) {
context.context = Context.Contexts.STRING;
context.stringDelimiterIsADoubleQuote = false;
} else if (context.context == Context.Contexts.STRING && !context.stringDelimiterIsADoubleQuote && !sprev.equals("\""))
context.expectingEndOfString = true;//Change the next char to a MAIN, cuz this one's still part of the string
} else if (s.equals("\n")) {
int earliestOccuranceOfSingleLineCommentDelimiterAsDistanceFromThisNewLine = -1;//-1 for no comments
//Loop until the next \n is found. In the process, determine location of comment if any
for(int i = caretPos; i >= 0; i--) {
String curr = String.valueOf(entireCode.charAt(i));
String prev = i - 1 >= 0 ? String.valueOf(entireCode.charAt(i - 1)) : "";
if(curr.equals("\n"))
break;//Line has been scanned through
if(curr.equals("/") && prev.equals("/"))
earliestOccuranceOfSingleLineCommentDelimiterAsDistanceFromThisNewLine = caretPos - i;
}
//Set the comment context flag
//If no comments, -1 + 1 will be 0 and will be treated as no comments.
context.commentedCharsLeft = earliestOccuranceOfSingleLineCommentDelimiterAsDistanceFromThisNewLine + 1;
if(earliestOccuranceOfSingleLineCommentDelimiterAsDistanceFromThisNewLine > 0) {
context.context = Context.Contexts.COMMENT;
}
} else if (s.equals("\\")) {
if (context.context == Context.Contexts.MAIN)
context.context = Context.Contexts.PATTERN;
else if (context.context == Context.Contexts.PATTERN)
context.expectingEndOfPattern = true;//Change the next char to a MAIN cuz this one's still part of the Pattern
}
}
}https://stackoverflow.com/questions/35801249
复制相似问题