微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – 非常基本的英文语法解析器

我正在编写一个非常基本的解析器(主要是为了更好地了解它们的工作原理),它将用户输入一些选择的几个单词,检测句子结构是OK还是Not OK,并输出结果.语法是:

句子:
名词动词

文章

句子连词句

连词:
“和”
“要么”
“但”

名词:
“鸟类”
“鱼”
“C ”

动词:
“规则”
“飞”
“游泳”

文章
“中的”

写这个语法很简单.它正在实施给我一些麻烦的代码.我的psuedocode为它是:

main()
get user input (string words;)
while loop (cin >> words)
call sentence()
end main()

sentence()
call noun()
if noun() call verb() (if verb is true return "OK" ???)(else "not ok"???)
else if not noun() call article()
                if article() call sentence() (if sentence is true "OK"???)(else "not"?)
else if not noun() call conjunction()
                   if sentence() conjunction() sentence() - no idea how to implement
                                                             return "OK"
else "not ok"

所以有我非常草率的伪装代码.我有几个关于实施的问题.

>对于单词功能(名词,动词等),我应该如何检查它们是否为真? (如在检查用户的输入是否有鸟,鱼,飞,游泳等)
>我应该如何处理连接调用输出
>我应该处理主函数调用函数输出吗?
>如果我的伪代码完全错误,上述问题都不重要.基础知识有什么问题吗?

另外值得注意的是,我正在第6章编程:练习和原则使用C,所以我更喜欢使用我已经学习的语言语法,所以属于高级编程类的任何东西都可能不是“ t非常有帮助(练习中具体说不要使用令牌,所以算出来).

提前致谢

最后编辑:在这本书的公共小组中,我问了同样的问题,Bjarne Stroustrup回答说他把练习解决方案放在了网上.他基本上将输入读入了句子函数,并使用if语句返回true或false.不过,他没有使用文章,所以我的复杂性更大.我猜,如果我从这个练习中学到了什么,那么在处理很多用户输入时,标记化是关键的(从目前为止我所知道的).现在我的代码是.我可以稍后回来,因为它还是非常漂亮的,基本上只有在句子好的时候才能返回,不能处理像(名词,连词,句子)这样的东西,但现在我正在继续.

#include "std_lib_facilities.h"

bool article(string words)
{
               if (words == "the")
               return true;
               else return false;        
}

bool verb(string words)
{
               if (words == "rules" || words == "fly" || words == "swim")
               return true;
               else return false;                   
}

bool noun(string words)
{
               if (words == "birds" || words == "fish" || words == "c++")
               return true;
               else return false;                   
}

bool conjunction(string words)
{
              if (words == "and" || words == "but" || words == "or")
              return true;
              else return false;                  
}

bool sentence()
{
string w1;
string w2;
string w3;
string w4;

cin >> w1;
if (!noun(w1) && !article(w1)) return false; // grammar of IFS!

cin >> w2;
if (noun(w1) && !verb(w2)) return false;
if (article(w1) && !noun(w2)) return false;

cin >> w3;
if (noun(w1) && verb(w2) && (w3 == ".")) return true;
if (verb(w2) && !conjunction(w3)) return false;
if (noun(w2) && !verb(w3)) return false;
if (conjunction(w3)) return sentence();

cin >> w4;
if (article(w1) && noun(w2) && verb(w3) && (w4 == ".")) return true;
if (!conjunction(w4)) return false;
if (conjunction(w4)) return sentence();
}


int main()
{                                   
cout << "Enter sentence. Use space then period to end.\n";
            bool test = sentence();
            if (test)
               cout << "OK\n";
            else
               cout << "not OK\n";

keep_window_open();
}

解决方法

好.如果你真的想用手做:-(

这个问题有两个部分:

>词汇分析
>句法分析.
>我们可以忽略Symantic分析,因为这就是为什么.

首先,您将输入流标记为可共鸣令牌.词语将是一个obvios选择,但这将为句法阶段留下大量的工作.所以我会把你的话分成以下类型(Conjunction,Noun,Verb,Article),然后写一个词法分析器来返回正确的Lexems.

Lexer.cpp
enum Lexeme { END,Conjunction,Article };
Lexem getNextLexme(std::istream in)
{
    std::string word;
    in >> word;

    if (!in) {return END;}

         if (word == "and")   return Conjunction;
    else if (word == "birds") return Noun;
    else if (word == "fly")   return Verb;
    else if (word == "the")   return Article;

    ... etc
}

所以现在你可以用简化的标记流来描述你的句法解析器.

bool ParseSentence(std::istream in)
{
    Lexeme token = getNextLexme(in);
    switch(token)
    {
        case Noun:    if (!parseVerb(in))
                      {    return false;
                      }
                      return parseConjunctionorEnd(in);
        case Article: return ParseSentence();
        case END:     return true;
    }
}
bool parseVerb(std::istream in)
{
    Lexeme token = getNextLexeme(in);
    if (token != Verb) { /*ERROR*/ return false;}
    return true;
 }
 // etc

语法分析的其他选项是构建状态表.但这涉及手分析语法和确定各州.这应该只是用最简单的语法表达,任何比这里大的东西应该留给可以自动产生状态表的工具.

所以假设我在下面的原始帖子中定义了这个语法:
并希望我得到正确的,因为我不是一个充气工具:-)

State 1:   Start <nothing Happened>
               Article -> State 2
               Noun -> State 3
               Otherwise Error
State 2:   Seen Article.
               Noun -> State 3
               Otherwise Error
State 3:   Seen Noun  in Sentence.
               Verb -> State 4
               Otherwise Error
State 4:   Seen Noun Verb
               End -> State 5
               Conjunction -> State 1
State 5:   Finished:

State 0:   Error State.


int stateTable[][]    // CurrentState,CurrentObject
           = {/*State 0: Error State:*/{},// END,Article 
              /*State 1: Start*/       {  0,3,2},/*State 2: Article*/     {  0,0},/*State 3: Noun*/        {  0,4,/*State 4: Noun Verb*/   {  5,1,/*State 5: End*/         {}
             };

bool parseSentence(std::iostream& in)
{
    int currentState = 1;
    while((currentState != 0) && (currentState != 5))
    {
        int token = getNextLexme(in);
        currentState = stateTable[currentState][token];
    }
    return currentState == 5;
}

原文地址:https://www.jb51.cc/c/114446.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐