Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework indexed grammars #15

Open
wants to merge 12 commits into
base: rework_cfg
Choose a base branch
from
39 changes: 39 additions & 0 deletions .github/workflows/ci_extra.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# This workflow is for any branch. It runs additional tests for several python versions.

name: Build extra

on: [push, pull_request]

jobs:
build:

runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10"]

steps:

- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Lint with pylint
run: |
pylint pyformlang || true
- name: Lint with pycodestyle
run: |
pycodestyle pyformlang || true
- name: Check with pyright
run: |
pyright --stats pyformlang
- name: Test with pytest
run: |
pytest --showlocals -v pyformlang
54 changes: 54 additions & 0 deletions .github/workflows/ci_feature.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# This workflow is for feature branches. It sets up python, lints with several analyzers,
# runs tests, collects test coverage and makes a coverage comment.

name: Build feature

on:
push:
branches-ignore: "master"
pull_request:

jobs:
build:

runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.8"]

steps:

- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Lint with pylint
run: |
pylint pyformlang || true
- name: Lint with pycodestyle
run: |
pycodestyle pyformlang || true
- name: Check with pyright
run: |
pyright --stats pyformlang
- name: Test with pytest
run: |
pytest --showlocals -v pyformlang

- name: Build coverage file
run: |
pytest pyformlang --junitxml=pytest.xml --cov=pyformlang | tee ./pytest-coverage.txt
- name: Make coverage comment
uses: MishaKav/pytest-coverage-comment@main
id: coverageComment
with:
pytest-coverage-path: ./pytest-coverage.txt
junitxml-path: ./pytest.xml
default-branch: master
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
# This workflow is for master branch only. It sets up python, lints with several analyzers,
# runs tests, collects test coverage, makes a coverage comment and creates a coverage badge.

name: Python package
name: Build master

on: [push, pull_request]
on:
push:
branches: "master"

jobs:
build:
Expand All @@ -12,9 +14,10 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.9", "3.10"]
python-version: ["3.8"]

steps:

- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
Expand All @@ -23,31 +26,33 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
pip install -r requirements.txt

- name: Lint with pylint
run: |
pylint pyformlang || true
- name: Lint with pycodestyle
run: |
pycodestyle pyformlang || true
- name: Check with pyright
run: |
pyright --stats pyformlang
- name: Test with pytest
run: |
pytest --showlocals -v pyformlang

- name: Build coverage file
if: ${{ matrix.python-version == '3.8'}}
run: |
pytest pyformlang --junitxml=pytest.xml --cov=pyformlang | tee ./pytest-coverage.txt
- name: Pytest coverage comment
if: ${{ matrix.python-version == '3.8'}}
- name: Make coverage comment
uses: MishaKav/pytest-coverage-comment@main
id: coverageComment
with:
pytest-coverage-path: ./pytest-coverage.txt
junitxml-path: ./pytest.xml
default-branch: master

- name: Create coverage Badge
if: ${{ github.ref_name == 'master' && matrix.python-version == '3.8'}}
uses: schneegans/[email protected]
with:
auth: ${{ secrets.GIST_SECRET }}
Expand Down
14 changes: 5 additions & 9 deletions pyformlang/cfg/cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,12 @@ def __init__(self,
start_symbol: Hashable = None,
productions: Iterable[Production] = None) -> None:
super().__init__()
if variables is not None:
variables = {to_variable(x) for x in variables}
self._variables = variables or set()
if terminals is not None:
terminals = {to_terminal(x) for x in terminals}
self._terminals = terminals or set()
self._variables = {to_variable(x) for x in variables or set()}
self._terminals = {to_terminal(x) for x in terminals or set()}
self._start_symbol = None
if start_symbol is not None:
start_symbol = to_variable(start_symbol)
self._variables.add(start_symbol)
self._start_symbol = start_symbol
self._start_symbol = to_variable(start_symbol)
self._variables.add(self._start_symbol)
self._productions = set()
for production in productions or set():
self.add_production(production)
Expand Down
2 changes: 2 additions & 0 deletions pyformlang/cfg/tests/test_terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ def test_creation(self):
assert epsilon.to_text() == "epsilon"
assert Terminal("C").to_text() == '"TER:C"'
assert repr(Epsilon()) == "epsilon"
assert str(terminal0) == "0"
assert repr(terminal0) == "Terminal(0)"

def test_eq(self):
assert "epsilon" == Epsilon()
Expand Down
2 changes: 2 additions & 0 deletions pyformlang/cfg/tests/test_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ def test_creation(self):
assert str(variable0) == str(variable3)
assert str(variable0) != str(variable1)
assert "A" == Variable("A")
assert str(variable1) == "1"
assert repr(variable1) == "Variable(1)"
22 changes: 6 additions & 16 deletions pyformlang/finite_automaton/epsilon_nfa.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,24 +65,14 @@ def __init__(
start_states: AbstractSet[Hashable] = None,
final_states: AbstractSet[Hashable] = None) -> None:
super().__init__()
if states is not None:
states = {to_state(x) for x in states}
self._states = states or set()
if input_symbols is not None:
input_symbols = {to_symbol(x) for x in input_symbols}
self._input_symbols = input_symbols or set()
self._states = {to_state(x) for x in states or set()}
self._input_symbols = {to_symbol(x) for x in input_symbols or set()}
self._transition_function = transition_function \
or NondeterministicTransitionFunction()
if start_states is not None:
start_states = {to_state(x) for x in start_states}
self._start_states = start_states or set()
if final_states is not None:
final_states = {to_state(x) for x in final_states}
self._final_states = final_states or set()
for state in self._final_states:
self._states.add(state)
for state in self._start_states:
self._states.add(state)
self._start_states = {to_state(x) for x in start_states or set()}
self._states.update(self._start_states)
self._final_states = {to_state(x) for x in final_states or set()}
self._states.update(self._final_states)

def _get_next_states_iterable(
self,
Expand Down
16 changes: 8 additions & 8 deletions pyformlang/finite_automaton/finite_automaton.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,14 +436,14 @@ def to_fst(self) -> FST:
"""
fst = FST()
for start_state in self._start_states:
fst.add_start_state(start_state.value)
fst.add_start_state(start_state)
for final_state in self._final_states:
fst.add_final_state(final_state.value)
fst.add_final_state(final_state)
for s_from, symb_by, s_to in self._transition_function:
fst.add_transition(s_from.value,
symb_by.value,
s_to.value,
[symb_by.value])
fst.add_transition(s_from,
symb_by,
s_to,
[symb_by])
return fst

def is_acyclic(self) -> bool:
Expand Down Expand Up @@ -700,10 +700,10 @@ def __try_add(set_to_add_to: Set[Any], element_to_add: Any) -> bool:
@staticmethod
def __add_start_state_to_graph(graph: MultiDiGraph, state: State) -> None:
""" Adds a starting node to a given graph """
graph.add_node("starting_" + str(state.value),
graph.add_node("starting_" + str(state),
label="",
shape=None,
height=.0,
width=.0)
graph.add_edge("starting_" + str(state.value),
graph.add_edge("starting_" + str(state),
state.value)
1 change: 1 addition & 0 deletions pyformlang/finite_automaton/tests/test_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def test_repr(self):
assert str(state1) == "ABC"
state2 = State(1)
assert str(state2) == "1"
assert repr(state1) == "State(ABC)"

def test_eq(self):
""" Tests the equality of states
Expand Down
1 change: 1 addition & 0 deletions pyformlang/finite_automaton/tests/test_symbol.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def test_repr(self):
assert str(symbol1) == "ABC"
symbol2 = Symbol(1)
assert str(symbol2) == "1"
assert repr(symbol2) == "Symbol(1)"

def test_eq(self):
""" Tests equality of symbols
Expand Down
8 changes: 6 additions & 2 deletions pyformlang/fst/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@

"""

from .fst import FST
from .fst import FST, TransitionFunction, State, Symbol, Epsilon


__all__ = ["FST"]
__all__ = ["FST",
"TransitionFunction",
"State",
"Symbol",
"Epsilon"]
Loading
Loading