如何在简单语法中使用 Space
How to use Space in a simple grammar
我是 antlr 和 ebnf 的初学者。
我在antlr4中表达了如下语法:
grammar RecordGrammar;
Record: 'record';
EndRecord: 'endrecord';
Track: 'track';
EndTrack: 'endtrack';
Length: 'length';
Name: [a-zA-Z]+;
Number: [0-9]+;
WS: [ \t\r\n]+;
records: (record)+ EOF;
record: Record WS Name WS
tracks WS?
EndRecord WS?;
tracks: track WS? (track WS)*;
track: Track WS
length
EndTrack WS?;
length: Length WS Number WS?;
当我在本文中使用上面的语法(使用 antlr)时:
record help
track
length 2
endtrack
track
length 4
endtrack
track
length 42
endtrack
endrecord
...它工作得很好而且花花公子。
但我想扩展 EBNF 中的 'Name' 规则以也接受 Space。
所以我希望语法也接受这个文本文件:
record help me
track
length 2
endtrack
track
length 4
endtrack
track
length 42
endtrack
endrecord
观察记录标签右侧的文字"help me"。
如何在语法中实现这一点?由于 Space 是一个自然的分隔符,我需要在我的规则中对此进行某种特殊处理。感谢我能得到的所有帮助...
您可以创建匹配多个 Name
标记的 name
解析器规则:
name : Name (WS+ Name)*;
但是因为你并没有真正对空格做任何事情,所以请注意在标记化过程中通过添加 -> skip
然后从你的解析器规则中删除所有 WS
来丢弃它们:
grammar RecordGrammar;
records : record+ EOF;
record : Record name tracks EndRecord;
tracks : track+;
track : Track length EndTrack;
length : Length Number;
name : Name+;
Record : 'record';
EndRecord : 'endrecord';
Track : 'track';
EndTrack : 'endtrack';
Length : 'length';
Name : [a-zA-Z]+;
Number : [0-9]+;
WS : [ \t\r\n]+ -> skip;
这将导致以下解析树:
您应该首先决定如何确定名称的实际结束位置。在最初的语法中,这很简单——它是一个单词,所以它以空白字符结尾。在 Bart 的回答中,它是单词 'record' 和 'track' * 之间的每个单词。但这是你的情况吗,或者这个名字实际上可以包含 'track' 这个词吗?
您可能还需要考虑以下选项:
- 在行尾终止名称(在这种情况下,空格变得很重要,您需要在名称中允许该词,使其成为 非保留关键字 ).
- 用引号 (
"
) 或撇号 ('
) 括起一个多词名称 - 在这种情况下,空格并不重要,可以根据 Bart 的回答跳过。
*) 它比实际情况更复杂 - 但这是它如何查找记录名称末尾的基本概念。
我是 antlr 和 ebnf 的初学者。
我在antlr4中表达了如下语法:
grammar RecordGrammar;
Record: 'record';
EndRecord: 'endrecord';
Track: 'track';
EndTrack: 'endtrack';
Length: 'length';
Name: [a-zA-Z]+;
Number: [0-9]+;
WS: [ \t\r\n]+;
records: (record)+ EOF;
record: Record WS Name WS
tracks WS?
EndRecord WS?;
tracks: track WS? (track WS)*;
track: Track WS
length
EndTrack WS?;
length: Length WS Number WS?;
当我在本文中使用上面的语法(使用 antlr)时:
record help
track
length 2
endtrack
track
length 4
endtrack
track
length 42
endtrack
endrecord
...它工作得很好而且花花公子。
但我想扩展 EBNF 中的 'Name' 规则以也接受 Space。
所以我希望语法也接受这个文本文件:
record help me
track
length 2
endtrack
track
length 4
endtrack
track
length 42
endtrack
endrecord
观察记录标签右侧的文字"help me"。
如何在语法中实现这一点?由于 Space 是一个自然的分隔符,我需要在我的规则中对此进行某种特殊处理。感谢我能得到的所有帮助...
您可以创建匹配多个 Name
标记的 name
解析器规则:
name : Name (WS+ Name)*;
但是因为你并没有真正对空格做任何事情,所以请注意在标记化过程中通过添加 -> skip
然后从你的解析器规则中删除所有 WS
来丢弃它们:
grammar RecordGrammar;
records : record+ EOF;
record : Record name tracks EndRecord;
tracks : track+;
track : Track length EndTrack;
length : Length Number;
name : Name+;
Record : 'record';
EndRecord : 'endrecord';
Track : 'track';
EndTrack : 'endtrack';
Length : 'length';
Name : [a-zA-Z]+;
Number : [0-9]+;
WS : [ \t\r\n]+ -> skip;
这将导致以下解析树:
您应该首先决定如何确定名称的实际结束位置。在最初的语法中,这很简单——它是一个单词,所以它以空白字符结尾。在 Bart 的回答中,它是单词 'record' 和 'track' * 之间的每个单词。但这是你的情况吗,或者这个名字实际上可以包含 'track' 这个词吗?
您可能还需要考虑以下选项:
- 在行尾终止名称(在这种情况下,空格变得很重要,您需要在名称中允许该词,使其成为 非保留关键字 ).
- 用引号 (
"
) 或撇号 ('
) 括起一个多词名称 - 在这种情况下,空格并不重要,可以根据 Bart 的回答跳过。
*) 它比实际情况更复杂 - 但这是它如何查找记录名称末尾的基本概念。