由括号转换/减少LALR(1)冲突

时间:2017-02-23 00:01:43

标签: grammar bison yacc lalr

我目前正在编写类似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
    | ...

1 个答案:

答案 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 ; 永远不会为空(删除已注释的规则)。