加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-16 05:32:17 所属栏目:百科 来源:网络整理
导读:我正在编写一个非常基本的解析器(主要是为了更好地了解它们的工作原理),它将用户输入一些选择的几个单词,检测句子结构是OK还是Not OK,并输出结果.语法是: 句子: 名词动词 文章 句子连词句 连词: “和” “要么” “但” 名词: “鸟类” “鱼” “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 << "OKn";
            else
               cout << "not OKn";

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;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读