我尝试为配置文件编写Xtext BNF(已知扩展名为.ini
)
例如,我想成功地解析
[Section1]
a = Easy123
b = This *is* valid too
[Section_2]
c = Voilà # inline comments are ignored
我的问题是匹配属性值(在“=”右边)。
如果属性与ID
终端匹配(例如a=Easy123
),则我当前的语法有效。
PropertyFile hidden(SL_COMMENT, WS):
sections+=Section*;
Section:
'[' name=ID ']'
(NEWLINE properties+=Property)+
NEWLINE+;
Property:
name=ID (':' | '=') value=ID ';'?;
terminal WS:
(' ' | '\t')+;
terminal NEWLINE:
// New line on DOS or Unix
'\r'? '\n';
terminal ID:
('A'..'Z' | 'a'..'z') ('A'..'Z' | 'a'..'z' | '_' | '-' | '0'..'9')*;
terminal SL_COMMENT:
// Single line comment
'#' !('\n' | '\r')*;
我不知道如何概括语法以匹配任何文本(例如c=Voilà
)。
我当然需要引入一个新的终端属性:name=ID (':' | '=') value=TEXT ';'?;
问题是:我应该如何定义这个TEXT
终端?
我试过了
>
终端文本:任意其他
这会引发警告
以下标记定义永远无法匹配,因为之前的标记匹配相同的输入:RULE_INT、RULE_STRING、RULE_ML_COMMENT、RULE_ANY_OTHER
(我觉得无所谓)。
解析失败
必需循环(…)输入“a”中的任何内容都不匹配
终端文本:!(“\r”|“\n”|“#”)
这会引发警告
以下标记定义永远无法匹配,因为之前的标记匹配相同的输入:RULE_INT
(我觉得无所谓)。
解析失败
[第1节]的EOF缺失
终端文本:(“!”|“$”..“~”)
(除了#
和“
”)在生成lexer/parser期间没有警告。但是,在
不匹配输入Easy123期待RULE_TEXT
需要规则文本的无关输入“This”
必需循环(…)与“is”中的任何内容都不匹配
谢谢你的帮助(我希望这个语法也能对其他人有用)
作为一种解决办法,我已经改变了
Property:
name=ID ':' value=ID ';'?;
当然,现在=< /code>不再冲突,但这肯定不是一个好的解决方案,因为属性通常可以用
name=value
定义
编辑:实际上,我的输入是一个特定的属性文件,属性是预先知道的。
我的代码现在看起来像
Section:
'[' name=ID ']'
(NEWLINE (properties+=AbstractProperty)?)+;
AbstractProperty:
ADef
| BDef
ADef:
'A' (':'|'=') ID;
BDef:
'B' (':'|'=') Float;
还有一个额外的好处,即属性名被称为关键字,并因此被着色。但是,自动补全仅建议“[”:(
解析这种格式的问题(或者至少是一个问题)是,由于文本部分可能包含=< /code>字符,所以像
foo=bar
这样的行将被解释为单个TEXT令牌,而不是ID,后面跟着“=”,后面跟着TEXT
。我看不出有什么方法可以避免这种情况,而不禁止(或要求转义)文本部分中的=< /code>字符。
如果这不是一个选项,我认为,唯一的解决方案是制作一个与整行匹配的令牌类型
LINE
,然后自己将其拆开。您可以通过从语法中删除文本
和ID
,并将其替换为标记类型行
,该类型匹配所有内容,直到下一个换行符或注释符号,并且必须以有效的ID开头。类似于这样:
LINE :
('A'..'Z' | 'a'..'z') ('A'..'Z' | 'a'..'z' | '_' | '-' | '0'..'9')*
WS* '=' WS*
!('\r' | '\n' | '#')+
;
这个令牌基本上会取代你的
属性
规则。
当然,这是一个相当不令人满意的解决方案,因为它会把整行作为一个字符串,你仍然必须自己把它分开来将标识和文本部分分开。它还阻止你突出显示标识部分或=符号,因为整行是一个令牌,你不能突出显示令牌的一部分(据我所知)。总的来说,这并没有给你带来太多好处,因为你根本不使用
XText
,但是我没有看到更好的方法。
这个语法起到了作用:
grammar org.xtext.example.mydsl.MyDsl hidden(SL_COMMENT, WS)
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
import "http://www.eclipse.org/emf/2002/Ecore"
PropertyFile:
sections+=Section*;
Section:
'[' name=ID ']'
(NEWLINE+ properties+=Property)+
NEWLINE+;
Property:
name=ID value=PROPERTY_VALUE;
terminal PROPERTY_VALUE: (':' | '=') !('\n' | '\r')*;
terminal WS:
(' ' | '\t')+;
terminal NEWLINE:
// New line on DOS or Unix
'\r'? '\n';
terminal ID:
('A'..'Z' | 'a'..'z') ('A'..'Z' | 'a'..'z' | '_' | '-' | '0'..'9')*;
terminal SL_COMMENT:
// Single line comment
'#' !('\n' | '\r')*;
关键是,不要试图只在语法中涵盖完整的语义,还要考虑其他服务。终端规则PROPERTY_VALUE
使用完整的值,包括前导赋值和可选的尾随分号。
现在只需为该语言注册一个值转换器服务,并处理输入中不重要的部分,如下所示:
import org.eclipse.xtext.conversion.IValueConverter;
import org.eclipse.xtext.conversion.ValueConverter;
import org.eclipse.xtext.conversion.ValueConverterException;
import org.eclipse.xtext.conversion.impl.AbstractDeclarativeValueConverterService;
import org.eclipse.xtext.conversion.impl.AbstractIDValueConverter;
import org.eclipse.xtext.conversion.impl.AbstractLexerBasedConverter;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.util.Strings;
import com.google.inject.Inject;
public class PropertyConverters extends AbstractDeclarativeValueConverterService {
@Inject
private AbstractIDValueConverter idValueConverter;
@ValueConverter(rule = "ID")
public IValueConverter<String> ID() {
return idValueConverter;
}
@Inject
private PropertyValueConverter propertyValueConverter;
@ValueConverter(rule = "PROPERTY_VALUE")
public IValueConverter<String> PropertyValue() {
return propertyValueConverter;
}
public static class PropertyValueConverter extends AbstractLexerBasedConverter<String> {
@Override
protected String toEscapedString(String value) {
return " = " + Strings.convertToJavaString(value, false);
}
public String toValue(String string, INode node) {
if (string == null)
return null;
try {
String value = string.substring(1).trim();
if (value.endsWith(";")) {
value = value.substring(0, value.length() - 1);
}
return value;
} catch (IllegalArgumentException e) {
throw new ValueConverterException(e.getMessage(), node, e);
}
}
}
}
在运行时模块中注册服务后,以下测试用例将成功,如下所示:
@Override
public Class<? extends IValueConverterService> bindIValueConverterService() {
return PropertyConverters.class;
}
测试用例:
import org.junit.runner.RunWith
import org.eclipse.xtext.junit4.XtextRunner
import org.xtext.example.mydsl.MyDslInjectorProvider
import org.eclipse.xtext.junit4.InjectWith
import org.junit.Test
import org.eclipse.xtext.junit4.util.ParseHelper
import com.google.inject.Inject
import org.xtext.example.mydsl.myDsl.PropertyFile
import static org.junit.Assert.*
@RunWith(typeof(XtextRunner))
@InjectWith(typeof(MyDslInjectorProvider))
class ParserTest {
@Inject
ParseHelper<PropertyFile> helper
@Test
def void testSample() {
val file = helper.parse('''
[Section1]
a = Easy123
b : This *is* valid too;
[Section_2]
# comment
c = Voilà # inline comments are ignored
''')
assertEquals(2, file.sections.size)
val section1 = file.sections.head
assertEquals(2, section1.properties.size)
assertEquals("a", section1.properties.head.name)
assertEquals("Easy123", section1.properties.head.value)
assertEquals("b", section1.properties.last.name)
assertEquals("This *is* valid too", section1.properties.last.value)
val section2 = file.sections.last
assertEquals(1, section2.properties.size)
assertEquals("Voilà # inline comments are ignored", section2.properties.head.value)
}
}
问题内容: 我刚刚开始学习Swift。我有要从文本文件读取的代码,应用程序显示了整个文本文件的内容。如何显示一行一行并多次调用该行? 包含以下内容: 以下是目前的情况。 如果还有另一种方法,请告诉我。将不胜感激。 问题答案: 斯威夫特3.0 该变量应该是数据的每一行。 使用的代码来自: 在用Obj-C编写的iOSSDK中逐行读取文件并使用NSString 查看旧版Swift的编辑历史记录。
我刚刚开始学习 Swift。我已经从文本文件中读取了我的代码,并且应用程序显示整个文本文件的内容。如何逐行显示并多次调用该行? 包含以下内容: 以下是目前的… 如果有别的方法,请告诉我。非常感谢。
问题内容: 我需要使用Java逐行读取大约5-6 GB的大型文本文件。 我如何快速做到这一点? 问题答案: 常见的模式是使用 如果你假设没有字符编码,则可以更快地读取数据。例如ASCII-7,但差别不大。你处理数据的时间很可能会花费更长的时间。 一种不太常用的模式,可以避免line泄漏的范围。 在Java 8中,你可以执行
dir=“某物”\temp。 我是新来的,任何帮助都很感激。我认为这是字符转义…但我不确定,我想使用正则表达式,但我想我会遇到同样的问题。 预期 C:\\users\\admin\\appdata\\local\\ dir=c:\\users\\admin\\appdata\\local\\temp
类似定位器参数,文本模式是另一种常用的 Selenium 命令参数。需要使用文本模式的命令,例如:verifyTextPresent, verifyTitle, verifyAlert, assertConfirmation, verifyText, verifyPrompt。上面已经提到,LinkText 定位器可使用文本模式。文本模式使用特殊字符来模糊匹配预期的文本,而不必准确的描述该文本。
问题内容: 如何在不使用?的情况下逐行读取文本文件的内容? 例如,我有一个文本文件,里面看起来像这样: 我想创建两个,然后使用类似这样的东西 这样,它分配的价值,以及价值。 问题答案: 您应该使用。 然后,您可以从下一个索引中访问列表的一个特定元素: 这将给您第一行(即:Purlplemonkeys)