Eclipse 如何使用antlr显示句子中的所有代词及其人称
根据WayneH的语法编辑 这是我语法文件里的东西Eclipse 如何使用antlr显示句子中的所有代词及其人称,eclipse,parsing,antlr,antlr3,Eclipse,Parsing,Antlr,Antlr3,根据WayneH的语法编辑 这是我语法文件里的东西 grammar pfinder; options { language = Java; } sentence : ((words | pronoun) SPACE)* ((words | pronoun) ('.' | '?')) ; words : WORDS {System.out.println($text);}; pronoun returns [String value] : sfir
grammar pfinder;
options {
language = Java;
}
sentence
: ((words | pronoun) SPACE)* ((words | pronoun) ('.' | '?'))
;
words
: WORDS {System.out.println($text);};
pronoun returns [String value]
: sfirst {$value = $sfirst.value; System.out.println($sfirst.text + '(' + $sfirst.value + ')');}
| ssecond {$value = $ssecond.value; System.out.println($ssecond.text + '(' + $ssecond.value + ')');}
| sthird {$value = $sthird.value; System.out.println($sthird.text + '(' + $sthird.value + ')');}
| pfirst {$value = $pfirst.value; System.out.println($pfirst.text + '(' + $pfirst.value + ')');}
| psecond {$value = $psecond.value; System.out.println($psecond.text + '(' + $psecond.value + ')');}
| pthird{$value = $pthird.value; System.out.println($pthird.text + '(' + $pthird.value + ')');};
sfirst returns [String value] : ('i' | 'me' | 'my' | 'mine') {$value = "s1";};
ssecond returns [String value] : ('you' | 'your'| 'yours'| 'yourself') {$value = "s2";};
sthird returns [String value] : ('he' | 'she' | 'it' | 'his' | 'hers' | 'its' | 'him' | 'her' | 'himself' | 'herself') {$value = "s3";};
pfirst returns [String value] : ('we' | 'us' | 'our' | 'ours') {$value = "p1";};
psecond returns [String value] : ('yourselves') {$value = "p2";};
pthird returns [String value] : ('they'| 'them'| 'their'| 'theirs' | 'themselves') {$value = "p3";};
WORDS : LETTER*;// {$channel=HIDDEN;};
SPACE : (' ')?;
fragment LETTER : ('a'..'z' | 'A'..'Z');
下面是关于java测试类的内容
import java.util.Scanner;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import java.util.List;
public class test2 {
public static void main(String[] args) throws RecognitionException {
String s;
Scanner input = new Scanner(System.in);
System.out.println("Eter a Sentence: ");
s=input.nextLine().toLowerCase();
ANTLRStringStream in = new ANTLRStringStream(s);
pfinderLexer lexer = new pfinderLexer(in);
TokenStream tokenStream = new CommonTokenStream(lexer);
pfinderParser parser = new pfinderParser(tokenStream);
parser.pronoun();
}
}
我需要在测试文件中放入什么,以便它显示一个句子中的所有代词及其各自的值(s1,s2,…)片段不会创建标记,并且将它们放在解析器规则中不会给出理想的结果 在我的测试箱上,这产生了(我想!)期望的结果:
program :
PRONOUN+
;
PRONOUN :
'i' | 'me' | 'my' | 'mine'
| 'you' | 'your'| 'yours'| 'yourself'
| 'he' | 'she' | 'it' | 'his' | 'hers' | 'its' | 'him' | 'her' | 'himself' | 'herself'
| 'we' | 'us' | 'our' | 'ours'
| 'yourselves'
| 'they'| 'them'| 'their'| 'theirs' | 'themselves'
;
WS : ' ' { $channel = HIDDEN; };
WORD : ('A'..'Z'|'a'..'z')+ { $channel = HIDDEN; };
在AntlWorks中,一个示例“我踢了你”返回了树结构:program->[i,you]
我觉得有必要指出,Antlr从句子中去掉代词太过分了。考虑使用正则表达式。此语法不区分大小写。将单词扩展到除代词词典(如puncuation等)之外的所有内容可能有点乏味。需要对输入进行消毒
---编辑:响应第二个OP:
- 我修改了原始语法,以便于分析。新语法是:
grammar pfinder; options { backtrack=true; output = AST; } tokens { PROGRAM; } program : (WORD* p+=PRONOUN+ WORD*)* -> ^(PROGRAM $p*) ; PRONOUN : 'i' | 'me' | 'my' | 'mine' | 'you' | 'your'| 'yours'| 'yourself' | 'he' | 'she' | 'it' | 'his' | 'hers' | 'its' | 'him' | 'her' | 'himself' | 'herself' | 'we' | 'us' | 'our' | 'ours' | 'yourselves' | 'they'| 'them'| 'their'| 'theirs' | 'themselves' ; WS : ' ' { $channel = HIDDEN; }; WORD : ('A'..'Z'|'a'..'z')+;
- 现在需要回溯来解决解析器规则程序。也许有一个更好的方式来写它,不需要回溯,但这是第一件突然出现在我脑海中的事情
- 一个虚构的代词程序已经被定义来对代词进行分组
- 每个匹配的程序都被添加到Antlr var$p中,并在AST中根据假想规则重写
- 解释器代码现在可以使用CommonTree来收集匹配的代词
- 下面是用C#(我不懂Java)编写的,但我编写它的目的是让您能够阅读和理解它
static object[] ReadTokens( string text ) { ArrayList results = new ArrayList(); pfinderLexer Lexer = new pfinderLexer(new Antlr.Runtime.ANTLRStringStream(text)); pfinderParser Parser = new pfinderParser(new CommonTokenStream(Lexer)); // syntaxTree is imaginary token {PROGRAM}, // its children are the pronouns collected by $p in grammar. CommonTree syntaxTree = Parser.program().Tree as CommonTree; if ( syntaxTree == null ) return null; foreach ( object pronoun in syntaxTree.Children ) { results.Add(pronoun.ToString()); } return results.ToArray(); }
- 调用ReadTokens(“我踢了你和他们”)返回数组[“我”、“你”、“他们”]
如果你想对口语/书面语言进行某种程度的分析,你可以考虑使用某种自然语言处理工具。例如,将告诉您哪些元素是代词(以及动词、名词、副词和其他深奥的语法结构)。(THT是我唯一熟悉的这类工具,所以不要认为这是对惊人的特别认可)。我认为您需要在ANTLR中了解更多关于lexer规则的信息,lexer规则从大写字母开始,并为解析器将要查看的流生成标记。Lexer片段规则不会为流生成令牌,但会帮助其他Lexer规则生成令牌,请查看Lexer规则单词和字母(字母不是令牌,但会帮助单词创建令牌) 现在,当文本文本被放入解析器规则(规则名称将以小写字母开头)时,该文本文本文本也是lexer将识别和传递的有效标记(至少当您使用ANTLR时-我没有使用任何其他类似于ANTLR的工具来回答) 接下来我注意到的是,你的“s”和“代词”规则似乎是一样的。我注释掉了“s”规则,把所有的东西都放进了“代词”规则中 最后一件事是学习如何把动作放到语法中,你可以在“s”规则中设置返回值。我让代词规则返回一个字符串值,这样,如果您想在“句子”规则中执行操作,就可以轻松完成“-I代词”注释/回答 现在,因为我不知道你的确切结果是什么,我玩了你的语法,做了一些轻微的修改和重组(将我认为是解析器规则的部分移到顶部,将所有lexer规则保留在底部),并采取了一些行动,我认为这些行动将向你展示你需要的东西。此外,可能有几种不同的方法来实现这一点,我认为我的解决方案对于您可能想要的任何结果都不是完美的,但以下是我在AntlWorks工作时得到的一个语法:
grammar pfinder;
options {
language = Java;
}
sentence
: ((words | pronoun) SPACE)* ((words | pronoun) ('.' | '?'))
;
words
: WORDS {System.out.println($text);};
pronoun returns [String value]
: sfirst {$value = $sfirst.value; System.out.println($sfirst.text + '(' + $sfirst.value + ')');}
| ssecond {$value = $ssecond.value; System.out.println($ssecond.text + '(' + $ssecond.value + ')');}
| sthird {$value = $sthird.value; System.out.println($sthird.text + '(' + $sthird.value + ')');}
| pfirst {$value = $pfirst.value; System.out.println($pfirst.text + '(' + $pfirst.value + ')');}
| psecond {$value = $psecond.value; System.out.println($psecond.text + '(' + $psecond.value + ')');}
| pthird{$value = $pthird.value; System.out.println($pthird.text + '(' + $pthird.value + ')');};
//s returns [String value]
// : exp=sfirst {$value = "s1";}
// | exp=ssecond {$value = "s2";}
// | exp=sthird {$value = "s3";}
// | exp=pfirst {$value = "p1";}
// | exp=psecond {$value = "p2";}
// | exp=pthird {$value = "p3";}
// ;
sfirst returns [String value] : ('i' | 'me' | 'my' | 'mine') {$value = "s1";};
ssecond returns [String value] : ('you' | 'your'| 'yours'| 'yourself') {$value = "s2";};
sthird returns [String value] : ('he' | 'she' | 'it' | 'his' | 'hers' | 'its' | 'him' | 'her' | 'himself' | 'herself') {$value = "s3";};
pfirst returns [String value] : ('we' | 'us' | 'our' | 'ours') {$value = "p1";};
psecond returns [String value] : ('yourselves') {$value = "p2";};
pthird returns [String value] : ('they'| 'them'| 'their'| 'theirs' | 'themselves') {$value = "p3";};
WORDS : LETTER*;// {$channel=HIDDEN;};
SPACE : (' ')?;
fragment LETTER : ('a'..'z' | 'A'..'Z');
我认为最终的结果是,这个语法将告诉你如何完成你正在尝试做的事情,并且无论最终结果是什么,都需要修改
祝你好运
我想你只需要在考试课上换一行,
parser.define();
致:
语法分析器。句子()
您可能还需要更改语法中的其他一些内容:
空间:'';
句子:(单词|代词)(空格(单词|代词))*(‘.|’?’);//然后你可能需要在句子和单词/代词之间设置一条规则。谢谢。我不知道java代码可以在antlr中使用。另一个问题。如果我想展示一切,我能做到吗?因为在上面的代码中,当你输入“我踢了你”时,它会显示“i(s1)”,所以句子的其他部分被忽略。是否有一个循环或其他东西可以显示所有的句子,比如它会输出“i(s1)kicking you(s2)”或只是“i(s1)you(s2)”?如果你只得到第一个单词,那么你的控制程序中就会有一些东西。当我在AntlWorks中输入“我踢了你”时,它会显示:我(s1)踢了你(s2)在调试模式下,我必须一步一步地完成。你能不能给我看一下第二行的代词?我已经编辑了我的测试程序。我不知道为什么它只显示它在java测试类中找到的第一个代词,用parser.define()更改行;到语法分析器。句子();你应该把所有的单词都打印出来,并在代词后面加上“s#”字样。我没有做任何格式化,所以可以随意添加代码(在单独的行上打印每个单词之类的东西)。祝你好运。作为这个问题的结论,我将给你留下一些想法让你记住LEXER规则“每次正确匹配时创建一个令牌。”片段规则不创建任何标记。曾经它们被用作编写更好的词法规则的糖。它们不属于解析器规则。”“解析器规则”用于按特定顺序(“语法”)对标记进行分组,但它们解析为标记的“平面”列表。没有父母