Kreirano 2024-09-30 Mon 13:44, pritisni ESC za mapu, m za meni, Ctrl+Shift+F za pretragu
$ mkdir jsd $ cd jsd $ python -m venv venv $ source venv/bin/activate (venv) $ pip install parglare Looking in indexes: https://pypi.python.org/simple/ Collecting parglare Using cached https://files.pythonhosted.org/packages/66/60/c1bd988a93f5c9114a53452913d51be9556cc56cd7fc9801bbbf03e561da/parglare-0.10.0-py2.py3-none-any.whl Collecting click (from parglare) Using cached https://files.pythonhosted.org/packages/fa/37/45185cb5abbc30d7257104c434fe0b07e5a195a6847506c074527aa599ec/Click-7.0-py2.py3-none-any.whl Installing collected packages: click, parglare Successfully installed click-7.0 parglare-0.10.0
Sa master grane:
$ mkdir jsd
$ cd jsd
$ python -m venv venv
$ source venv/bin/activate
$ pip install https://github.com/igordejanovic/parglare/archive/master.zip
Looking in indexes: https://pypi.python.org/simple/
Collecting https://github.com/igordejanovic/parglare/archive/master.zip
Downloading https://github.com/igordejanovic/parglare/archive/master.zip
- 6.7MB 1.4MB/s
Requirement already satisfied: click in ./venv/lib/python3.7/site-packages (from parglare==0.11.0.dev0) (7.0)
Installing collected packages: parglare
Running setup.py install for parglare ... done
Successfully installed parglare-0.11.0.dev0
Sa master grane iz kloniranog git repozitorijuma:
$ mkdir jsd $ cd jsd $ python -m venv venv $ source venv/bin/activate $ git clone git@github.com:igordejanovic/parglare.git Cloning into 'parglare'... remote: Enumerating objects: 55, done. remote: Counting objects: 100% (55/55), done. remote: Compressing objects: 100% (44/44), done. remote: Total 6138 (delta 20), reused 29 (delta 9), pack-reused 6083 Receiving objects: 100% (6138/6138), 7.60 MiB | 2.87 MiB/s, done. Resolving deltas: 100% (4065/4065), done. $ pip install -e parglare Looking in indexes: https://pypi.python.org/simple/ Obtaining file:///home/igor/jsd/parglare Requirement already satisfied: click in ./venv/lib/python3.7/site-packages (from parglare==0.11.0.dev0) (7.0) Installing collected packages: parglare Running setup.py develop for parglare Successfully installed parglare
grammar = r"""
E: E '+' E
| E '-' E
| E '*' E
| E '/' E
| '(' E ')'
| number;
terminals
number: /\d+(\.\d+)?/;
"""
actions = {
"E": [lambda _, n: n[0] + n[2],
lambda _, n: n[0] - n[2],
lambda _, n: n[0] * n[2],
lambda _, n: n[0] / n[2],
lambda _, n: n[1],
lambda _, n: n[0]],
"number": lambda _, value: float(value),
}
from parglare import Parser, Grammar
g = Grammar.from_string(grammar)
parser = Parser(g, actions=actions)
result = parser.parse("2 * 3 + 4 / 2 / 2")
print("Result = ", result)
Parser klasa (LR parser) razrešava Shift/Reduce konflikte
tako što preferira Shift operaciju (videti prefer_shifts).Parser klase sa GLRParser dobijamo generalizovano parsiranje gde
će u slučaju višeznačnosti biti kreirana sva stabla parsiranja.from parglare import GLRParser, Grammar
g = Grammar.from_string(grammar)
parser = GLRParser(g, consume_input=True, actions=actions)
result = parser.parse("2 * 3 + 4 / 2 / 2")
print("Result = ", result)
print("Broj interpretacija = ", len(result))
Broj interpretacija je Katalanov broj od n gde je n broj binarnih
operacija u izrazu.
1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440...
{} koje navodimo po produkciji.left (odnosno reduce) i right
(odnosno shift).grammar = r"""
E: E '+' E {left}
| E '-' E {left}
| E '*' E {left}
| E '/' E {left}
| '(' E ')'
| number;
terminals
number: /\d+(\.\d+)?/;
"""
from parglare import GLRParser, Grammar
g = Grammar.from_string(grammar)
parser = GLRParser(g, actions=actions)
result = parser.parse("2 * 3 + 4 / 2 / 2")
print("Result = ", result)
grammar = r"""
E: E '+' E {left, 1}
| E '-' E {left, 1}
| E '*' E {left, 2}
| E '/' E {left, 2}
| '(' E ')'
| number;
terminals
number: /\d+(\.\d+)?/;
"""
from parglare import GLRParser, Grammar
g = Grammar.from_string(grammar)
parser = GLRParser(g, actions=actions)
result = parser.parse("2 * 3 + 4 / 2 / 2")
print("Result = ", result)
$ pglr compile --help
Usage: pglr compile [OPTIONS] GRAMMAR_FILE
Options:
--help Show this message and exit.
To compile and check your grammar run:
$ pglr compile <grammar_file>
$ pglr compile robot.pg
Compiling...
Grammar OK.
.pgt i biće automatski učitana
ukoliko postoji. Ukoliko ne postoji biće kreirana u vreme izvršavanja i
upisana u .pgt fajl.parglare će nam dati tačnu
lokaciju i šta na njoj očekuje.
$ pglr compile calc.pg
Error in the grammar file.
Error in file "calc.pg" at position 4,16 => "/' E left*, 2}\n | E ".
Expected: { or | or ; or Name or RegExTerm or StrTerm
$ pglr --debug compile calc.pg
*** GRAMMAR ***
Terminals:
number STOP + - ^ EMPTY ) \d+(\.\d+)? ( EOF / *
NonTerminals:
S' E
Productions:
0: S' = E STOP
1: E = E + E
2: E = E - E
3: E = E * E
4: E = E / E
5: E = E ^ E
6: E = ( E )
7: E = number
*** STATES ***
State 0
0: S' = . E STOP {}
1: E = . E + E {STOP, -, +, ^, ), /, *}
2: E = . E - E {STOP, -, +, ^, ), /, *}
3: E = . E * E {STOP, -, +, ^, ), /, *}
4: E = . E / E {STOP, -, +, ^, ), /, *}
5: E = . E ^ E {STOP, -, +, ^, ), /, *}
6: E = . ( E ) {STOP, -, +, ^, ), /, *}
7: E = . number {STOP, -, +, ^, ), /, *}
GOTO:
E->1
ACTIONS:
(->SHIFT:2, number->SHIFT:3
...
$ pglr viz calc.pg Grammar OK. Generating 'calc.pg.dot' file for the grammar PDA. Use dot viewer (e.g. xdot) or convert to pdf by running 'dot -Tpdf -O calc.pg.dot'
.dot fajl koji možemo pregledati sa .dot pregledačima (npr. xdot)
ili konvertovati u neki grafički format (npr. dot -Tpdf -O calc.pg.dot)
$ pglr trace --help Usage: pglr trace [OPTIONS] GRAMMAR_FILE Options: -f, --input-file PATH Input file for tracing -i, --input TEXT Input string for tracing --help Show this message and exit.
$ pglr trace calc.pg -i "2 + 3 * 5"
calc parsercalc parsergrammar = r"""
E: E '+' E {left, 1}
| E '-' E {left, 1}
| E '*' E {left, 2}
| E '/' E {left, 2}
| '(' E ')'
| number;
terminals
number: /\d+(\.\d+)?/;
"""
actions = {
"E": [lambda _, n: n[0] + n[2],
lambda _, n: n[0] - n[2],
lambda _, n: n[0] * n[2],
lambda _, n: n[0] / n[2],
lambda _, n: n[1],
lambda _, n: n[0]],
"number": lambda _, value: float(value),
}
from parglare import Parser, Grammar
g = Grammar.from_string(grammar)
parser = Parser(g, actions=actions)
result = parser.parse("2 * 3 + 4 / 2 / 2")
print("Result = ", result)
calc primer sa operacijom stepenovanja (simbol ^) koja ima
najviši prioritet i desno je asocijativna.
Proširiti calc primer sa unarnom operacijom faktorijel (simbol !) koja
ima najviši prioritet.
x! = x * (x-1) * ... * 1
Dodati mogućnost definisanja varijabli i nihove upotrebe u calc izrazima:
a = 4 b = 8 a * 2 / b^a^2 + b * a!
examples/calc folderu.ime_funkcije(param1, param2...). Parser
treba da parsira proizvoljan naziv funkcije i proizvoljan broj parametara.
Javiti grešku ukoliko funkcija nije definisana. Podržati izračunavanje
vrednosti za proizvoljne funkcije iz Python math modula.Robot jezikexamples/robot.
Fajl program.rbt
begin
initial 3, 1
up 4 // go up 4 steps
left 9
down // step is optional
right 1
end
Fajl robot.pg
program: "begin" commands=command* "end";
command: initial | move;
initial: INITIAL x=INT "," y=INT;
move: direction=direction steps=INT?;
direction: "up" | "down" | "left" | "right";
// Support for C-like comments
LAYOUT: LayoutItem | LAYOUT LayoutItem;
LayoutItem: WS | Comment | EMPTY;
terminals
INT: /\d+/;
INITIAL: "initial";
WS: /\s+/;
Comment: /\/\/.*/;
import os
from parglare import Grammar, Parser
from parglare import get_collector
action = get_collector()
@action
def INT(_, value):
return int(value)
@action
def initial(context, nodes, x, y):
print("Robot initial position set to: {}, {}".format(x, y))
# We use context.extra to keep robot position state.
context.extra = (x, y)
@action
def program(context, nodes, commands):
return context.extra
@action
def move(context, nodes, direction, steps):
steps = 1 if steps is None else steps
print("Moving robot {} for {} steps.".format(direction, steps))
move = {
"up": (0, 1),
"down": (0, -1),
"left": (-1, 0),
"right": (1, 0)
}[direction]
# Calculate new robot position
x, y = context.extra
context.extra = (x + steps * move[0], y + steps * move[1])
def main(debug=False):
this_folder = os.path.dirname(__file__)
g = Grammar.from_file(os.path.join(this_folder, 'robot.pg'),
debug=debug, debug_colors=True)
parser = Parser(g, actions=action.all, debug=debug,
debug_colors=True)
end_position = parser.parse_file(os.path.join(this_folder, 'program.rbt'))
print("Robot stops at position: {}".format(end_position))
if __name__ == "__main__":
main(debug=False)
Dodati mogućnost kretanja po dijagonali. Na primer:
begin
initial 5, 8
up left 2
down left 5
down 5
end
Dodati for petlju:
begin
initial 4, 7
for i in 1..10
begin
down 3
down right i
end
end
Dodati koncept tekuće lokacije (ugrađene promenjive robotx i roboty),
operacije poređenja <, >, =, i iskaz if:
begin
initial 4, 7
for i in 1..10
begin
down 3
if robotx > 4 up 5
down right i
if roboty < 3
begin
left 10
down
end
end
end