Skip to content

Commit a9db2a7

Browse files
committed
Defines lr1 parsing table
1 parent c3fe9a0 commit a9db2a7

File tree

3 files changed

+89
-8
lines changed

3 files changed

+89
-8
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
from .entry import Entry
22
from .conflict import Conflict, ConflictType
3-
from .table import LR0ParsingTable, SLRParsingTable
3+
from .table import LR0ParsingTable, SLRParsingTable, LR1ParsingTable, ParsingTable

src/syntactes/parsing_table/table.py

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
1-
from typing import Iterable, Optional, TypeAlias
1+
from typing import Iterable, Optional, Protocol, TypeAlias
22

33
from syntactes import Grammar, Token
44
from syntactes._action import Action
5-
from syntactes._state import LR0State
5+
from syntactes._state import LR0State, LR1State, State
66
from syntactes.parsing_table import Conflict, Entry
77

88
Row: TypeAlias = dict[Token, list[Action]]
99

1010

11+
class ParsingTable(Protocol):
12+
rows: dict[State, Row]
13+
initial_state: State
14+
15+
@staticmethod
16+
def from_entries(entries: Iterable[Entry], grammar: Grammar) -> "ParsingTable": ...
17+
18+
def get(self, state: State) -> Optional[Row]: ...
19+
20+
def get_actions(self, state: State, token: Token) -> Optional[list[Action]]: ...
21+
1122
class LR0ParsingTable:
1223
"""
1324
Table that contains all the transitions from state to state with a symbol.
@@ -19,13 +30,11 @@ def __init__(self, grammar: Grammar) -> None:
1930
self._initial_state = None
2031

2132
@staticmethod
22-
def from_entries(
23-
entries: Iterable[Entry], tokens: Iterable[Token]
24-
) -> "LR0ParsingTable":
33+
def from_entries(entries: Iterable[Entry], grammar: Grammar) -> "LR0ParsingTable":
2534
"""
2635
Create a parsing table from the given entries.
2736
"""
28-
table = LR0ParsingTable(tokens)
37+
table = LR0ParsingTable(grammar)
2938
{table.add_entry(entry) for entry in entries}
3039
return table
3140

@@ -133,3 +142,46 @@ def from_entries(
133142

134143
def _header_str(self) -> str:
135144
return "SLR PARSING TABLE"
145+
146+
147+
class LR1ParsingTable(LR0ParsingTable):
148+
"""
149+
Table that contains all the transitions from state to state with a symbol.
150+
"""
151+
152+
def __init__(self, grammar: Grammar) -> None:
153+
self.rows: dict[LR1State, Row] = dict()
154+
self._grammar = grammar
155+
self._initial_state = None
156+
157+
@staticmethod
158+
def from_entries(
159+
entries: Iterable[Entry], tokens: Iterable[Token]
160+
) -> "LR1ParsingTable":
161+
"""
162+
Create a parsing table from the given entries.
163+
"""
164+
table = LR1ParsingTable(tokens)
165+
{table.add_entry(entry) for entry in entries}
166+
return table
167+
168+
@property
169+
def initial_state(self) -> LR1State:
170+
return self._initial_state
171+
172+
def get_actions(self, state: LR1State, token: Token) -> Optional[list[Action]]:
173+
"""
174+
Get the actions from state with given number with `token`.
175+
If there are no actions, returns None.
176+
"""
177+
return self.rows.get(state, {}).get(token, None)
178+
179+
def get(self, state: LR1State) -> Optional[Row]:
180+
"""
181+
Get the mapping of tokens to actions for the given state number.
182+
Returns None if the state is not found.
183+
"""
184+
return self.rows.get(state, None)
185+
186+
def _header_str(self) -> str:
187+
return "LR1 PARSING TABLE"

src/syntactes/tests/data.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from syntactes._action import Action
33
from syntactes._item import LR0Item, LR1Item
44
from syntactes._state import LR0State, LR1State
5-
from syntactes.parsing_table import Entry, LR0ParsingTable, SLRParsingTable
5+
from syntactes.parsing_table import Entry, LR0ParsingTable, SLRParsingTable, LR1ParsingTable
66

77
EOF = Token.eof()
88
S = Token("S", False)
@@ -250,3 +250,32 @@ def lr1_state_12():
250250
state = LR1State.from_items({item_1})
251251
state.set_number(12)
252252
return state
253+
254+
255+
def lr1_parsing_table():
256+
table = LR1ParsingTable(grammar_1)
257+
table.add_entry(Entry(lr1_state_1(), L, Action.shift(lr1_state_2())))
258+
table.add_entry(Entry(lr1_state_1(), C, Action.shift(lr1_state_3())))
259+
table.add_entry(Entry(lr1_state_1(), LPAREN, Action.shift(lr1_state_4())))
260+
table.add_entry(Entry(lr1_state_2(), C, Action.shift(lr1_state_5())))
261+
table.add_entry(Entry(lr1_state_2(), LPAREN, Action.shift(lr1_state_4())))
262+
table.add_entry(Entry(lr1_state_2(), EOF, Action.accept()))
263+
table.add_entry(Entry(lr1_state_3(), LPAREN, Action.reduce(rule_3_2)))
264+
table.add_entry(Entry(lr1_state_3(), EOF, Action.reduce(rule_3_2)))
265+
table.add_entry(Entry(lr1_state_4(), C, Action.shift(lr1_state_6())))
266+
table.add_entry(Entry(lr1_state_4(), LPAREN, Action.shift(lr1_state_7())))
267+
table.add_entry(Entry(lr1_state_4(), RPAREN, Action.shift(lr1_state_8())))
268+
table.add_entry(Entry(lr1_state_5(), LPAREN, Action.reduce(rule_2_2)))
269+
table.add_entry(Entry(lr1_state_5(), RPAREN, Action.reduce(rule_2_2)))
270+
table.add_entry(Entry(lr1_state_6(), RPAREN, Action.shift(lr1_state_9())))
271+
table.add_entry(Entry(lr1_state_7(), LPAREN, Action.shift(lr1_state_7())))
272+
table.add_entry(Entry(lr1_state_7(), RPAREN, Action.shift(lr1_state_11())))
273+
table.add_entry(Entry(lr1_state_7(), C, Action.shift(lr1_state_10())))
274+
table.add_entry(Entry(lr1_state_8(), LPAREN, Action.reduce(rule_5_2)))
275+
table.add_entry(Entry(lr1_state_8(), EOF, Action.reduce(rule_5_2)))
276+
table.add_entry(Entry(lr1_state_9(), LPAREN, Action.reduce(rule_4_2)))
277+
table.add_entry(Entry(lr1_state_9(), EOF, Action.reduce(rule_4_2)))
278+
table.add_entry(Entry(lr1_state_10(), RPAREN, Action.shift(lr1_state_12)))
279+
table.add_entry(Entry(lr1_state_11(), RPAREN, Action.reduce(rule_5_2)))
280+
table.add_entry(Entry(lr1_state_12(), RPAREN, Action.reduce(rule_4_2)))
281+
return table

0 commit comments

Comments
 (0)