我目前正在编写类似Visual Basic的LALR(1)语法,面对这种特殊的转移/减少冲突,我不知道如何正确解决它。
语法中有问题的部分是(请参阅编辑1 和编辑2 以获得澄清):
Expression
: IndexExpression
| /* other expressions */
IndexExpression
: MemberExpression
| MemberExpression '(' ArgumentList ')'
MemberExpression
: ParenthesizedExpression
| Identifier
ParenthesizedExpression
: '(' Expression ')'
ArgumentList
: Expression
| Expression ',' ArgumentList
| ',' ArgumentList
转移/减少冲突是这样的:
State 109
237 ParenthesizedExpression: '(' Expression ')' .
$default reduce using rule 237 (ParenthesizedExpression)
...
State 295
231 IndexExpression: MemberExpression '(' . ArgumentList ')'
237 ParenthesizedExpression: '(' . Expression ')'
...
Expression go to state 352
...
State 352
182 ArgumentList: Expression .
183 | Expression . ',' ArgumentList
237 ParenthesizedExpression: '(' Expression . ')'
...
')' shift, and go to state 109
')' [reduce using rule 182 (ArgumentList)]
换句话说,解析器在面对括号括起来的表达式时是不确定的,无论是带有单个表达式的 ArgumentList 还是 ParenthesizedExpression 。
有没有办法解决这个冲突,同时将语法保持为LALR(1)?
谢谢。
编辑1:
/ * 表达式中的其他表达式* /实际上不是空表达式,我只是为了简洁而以这种方式编写它。实际上它有其他替代表达式:
Expression
: IndexExpression
| Expression '+' Expression
| ...
编辑2:
以下是@rici指出的语法的其他部分可能有问题(特别是声明的第一个右手规则):
Statement
: MemberExpression ArgumentList
| MemberExpression '=' Expression
| MemberExpression '(' ArgumentList ')' '=' Expression
| ...
答案 0 :(得分:2)
错误是因为class GMap extends React.Component {
state = { zoom: 10 };
static propTypes() {
initialCenter: React.PropTypes.objectOf(React.PropTypes.number).isRequired
}
render() {
return <div className="GMap">
<div className='UpdatedText'>
<p>Current Zoom: { this.state.zoom }</p>
</div>
<div className='GMap-canvas' ref="mapCanvas">
</div>
</div>
}
componentDidMount() {
// create the map, marker and infoWindow after the component has
// been rendered because we need to manipulate the DOM for Google =(
this.map = this.createMap()
this.marker = this.createMarker()
this.infoWindow = this.createInfoWindow()
// have to define google maps event listeners here too
// because we can't add listeners on the map until its created
google.maps.event.addListener(this.map, 'zoom_changed', ()=> this.handleZoomChange())
}
// clean up event listeners when component unmounts
componentDidUnMount() {
google.maps.event.clearListeners(map, 'zoom_changed')
}
createMap() {
let mapOptions = {
zoom: this.state.zoom,
center: this.mapCenter()
}
return new google.maps.Map(this.refs.mapCanvas, mapOptions)
}
mapCenter() {
return new google.maps.LatLng(
this.props.initialCenter.lat,
this.props.initialCenter.lng
)
}
createMarker() {
const navLinks = [
{location: 'Bondi Beach', lat: -33.890542, long: 151.274856},
{location: 'Coogee Beach', lat: -33.923036, long: 151.259052},
{location: 'Cronulla Beach', lat: -34.028249, long: 151.157507},
{location: 'Manly Beach', lat: -33.80010128657071, long: 151.28747820854187}
];
navLinks.map((b, i) => {
return new google.maps.Marker({
position: new google.maps.LatLng(b.lat, b.long),
map: this.map
})
console.log(b.long)
})
}
createInfoWindow() {
let contentString = "<div class='InfoWindow'>I'm a Window that contains Info Yay</div>"
return new google.maps.InfoWindow({
map: this.map,
anchor: this.marker,
content: contentString
})
}
handleZoomChange() {
this.setState({
zoom: this.map.getZoom()
})
}
}
var initialCenter = { lng: -90.1056957, lat: 29.9717272 }
ReactDOM.render(<GMap initialCenter={initialCenter} />, document.getElementById('container'));
被允许为空,因为注释的规则为Expression
,并且假定它不为空。
以下显示使用/* other expressions */
导致两个等效规则的地方:
Expression
轮班/减少冲突的次数是ArgumentList
: Expression
| Expression ',' ArgumentList /* degenerates into "',' ArgumentList" */
| ',' ArgumentList
;
被引用的次数(一次在ArgumentList
,两次在IndexExpression
本身)
要删除冲突,请针对空ArgumentList
的情况修复ArgumentList
:
Expression
或确保ArgumentList
: Expression
| ArgumentList ',' Expression
;
永远不会为空(删除已注释的规则)。