{:error, {:undefined, :standard_syntax_parser, ['syntax error before: ', []]}}
{:error, {:undefined, :standard_syntax_parser, ['syntax error before: ', []]}}
所以我正在尝试使用 yecc。
Terminals string string_delimeter.
Nonterminals value string_content.
Rootsymbol value.
value -> string : extract_value('').
value -> string_delimeter string_content string_delimeter : ''.
string_content -> value string_content : ['' | ''].
string_content -> value : ''.
Erlang code.
extract_value({_, Value}) -> Value.
对于输入:
[string_delimeter: '\'', string: 'test', string_delimeter: '\'']
我明白了
{:error, {:undefined, :standard_syntax_parser, ['syntax error before: ', []]}}
如果我删除 string_content 周围的任何(左或右)string_delimeter:
value -> string_delimeter string_content string_delimeter : ''.
value -> string_delimeter string_content : ''.
为
[string_delimeter: '\'', string: 'test']
它returns
{:ok, 'test'}
我不太理解这种行为,问题出在哪里?
For the input:
[string_delimeter: '\'', string: 'test', string_delimeter: '\'']
我觉得你很困惑(或者也许是我!)。 yecc
需要一个标记列表,其中标记是一个 2 或 3 元素元组。来自 yecc docs:
The user should implement a scanner that segments the input text, and
turns it into one or more lists of tokens. Each token should be a
tuple containing information about syntactic category, position in the
text (e.g. line number), and the actual terminal symbol found in the
text: {Category, LineNumber, Symbol}
.
If a terminal symbol is the only member of a category, and the symbol
name is identical to the category name, the token format may be
{Symbol, LineNumber}
...
这是 yecc 期望的示例:
[
{'[',1},
{atom,1,foo},
{',',1},
{'[',1},
{int,1,1},
{']',1},
{',',1},
{'[',1},
{atom,1,bar},
{',',1},
{'[',1},
{int,1,2},
{',',1},
{int,1,3},
{']',1},
{']',1},
{']',1}
]
您可以使用 leex
实现这样的扫描器,然后将输出提供给 yecc
解析器。
忠告:你永远不应该 post 一个描述你如何 运行 你的代码的问题——这只是在浪费大量时间。而是复制并粘贴您 运行 的确切命令以及这些命令产生的输出。您只需要说:
- This is what I tried:
[Your code here]
- Here is the output:
[all commands you ran and the output here]
- This is the output I expect/want, or Wtf??!! is going on.
[expected/desired output here]
啊,好的。您正在使用 elixir
,即使您问题上的标签说您正在使用 erlang
。我可以获得一个更简单的解析器版本:
string_parser.yrl:
Nonterminals the_string content.
Terminals '\'' string.
Rootsymbol the_string.
the_string -> '\'' content '\'' : ''.
%I guess the atom :string has to be the first element of the tuple
%returned by '' in previous line:
content -> string : extract_value('')
Erlang code.
extract_value({_, _, Value}) -> Value.
在 iex 中:
iex(1)> :yecc.file('string_parser.yrl')
{:ok, 'string_parser.erl'}
iex(2)> c("string_parser.erl")
[:string_parser]
iex(3)> :string_parser.parse([{:"'", 1}, {:string, 1, "hello"}, {:"'", 1}])
{:ok, "hello"}
但是,我无法使用递归定义。
好的,我越来越近了:
string_parser.yrl:
Nonterminals string interior_strings interior_string.
Terminals left_delim right_delim result.
Rootsymbol string.
string -> left_delim interior_strings right_delim : ''.
string -> left_delim right_delim : "".
interior_strings -> interior_string : [''].
interior_strings -> interior_string interior_strings : ['' | ''].
interior_string -> result : extract_value('').
interior_string -> string : ''.
Erlang code.
extract_value({_, _, Value}) -> Value.
在 iex 中:
iex(49)> :yecc.file('string_parser.yrl')
{:ok, 'string_parser.erl'}
iex(50)> c("string_parser.erl")
[:string_parser]
iex(51)> :string_parser.parse([{:left_delim, 1}, {:result, 1, "hello"}, {:left_delim, 1}, {:result, 1, "goodbye"}, {:right_delim, 1}, {:right_delim, 1}])
{:ok, ["hello", ["goodbye"]]}
iex(53)>
至此,我不知道为什么该死的括号在"goodbye"
周围。
成功!
string_parser.yrl:
Nonterminals string interior_strings interior_string.
Terminals left_delim right_delim result.
Rootsymbol string.
string -> left_delim interior_strings right_delim : ''.
string -> left_delim right_delim : "".
interior_strings -> left_delim interior_string right_delim: [''].
interior_strings -> interior_string interior_strings : ['' | ''].
interior_string -> result : extract_value('').
interior_string -> string : ''.
Erlang code.
extract_value({_, _, Value}) -> Value.
在 iex 中:
iex(53)> :yecc.file('string_parser.yrl')
{:ok, 'string_parser.erl'}
iex(54)> c("string_parser.erl")
[:string_parser]
iex(55)> :string_parser.parse([{:left_delim, 1}, {:result, 1, "hello"}, {:left_delim, 1}, {:result, 1, "goodbye"}, {:right_delim, 1}, {:right_delim, 1}])
{:ok, ["hello", "goodbye"]}
我仍然无法开始工作的一件事是,如果我明确指定 '\''
作为分隔符:
Nonterminals string interior_strings interior_string.
Terminals '\'' result.
Rootsymbol string.
Endsymbol '$end'.
string -> '\'' interior_strings '\'' : ''.
string -> '\'' '\'' : "".
interior_strings -> '\'' interior_string '\'': [''].
interior_strings -> interior_string interior_strings : ['' | ''].
interior_string -> result : extract_value('').
interior_string -> string : ''.
Erlang code.
extract_value({_, _, Value}) -> Value.
在 iex 中:
iex(3)> :string_parser.parse([{:"'", 1}, {:result, 1, "hello"},
{:"'", 1}, {:result, 1, "goodbye"}, {:"'", 1}, {:"'", 1}, {:"$end", 1}])
{:error, {1, :string_parser, ['syntax error before: ', []]}}
处理如此可怕的错误消息太令人沮丧了。空列表 []
之前有语法错误??!令牌列表中的空列表在哪里?
我认为添加最后一个元组:{:"$end", 1}
可能有效——但没有成功。同样的错误。
如果我使用文字括号作为分隔符,我可以让 string_parser 工作:
string_parser.yrl:
Nonterminals string interior_strings interior_string.
Terminals '[' ']' content.
Rootsymbol string.
string -> '[' interior_strings ']' : ''.
string -> '[' ']' : "".
interior_strings -> '[' interior_string ']' : [''].
interior_strings -> interior_string interior_strings : ['' | ''].
interior_string -> content : extract_content('').
interior_string -> string : ''.
Erlang code.
extract_content({_, _, Content}) -> Content.
在 iex 中:
iex(11)> :yecc.file('string_parser.yrl')
{:ok, 'string_parser.erl'}
iex(12)> c("string_parser.erl")
[:string_parser]
iex(13)> :string_parser.parse([{:"[", 1}, {:content, 1, "hello"}, {:"[", 1}, {:content, 1, "goodbye"}, {:"]", 1}, {:"]", 1}])
{:ok, ["hello", "goodbye"]}
iex(14)>
我试着用erlang写了一个string_parser,我得到了同样的错误。 .yrl 文件不是 erlang 语法,所以无论什么解析 .yrl 文件似乎都无法解析单引号原子:'\''
.
我没有弄清楚为什么这是 yecc 中的问题:
token_1 token_2 token_1
我真的希望我知道,但我有办法解决这个问题:
Terminals string string_delimeter whitespace.
Nonterminals value string_content.
Rootsymbol value.
value -> string : extract_value('').
value -> string_delimeter string_content : ''.
string_content -> string_content string_delimeter : ''.
string_content -> value whitespace string_content : ['' | ''].
string_content -> value : [''].
Erlang code.
extract_value({_, Value}) -> Value.
所以我正在尝试使用 yecc。
Terminals string string_delimeter.
Nonterminals value string_content.
Rootsymbol value.
value -> string : extract_value('').
value -> string_delimeter string_content string_delimeter : ''.
string_content -> value string_content : ['' | ''].
string_content -> value : ''.
Erlang code.
extract_value({_, Value}) -> Value.
对于输入:
[string_delimeter: '\'', string: 'test', string_delimeter: '\'']
我明白了
{:error, {:undefined, :standard_syntax_parser, ['syntax error before: ', []]}}
如果我删除 string_content 周围的任何(左或右)string_delimeter:
value -> string_delimeter string_content string_delimeter : ''.
value -> string_delimeter string_content : ''.
为
[string_delimeter: '\'', string: 'test']
它returns
{:ok, 'test'}
我不太理解这种行为,问题出在哪里?
For the input:
[string_delimeter: '\'', string: 'test', string_delimeter: '\'']
我觉得你很困惑(或者也许是我!)。 yecc
需要一个标记列表,其中标记是一个 2 或 3 元素元组。来自 yecc docs:
The user should implement a scanner that segments the input text, and turns it into one or more lists of tokens. Each token should be a tuple containing information about syntactic category, position in the text (e.g. line number), and the actual terminal symbol found in the text:
{Category, LineNumber, Symbol}
.If a terminal symbol is the only member of a category, and the symbol name is identical to the category name, the token format may be
{Symbol, LineNumber}
...
这是 yecc 期望的示例:
[
{'[',1},
{atom,1,foo},
{',',1},
{'[',1},
{int,1,1},
{']',1},
{',',1},
{'[',1},
{atom,1,bar},
{',',1},
{'[',1},
{int,1,2},
{',',1},
{int,1,3},
{']',1},
{']',1},
{']',1}
]
您可以使用 leex
实现这样的扫描器,然后将输出提供给 yecc
解析器。
忠告:你永远不应该 post 一个描述你如何 运行 你的代码的问题——这只是在浪费大量时间。而是复制并粘贴您 运行 的确切命令以及这些命令产生的输出。您只需要说:
- This is what I tried:
[Your code here]
- Here is the output:
[all commands you ran and the output here]
- This is the output I expect/want, or Wtf??!! is going on.
[expected/desired output here]
啊,好的。您正在使用 elixir
,即使您问题上的标签说您正在使用 erlang
。我可以获得一个更简单的解析器版本:
string_parser.yrl:
Nonterminals the_string content.
Terminals '\'' string.
Rootsymbol the_string.
the_string -> '\'' content '\'' : ''.
%I guess the atom :string has to be the first element of the tuple
%returned by '' in previous line:
content -> string : extract_value('')
Erlang code.
extract_value({_, _, Value}) -> Value.
在 iex 中:
iex(1)> :yecc.file('string_parser.yrl')
{:ok, 'string_parser.erl'}
iex(2)> c("string_parser.erl")
[:string_parser]
iex(3)> :string_parser.parse([{:"'", 1}, {:string, 1, "hello"}, {:"'", 1}])
{:ok, "hello"}
但是,我无法使用递归定义。
好的,我越来越近了:
string_parser.yrl:
Nonterminals string interior_strings interior_string.
Terminals left_delim right_delim result.
Rootsymbol string.
string -> left_delim interior_strings right_delim : ''.
string -> left_delim right_delim : "".
interior_strings -> interior_string : [''].
interior_strings -> interior_string interior_strings : ['' | ''].
interior_string -> result : extract_value('').
interior_string -> string : ''.
Erlang code.
extract_value({_, _, Value}) -> Value.
在 iex 中:
iex(49)> :yecc.file('string_parser.yrl')
{:ok, 'string_parser.erl'}
iex(50)> c("string_parser.erl")
[:string_parser]
iex(51)> :string_parser.parse([{:left_delim, 1}, {:result, 1, "hello"}, {:left_delim, 1}, {:result, 1, "goodbye"}, {:right_delim, 1}, {:right_delim, 1}])
{:ok, ["hello", ["goodbye"]]}
iex(53)>
至此,我不知道为什么该死的括号在"goodbye"
周围。
成功!
string_parser.yrl:
Nonterminals string interior_strings interior_string.
Terminals left_delim right_delim result.
Rootsymbol string.
string -> left_delim interior_strings right_delim : ''.
string -> left_delim right_delim : "".
interior_strings -> left_delim interior_string right_delim: [''].
interior_strings -> interior_string interior_strings : ['' | ''].
interior_string -> result : extract_value('').
interior_string -> string : ''.
Erlang code.
extract_value({_, _, Value}) -> Value.
在 iex 中:
iex(53)> :yecc.file('string_parser.yrl')
{:ok, 'string_parser.erl'}
iex(54)> c("string_parser.erl")
[:string_parser]
iex(55)> :string_parser.parse([{:left_delim, 1}, {:result, 1, "hello"}, {:left_delim, 1}, {:result, 1, "goodbye"}, {:right_delim, 1}, {:right_delim, 1}])
{:ok, ["hello", "goodbye"]}
我仍然无法开始工作的一件事是,如果我明确指定 '\''
作为分隔符:
Nonterminals string interior_strings interior_string.
Terminals '\'' result.
Rootsymbol string.
Endsymbol '$end'.
string -> '\'' interior_strings '\'' : ''.
string -> '\'' '\'' : "".
interior_strings -> '\'' interior_string '\'': [''].
interior_strings -> interior_string interior_strings : ['' | ''].
interior_string -> result : extract_value('').
interior_string -> string : ''.
Erlang code.
extract_value({_, _, Value}) -> Value.
在 iex 中:
iex(3)> :string_parser.parse([{:"'", 1}, {:result, 1, "hello"},
{:"'", 1}, {:result, 1, "goodbye"}, {:"'", 1}, {:"'", 1}, {:"$end", 1}])
{:error, {1, :string_parser, ['syntax error before: ', []]}}
处理如此可怕的错误消息太令人沮丧了。空列表 []
之前有语法错误??!令牌列表中的空列表在哪里?
我认为添加最后一个元组:{:"$end", 1}
可能有效——但没有成功。同样的错误。
如果我使用文字括号作为分隔符,我可以让 string_parser 工作:
string_parser.yrl:
Nonterminals string interior_strings interior_string.
Terminals '[' ']' content.
Rootsymbol string.
string -> '[' interior_strings ']' : ''.
string -> '[' ']' : "".
interior_strings -> '[' interior_string ']' : [''].
interior_strings -> interior_string interior_strings : ['' | ''].
interior_string -> content : extract_content('').
interior_string -> string : ''.
Erlang code.
extract_content({_, _, Content}) -> Content.
在 iex 中:
iex(11)> :yecc.file('string_parser.yrl')
{:ok, 'string_parser.erl'}
iex(12)> c("string_parser.erl")
[:string_parser]
iex(13)> :string_parser.parse([{:"[", 1}, {:content, 1, "hello"}, {:"[", 1}, {:content, 1, "goodbye"}, {:"]", 1}, {:"]", 1}])
{:ok, ["hello", "goodbye"]}
iex(14)>
我试着用erlang写了一个string_parser,我得到了同样的错误。 .yrl 文件不是 erlang 语法,所以无论什么解析 .yrl 文件似乎都无法解析单引号原子:'\''
.
我没有弄清楚为什么这是 yecc 中的问题: token_1 token_2 token_1 我真的希望我知道,但我有办法解决这个问题:
Terminals string string_delimeter whitespace.
Nonterminals value string_content.
Rootsymbol value.
value -> string : extract_value('').
value -> string_delimeter string_content : ''.
string_content -> string_content string_delimeter : ''.
string_content -> value whitespace string_content : ['' | ''].
string_content -> value : [''].
Erlang code.
extract_value({_, Value}) -> Value.