2016-06-19 61 views
3

我正在嘗試編寫解析器,該解析器解析了int32_tdouble。 作爲第一次嘗試,我寫這個解析器:助推精神x3 int32 | double_無法解析雙重

const auto int_or_double = boost::spirit::x3::int32 | boost::spirit::x3::double_; 

我希望拿回boost::variant<int32_t, double> 解析器成功解析整數像12, 100, -42, 7但它無法解析像13.243, 42.7, 12.0 -10000.3

雙打這裏是一個活demo

爲什麼此解析器在雙打失敗?

回答

5

您的問題與this question非常相似。

當您的語法中首先出現整數解析器時,它是首選。對於輸入"12.9",解析器將解析"12.9的整數部分,即12,並將在.處停止。 live example

你要顛倒順序,因此雙解析器優於整數1:

const auto double_or_int = boost::spirit::x3::double_ | boost::spirit::x3::int32; 

這將現在"12.9"工作:live example

然而,由於雙解析器也解析整數,即使輸入爲"12",您也將始終得到雙精度值:live example

爲了防止這種情況,你需要一個嚴格的雙重解析器:

boost::spirit::x3::real_parser<double, boost::spirit::x3::strict_real_policies<double> > const double_ = {}; 

live example

+0

哇謝謝我不知道'strict_real_policies'模板 – Exagon

1

我不知道strict_real_policies或者,這聽起來很方便。

我以更直接的方式工作圍繞這個曾經像這樣:

(qi::int_ >> !lit('.') >> !lit('e') >> !lit('E')) | qi::float_ 

如果你看看在流程圖上http://www.json.org/ 你可以看到,這三個字符覆蓋所有的法律途徑,一個數字可能會導致解析爲一個浮點數。 (在我的特殊問題。)

+3

這種方法通常會工作,但在像[這一個](http://coliru.stacked-crooked .com/a/07be3ea0e2824259)它會失敗。如果你知道整數部分永遠不會丟失,我認爲'(int_ >>!char _(「。eE」))| float_'應該是等效的,並且(稍微)不太吵。 – llonesmiz

+3

這是忘記船長,所以它可能會變成'lexeme [int_ >>!char _(「。eE」)] | double_' – sehe

+0

@sehe:在我工作的語法中,我禁用了所有的船長。完整的規則實際上是'non_nil_value = true_ | false_ | (qi :: int_ >>!lit('。')>>!lit('e')>>!lit('E'))| qi :: float_ | tstring_ | lua_string_ |表;'。但是,一般來說,我猜'lexeme'應該參與其中。 –