简单的语法检查器程序-最佳数据结构

Simple grammar checker program - optimal data structure

本文关键字:最佳 数据结构 程序 语法 检查 简单      更新时间:2023-09-26

我想为英语创建一个简单的游戏,检查某人的句子。他们能够使用单词库中的一组固定单词来构建句子。

"银行"这个词可能是一些混乱的东西,比如:

[want, eat, I, hi, to]

然后他们会按照正确的顺序造句:

hi I want to eat.

我在英语SO上问了这个问题,因为它最初涉及语法问题——这个问题已经演变成了一个更像数据结构的问题。你可以在这个链接上阅读更多关于它的信息。我最初的想法是用一套通用的英语规则来检查句子语法,似乎很快就会变得过于复杂。建议我只使用硬编码检查进行匹配,如下所示。

在我进一步定义这些检查之前,我想知道是否有更好的数据结构/方法可以用于检查语法。

  if (input === the_answer) {
    msg = correct!
  } else {
    msg = 'Try again: ' + this.grammarRules(input, the_answer)); 
  }
Language_System.prototype.grammarRules = function(input, answer) {
   var grammar_hints = {
     quest1 : {
       task1 : [
         'The subject, Bob, needs to be first',
         'The phrase is Hello there'
       ]
     } 
   };
   var grammar_rules = {
     quest1 : {
       task1 : function (input, answer) {
         var error = -1;
         if (input[0] !== answer[0]) {
           error = 0;
         } else if (input.indexOf('hello') > input.indexOf('there')) {
           error = 1;
         }
         return grammar_hints.quest1.task1[error];
       }
     }
  };
  return grammar_rules.Lee.quest1.task1(input, answer);    
};

如果您考虑一种更具声明性的方法,会容易得多:-定义标准quest结构-定义具有通用输入格式的标准task结构-定义通用验证器并重用它们

您从grammar_hints对象开始就走上了正确的道路,但实际上我会把描述一个任务的所有属性都放在同一个对象中。

建议:

var quests = [
    {
        name: 'Quest 1',
        tasks: [
            {
                name: 'Task 1',
                solution: 'hi I want to eat',
                validators: [
                    validators.first('hi'),
                    validators.verbAfterNoun('want', 'I'),
                ]
            }
        ],
    },
];

您将能够在多个任务中重用许多验证器,因此您希望它们尽可能通用,这里有一个例子:

var validators = {
    first: function (input, term) {
        if (input[0] !== term) {
            return 'The sentence needs to start with: ' + term;
        }
    },
    verbAfterNoun: function (input, verb, noun) {
        if (input.indexOf(verb) < input.indexOf(noun)) {
            return 'The verb, ' + verb + ', needs to come after the noun ' + noun;
        }
    }
};

现在,因为您想要一个声明性格式(我实际使用它们的输入初始化验证器,并将结果传递到validators数组中),所以我们需要一个验证器工厂,它接受一个通用验证器,并返回一个仅可用于输入的助手方法。这将帮助我们,这样我们的测试框架就不需要知道有多少输入要传递给每个验证器回调

// This is a factory method that applies the given callback (with the given arguments)
function makeValidator (fn) {
    return function inputFN () {
        var args = [].slice.call(arguments);
        return function validate (input) {
            return fn.apply(null, [input].concat(args));
        }
    }
}
// Apply the makeValidator() method on all the validators
for (var key in validators) {
    validators[key] = makeValidator(validators[key]);
}

最后,我们还想要一种根据输入检查任务的标准方法:

// This method provides the generic validation framework for any task given any input
function validate (task, input) {
    var wordList = input.split(' ');
    if (input === task.solution) return {success: true, errors: []};
    var errors = [];
    task.validators.forEach(function (fn) {
        var error = fn(wordList);
        if (error) errors.push(error);
    });
    return {success: false, errors: errors};
}

还有一些例子:

var task = quests[0].tasks[0];
console.log(validate(task, 'hi I want to eat'));
console.log(validate(task, 'I want to eat hi'));
console.log(validate(task, 'hi want I to eat'));
console.log(validate(task, 'want I to eat hi'));

综合起来:

// This is a factory method that applies the given callback (with the given arguments)
function makeValidator (fn) {
    return function inputFN () {
        var args = [].slice.call(arguments);
        return function validate (input) {
            return fn.apply(null, [input].concat(args));
        }
    }
}
var validators = {
    first: function (input, term) {
        if (input[0] !== term) {
            return 'The sentence needs to start with: ' + term;
        }
    },
    verbAfterNoun: function (input, verb, noun) {
        if (input.indexOf(verb) < input.indexOf(noun)) {
            return 'The verb, ' + verb + ', needs to come after the noun ' + noun;
        }
    }
};
// Apply the makeValidator() method on all the validators
for (var key in validators) {
    validators[key] = makeValidator(validators[key]);
}
var quests = [
    {
        name: 'Quest 1',
        tasks: [
            {
                name: 'Task 1',
                solution: 'hi I want to eat',
                validators: [
                    validators.first('hi'),
                    validators.verbAfterNoun('want', 'I'),
                ]
            }
        ],
    },
];
// This method provides the generic validation framework for any task given any input
function validate (task, input) {
    var wordList = input.split(' ');
    if (input === task.solution) return {success: true, errors: []};
    var errors = [];
    task.validators.forEach(function (fn) {
        var error = fn(wordList);
        if (error) errors.push(error);
    });
    return {success: false, errors: errors};
}
function printTask (input) {
    var task = quests[0].tasks[0];
    var result = validate(task, input);
    document.body.innerHTML += '<div><b>checking:</b> ' + input + '<pre>' + JSON.stringify(result, null, 4) + '</pre><hr />';
}
// Lets look at some examples
printTask('I want to eat hi');
printTask('hi want I to eat');
printTask('want I to eat hi');
printTask('hi I want to eat');