Prosty parser wyrażeń
Proszę zbudować parser rekurencyjnego zejścia dla wyrażeń arytmetycznych w czystym Lua.
Prosty parser wyrażeń to bezpłatna lekcja Lua Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Lua Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Lua Academy zawiera 4 lekcji w sumie.
Cel: parsowanie wyrażeń arytmetycznych
Należy zbudować w czystym Lua parser rekurencyjnego zejścia, który parsuje i oblicza wyrażenia takie jak 3 + 4 * (2 - 1), z uwzględnieniem priorytetu operatorów.
Tokenizator
Najpierw należy podzielić dane wejściowe na tokeny reprezentujące liczby, operatory i nawiasy.
local function tokenize(expr)
local tokens = {}
for tok in expr:gmatch("[%d%.]+|[%+%-%*/%(%)%^]|%S") do
tokens[#tokens+1] = tok
end
return tokens
endUlepszony tokenizator
Bardziej niezawodny tokenizator korzystający ze wzorców gmatch.
local function tokenize(expr)
local tokens = {}
for tok in expr:gmatch("%d+%.?%d*|[%+%-%*/%(%)%^]") do
tokens[#tokens+1] = tok
end
return tokens
endStan parsera
Parser przechowuje listę tokenów i pozycję. Funkcje pomocnicze peek i consume przesuwają się po tokenach.
local function newParser(tokens)
local pos = 1
local function peek() return tokens[pos] end
local function consume() pos = pos + 1; return tokens[pos-1] end
return {peek=peek, consume=consume}
endGramatyka wyrażeń
Gramatyka uwzględnia priorytet operatorów:
- expr = term ((+ | -) term)*
- term = factor ((* | /) factor)*
- factor = number | (expr) | -factor
Parsowanie składników
Wyrażenia addytywne należy parsować przez parsowanie składników i składanie operatorów +/- od lewej do prawej.
local parseExpr, parseTerm, parseFactor
parseExpr = function(p)
local val = parseTerm(p)
while p.peek() == "+" or p.peek() == "-" do
local op = p.consume()
local right = parseTerm(p)
if op == "+" then val = val + right
else val = val - right end
end
return val
endParsowanie czynników
Należy parsować wyrażenia multiplikatywne, w tym potęgowanie.
parseTerm = function(p)
local val = parseFactor(p)
while p.peek() == "*" or p.peek() == "/" do
local op = p.consume()
local right = parseFactor(p)
if op == "*" then val = val * right
else val = val / right end
end
return val
endParsowanie liczb i nawiasów
Należy parsować atomy: literały, podwyrażenia w nawiasach i negację jednoargumentową.
parseFactor = function(p)
local tok = p.peek()
if tok == "(" then
p.consume() -- (
local val = parseExpr(p)
p.consume() -- )
return val
elseif tok == "-" then
p.consume()
return -parseFactor(p)
else
return tonumber(p.consume())
end
endPołączenie elementów
Należy podzielić wyrażenie na tokeny, sparsować je i obliczyć jego wartość.
local function eval(expr)
local tokens = tokenize(expr)
local parser = newParser(tokens)
return parseExpr(parser)
end
print(eval("3 + 4 * 2")) -- 11
print(eval("(3 + 4) * 2")) -- 14
print(eval("2 ^ 10")) -- 1024 (if ^ is supported)Rozszerzanie parsera
Należy dodać zmienne, funkcje, operatory porównania i literały łańcuchów, rozszerzając gramatykę oraz dodając nowe przypadki do parseFactor.
Zgłaszanie błędów
W tokenizatorze należy śledzić wiersz i kolumnę. Należy zgłaszać zrozumiałe błędy: "Expected ')' at position 7, got '+'".
Generatory parserów
W przypadku złożonych gramatyk należy używać generatorów parserów, takich jak LPEG (gramatyki wyrażeń parsowania). LPEG jest znacznie bardziej zaawansowany i ekspresywny niż ręcznie napisany parser rekurencyjnego zejścia w przypadku dużych gramatyk.
Pytanie o parser
Czego używa parser rekurencyjnego zejścia, aby wymusić priorytet operatorów?
Podsumowanie: prosty parser wyrażeń
Parser rekurencyjnego zejścia używa jednej funkcji dla każdej reguły gramatycznej, naturalnie wymuszając priorytet operatorów poprzez hierarchię wywołań. Najpierw należy podzielić dane na tokeny, a następnie zaimplementować funkcje expr → term → factor. Aby uzyskać pełny język wyrażeń, można rozszerzyć parser o zmienne i funkcje.
Często zadawane pytania
Czy lekcja „Prosty parser wyrażeń” jest bezpłatna?
Tak — pełny tekst „Prosty parser wyrażeń” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Lua Academy, przejdź na CoddyKit PRO. Kurs Lua Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Prosty parser wyrażeń”?
Proszę zbudować parser rekurencyjnego zejścia dla wyrażeń arytmetycznych w czystym Lua. Ćwiczysz Lua Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Lua Academy?
Nie wymagamy żadnego doświadczenia. Lua Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Prosty parser wyrażeń”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Lua Academy?
Tak. Każda lekcja Lua Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Zasady projektowania DSL w Lua
- Przeciążanie operatorów na potrzeby płynnego DSL
- Tworzenie DSL konfiguracji
- Prosty parser wyrażeń