我有一个简单的语法,它可以逐节解析键值对。
<div class="form-row p-3">
<label for="existing_user_list_id" class="col-12 col-sm-4 col-form-label">Select already existing list</label>
<div class="col-12 col-sm-8">
<v-select
v-model="selection_existing_user_list_id"
data-vv-name="selection_existing_user_list_id"
:options="userListsByUserIdArray"
v-validate="''"
id="existing_user_list_id"
name="existing_user_list_id"
class="form-control editable_field"
placeholder="Select existing user list"
v-on:input="onChangeSelectionExistingUserListId($event);"
></v-select>
<span v-show="vueErrorsList.has('existing_user_list_id')" class="text-danger">{{ vueErrorsList.first('existing_user_list_id') }}</span>
</div>
</div>
<div class="form-row p-1 m-1 ml-4">
<strong>OR</strong>
</div>
<div class="form-row p-2`">
<label for="new_user_list_title" class="col-12 col-sm-4 col-form-label">Create a new list</label>
<div class="col-12 col-sm-8">
<input class="form-control" value="" id="new_user_list_title" v-model="new_user_list_title" @change="onChangeBewUserListTitle($event);">
<span v-show="vueErrorsList.has('title')" class="text-danger">{{ vueErrorsList.first('title') }}</span>
</div>
</div>
我的语法是:
import { Validator } from 'vee-validate';
Validator.extend('new_user_list_title', {
getMessage: field => 'The ' + field + ' value is not a valid new_user_list_title.',
validate: value => false // for simplicity I try to raise error always
// validate: value => value.length == 0 && selection_existing_user_list_id == null
})
但是,语法在使用Earley解析器而不是lalr解析器时有效。
具有以下代码:
k1:1
k2:x
k3:3
k4:4
earley解析器给我有效的结果。
start: section (_sep section)*
_sep: _NEWLINE _NEWLINE+
section: item (_NEWLINE item)*
item: NAME ":" VALUE
_NEWLINE: /\r?\n[\t ]*/
VALUE: /\w+/
NAME: /\w+/
但是lalr解析器没有
from lark import Lark
import logging
from pathlib import Path
logging.basicConfig(level=logging.DEBUG)
my_grammar = Path("my_grammar.lark").read_text()
print(my_grammar)
early = Lark(my_grammar, debug=True)
print(my_grammar)
lalr = Lark(my_grammar, parser='lalr', debug=True)
text = """
k1:1
k2:x
k3:3
k4:4
"""
print(text.strip())
print(early.parse(text.strip()).pretty())
print(lalr.parse(text.strip()).pretty())
PS:问题出在_NEWLINE。
Lark-parser语法配置语法文件中的词法分析器和解析器。在我上面的语法中,一行将被标记为_NEWLINE。多个新行将被标记为_NEWLINE .. _NEWLINE。它混淆了解析器。
将start
section
item
k1
1
item
k2
x
section
item
k3
3
item
k4
4
更改为lark.exceptions.UnexpectedCharacters: No terminal defined for '
' at line 3 col 1
^
Expecting: {'NAME'}
。多行将被标记为一个标记。并且lalr(1)解析器可以顺利进行处理。
在我开始工作时。仍然对早期的解析器如何正确感到好奇。