From 4298176d72cd43345ee5c5b74b4140cce1ab28cb Mon Sep 17 00:00:00 2001 From: Mikko Ahlroth Date: Sun, 19 May 2024 15:36:13 +0300 Subject: [PATCH] Add plural forms parser that nearly works --- expo_plural_forms_parser.erl | 1098 ---------------------------- gleam.toml | 1 + manifest.toml | 2 + src/kielet.gleam | 19 +- src/kielet/plurals.gleam | 27 + src/kielet/plurals/ast.gleam | 19 + src/kielet/plurals/evaluator.gleam | 38 + src/kielet/plurals/parser.gleam | 128 ++++ src/kielet/plurals/parser.notgleam | 148 ---- src/kielet/plurals/tokenizer.gleam | 142 +++- test/plurals_test.gleam | 184 +++++ 11 files changed, 532 insertions(+), 1274 deletions(-) delete mode 100644 expo_plural_forms_parser.erl create mode 100644 src/kielet/plurals.gleam create mode 100644 src/kielet/plurals/ast.gleam create mode 100644 src/kielet/plurals/evaluator.gleam create mode 100644 src/kielet/plurals/parser.gleam delete mode 100644 src/kielet/plurals/parser.notgleam create mode 100644 test/plurals_test.gleam diff --git a/expo_plural_forms_parser.erl b/expo_plural_forms_parser.erl deleted file mode 100644 index b141e15..0000000 --- a/expo_plural_forms_parser.erl +++ /dev/null @@ -1,1098 +0,0 @@ --module(expo_plural_forms_parser). --export([parse/1, parse_and_scan/1, format_error/1]). --file("expo_plural_forms_parser.yrl", 48). - -value({int, _Line, Int}) -> Int. - -operator({Op, _Line}) -> Op. - --file("/Users/nicd/.asdf/installs/erlang/26.1.2/lib/parsetools-2.5/include/yeccpre.hrl", 0). -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2021. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% The parser generator will insert appropriate declarations before this line.% - --type yecc_ret() :: {'error', _} | {'ok', _}. - --spec parse(Tokens :: list()) -> yecc_ret(). -parse(Tokens) -> - yeccpars0(Tokens, {no_func, no_location}, 0, [], []). - --spec parse_and_scan({function() | {atom(), atom()}, [_]} - | {atom(), atom(), [_]}) -> yecc_ret(). -parse_and_scan({F, A}) -> - yeccpars0([], {{F, A}, no_location}, 0, [], []); -parse_and_scan({M, F, A}) -> - Arity = length(A), - yeccpars0([], {{fun M:F/Arity, A}, no_location}, 0, [], []). - --spec format_error(any()) -> [char() | list()]. -format_error(Message) -> - case io_lib:deep_char_list(Message) of - true -> - Message; - _ -> - io_lib:write(Message) - end. - -%% To be used in grammar files to throw an error message to the parser -%% toplevel. Doesn't have to be exported! --compile({nowarn_unused_function, return_error/2}). --spec return_error(erl_anno:location(), any()) -> no_return(). -return_error(Location, Message) -> - throw({error, {Location, ?MODULE, Message}}). - --define(CODE_VERSION, "1.4"). - -yeccpars0(Tokens, Tzr, State, States, Vstack) -> - try yeccpars1(Tokens, Tzr, State, States, Vstack) - catch - error: Error: Stacktrace -> - try yecc_error_type(Error, Stacktrace) of - Desc -> - erlang:raise(error, {yecc_bug, ?CODE_VERSION, Desc}, - Stacktrace) - catch _:_ -> erlang:raise(error, Error, Stacktrace) - end; - %% Probably thrown from return_error/2: - throw: {error, {_Location, ?MODULE, _M}} = Error -> - Error - end. - -yecc_error_type(function_clause, [{?MODULE,F,ArityOrArgs,_} | _]) -> - case atom_to_list(F) of - "yeccgoto_" ++ SymbolL -> - {ok,[{atom,_,Symbol}],_} = erl_scan:string(SymbolL), - State = case ArityOrArgs of - [S,_,_,_,_,_,_] -> S; - _ -> state_is_unknown - end, - {Symbol, State, missing_in_goto_table} - end. - -yeccpars1([Token | Tokens], Tzr, State, States, Vstack) -> - yeccpars2(State, element(1, Token), States, Vstack, Token, Tokens, Tzr); -yeccpars1([], {{F, A},_Location}, State, States, Vstack) -> - case apply(F, A) of - {ok, Tokens, EndLocation} -> - yeccpars1(Tokens, {{F, A}, EndLocation}, State, States, Vstack); - {eof, EndLocation} -> - yeccpars1([], {no_func, EndLocation}, State, States, Vstack); - {error, Descriptor, _EndLocation} -> - {error, Descriptor} - end; -yeccpars1([], {no_func, no_location}, State, States, Vstack) -> - Line = 999999, - yeccpars2(State, '$end', States, Vstack, yecc_end(Line), [], - {no_func, Line}); -yeccpars1([], {no_func, EndLocation}, State, States, Vstack) -> - yeccpars2(State, '$end', States, Vstack, yecc_end(EndLocation), [], - {no_func, EndLocation}). - -%% yeccpars1/7 is called from generated code. -%% -%% When using the {includefile, Includefile} option, make sure that -%% yeccpars1/7 can be found by parsing the file without following -%% include directives. yecc will otherwise assume that an old -%% yeccpre.hrl is included (one which defines yeccpars1/5). -yeccpars1(State1, State, States, Vstack, Token0, [Token | Tokens], Tzr) -> - yeccpars2(State, element(1, Token), [State1 | States], - [Token0 | Vstack], Token, Tokens, Tzr); -yeccpars1(State1, State, States, Vstack, Token0, [], {{_F,_A}, _Location}=Tzr) -> - yeccpars1([], Tzr, State, [State1 | States], [Token0 | Vstack]); -yeccpars1(State1, State, States, Vstack, Token0, [], {no_func, no_location}) -> - Location = yecctoken_end_location(Token0), - yeccpars2(State, '$end', [State1 | States], [Token0 | Vstack], - yecc_end(Location), [], {no_func, Location}); -yeccpars1(State1, State, States, Vstack, Token0, [], {no_func, Location}) -> - yeccpars2(State, '$end', [State1 | States], [Token0 | Vstack], - yecc_end(Location), [], {no_func, Location}). - -%% For internal use only. -yecc_end(Location) -> - {'$end', Location}. - -yecctoken_end_location(Token) -> - try erl_anno:end_location(element(2, Token)) of - undefined -> yecctoken_location(Token); - Loc -> Loc - catch _:_ -> yecctoken_location(Token) - end. - --compile({nowarn_unused_function, yeccerror/1}). -yeccerror(Token) -> - Text = yecctoken_to_string(Token), - Location = yecctoken_location(Token), - {error, {Location, ?MODULE, ["syntax error before: ", Text]}}. - --compile({nowarn_unused_function, yecctoken_to_string/1}). -yecctoken_to_string(Token) -> - try erl_scan:text(Token) of - undefined -> yecctoken2string(Token); - Txt -> Txt - catch _:_ -> yecctoken2string(Token) - end. - -yecctoken_location(Token) -> - try erl_scan:location(Token) - catch _:_ -> element(2, Token) - end. - --compile({nowarn_unused_function, yecctoken2string/1}). -yecctoken2string(Token) -> - try - yecctoken2string1(Token) - catch - _:_ -> - io_lib:format("~tp", [Token]) - end. - --compile({nowarn_unused_function, yecctoken2string1/1}). -yecctoken2string1({atom, _, A}) -> io_lib:write_atom(A); -yecctoken2string1({integer,_,N}) -> io_lib:write(N); -yecctoken2string1({float,_,F}) -> io_lib:write(F); -yecctoken2string1({char,_,C}) -> io_lib:write_char(C); -yecctoken2string1({var,_,V}) -> io_lib:format("~s", [V]); -yecctoken2string1({string,_,S}) -> io_lib:write_string(S); -yecctoken2string1({reserved_symbol, _, A}) -> io_lib:write(A); -yecctoken2string1({_Cat, _, Val}) -> io_lib:format("~tp", [Val]); -yecctoken2string1({dot, _}) -> "'.'"; -yecctoken2string1({'$end', _}) -> []; -yecctoken2string1({Other, _}) when is_atom(Other) -> - io_lib:write_atom(Other); -yecctoken2string1(Other) -> - io_lib:format("~tp", [Other]). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - --file("expo_plural_forms_parser.erl", 188). - --dialyzer({nowarn_function, yeccpars2/7}). --compile({nowarn_unused_function, yeccpars2/7}). -yeccpars2(0=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_0(S, Cat, Ss, Stack, T, Ts, Tzr); -%% yeccpars2(1=S, Cat, Ss, Stack, T, Ts, Tzr) -> -%% yeccpars2_1(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(2=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_2(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(3=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_3(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(4=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_4(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(5=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_5(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(6=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_6(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(7=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_7(S, Cat, Ss, Stack, T, Ts, Tzr); -%% yeccpars2(8=S, Cat, Ss, Stack, T, Ts, Tzr) -> -%% yeccpars2_8(S, Cat, Ss, Stack, T, Ts, Tzr); -%% yeccpars2(9=S, Cat, Ss, Stack, T, Ts, Tzr) -> -%% yeccpars2_9(S, Cat, Ss, Stack, T, Ts, Tzr); -%% yeccpars2(10=S, Cat, Ss, Stack, T, Ts, Tzr) -> -%% yeccpars2_10(S, Cat, Ss, Stack, T, Ts, Tzr); -%% yeccpars2(11=S, Cat, Ss, Stack, T, Ts, Tzr) -> -%% yeccpars2_11(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(12=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_12(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(13=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_13(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(14=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_14(S, Cat, Ss, Stack, T, Ts, Tzr); -%% yeccpars2(15=S, Cat, Ss, Stack, T, Ts, Tzr) -> -%% yeccpars2_15(S, Cat, Ss, Stack, T, Ts, Tzr); -%% yeccpars2(16=S, Cat, Ss, Stack, T, Ts, Tzr) -> -%% yeccpars2_16(S, Cat, Ss, Stack, T, Ts, Tzr); -%% yeccpars2(17=S, Cat, Ss, Stack, T, Ts, Tzr) -> -%% yeccpars2_17(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(18=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_18(S, Cat, Ss, Stack, T, Ts, Tzr); -%% yeccpars2(19=S, Cat, Ss, Stack, T, Ts, Tzr) -> -%% yeccpars2_12(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(20=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_20(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(21=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_21(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(22=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_12(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(23=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_23(S, Cat, Ss, Stack, T, Ts, Tzr); -%% yeccpars2(24=S, Cat, Ss, Stack, T, Ts, Tzr) -> -%% yeccpars2_24(S, Cat, Ss, Stack, T, Ts, Tzr); -%% yeccpars2(25=S, Cat, Ss, Stack, T, Ts, Tzr) -> -%% yeccpars2_25(S, Cat, Ss, Stack, T, Ts, Tzr); -%% yeccpars2(26=S, Cat, Ss, Stack, T, Ts, Tzr) -> -%% yeccpars2_26(S, Cat, Ss, Stack, T, Ts, Tzr); -%% yeccpars2(27=S, Cat, Ss, Stack, T, Ts, Tzr) -> -%% yeccpars2_12(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(28=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_28(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(29=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_12(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(30=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_12(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(31=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_31(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(32=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_32(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(33=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_33(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(34=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_34(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(35=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_35(S, Cat, Ss, Stack, T, Ts, Tzr); -%% yeccpars2(36=S, Cat, Ss, Stack, T, Ts, Tzr) -> -%% yeccpars2_36(S, Cat, Ss, Stack, T, Ts, Tzr); -%% yeccpars2(37=S, Cat, Ss, Stack, T, Ts, Tzr) -> -%% yeccpars2_37(S, Cat, Ss, Stack, T, Ts, Tzr); -%% yeccpars2(38=S, Cat, Ss, Stack, T, Ts, Tzr) -> -%% yeccpars2_38(S, Cat, Ss, Stack, T, Ts, Tzr); -%% yeccpars2(39=S, Cat, Ss, Stack, T, Ts, Tzr) -> -%% yeccpars2_39(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(40=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_40(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(41=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_41(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(42=S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_42(S, Cat, Ss, Stack, T, Ts, Tzr); -yeccpars2(Other, _, _, _, _, _, _) -> - erlang:error({yecc_bug,"1.4",{missing_state_in_action_table, Other}}). - --dialyzer({nowarn_function, yeccpars2_0/7}). --compile({nowarn_unused_function, yeccpars2_0/7}). -yeccpars2_0(S, 'nplurals', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 2, Ss, Stack, T, Ts, Tzr); -yeccpars2_0(_, _, _, _, T, _, _) -> - yeccerror(T). - --dialyzer({nowarn_function, yeccpars2_1/7}). --compile({nowarn_unused_function, yeccpars2_1/7}). -yeccpars2_1(_S, '$end', _Ss, Stack, _T, _Ts, _Tzr) -> - {ok, hd(Stack)}; -yeccpars2_1(_, _, _, _, T, _, _) -> - yeccerror(T). - --dialyzer({nowarn_function, yeccpars2_2/7}). --compile({nowarn_unused_function, yeccpars2_2/7}). -yeccpars2_2(S, '=', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 3, Ss, Stack, T, Ts, Tzr); -yeccpars2_2(_, _, _, _, T, _, _) -> - yeccerror(T). - --dialyzer({nowarn_function, yeccpars2_3/7}). --compile({nowarn_unused_function, yeccpars2_3/7}). -yeccpars2_3(S, 'int', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 4, Ss, Stack, T, Ts, Tzr); -yeccpars2_3(_, _, _, _, T, _, _) -> - yeccerror(T). - --dialyzer({nowarn_function, yeccpars2_4/7}). --compile({nowarn_unused_function, yeccpars2_4/7}). -yeccpars2_4(S, ';', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 5, Ss, Stack, T, Ts, Tzr); -yeccpars2_4(_, _, _, _, T, _, _) -> - yeccerror(T). - --dialyzer({nowarn_function, yeccpars2_5/7}). --compile({nowarn_unused_function, yeccpars2_5/7}). -yeccpars2_5(S, 'plural', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 6, Ss, Stack, T, Ts, Tzr); -yeccpars2_5(_, _, _, _, T, _, _) -> - yeccerror(T). - --dialyzer({nowarn_function, yeccpars2_6/7}). --compile({nowarn_unused_function, yeccpars2_6/7}). -yeccpars2_6(S, '=', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 7, Ss, Stack, T, Ts, Tzr); -yeccpars2_6(_, _, _, _, T, _, _) -> - yeccerror(T). - --dialyzer({nowarn_function, yeccpars2_7/7}). --compile({nowarn_unused_function, yeccpars2_7/7}). -yeccpars2_7(S, '(', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 12, Ss, Stack, T, Ts, Tzr); -yeccpars2_7(S, 'int', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 13, Ss, Stack, T, Ts, Tzr); -yeccpars2_7(S, 'n', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 14, Ss, Stack, T, Ts, Tzr); -yeccpars2_7(_, _, _, _, T, _, _) -> - yeccerror(T). - --dialyzer({nowarn_function, yeccpars2_8/7}). --compile({nowarn_unused_function, yeccpars2_8/7}). -yeccpars2_8(S, ';', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 42, Ss, Stack, T, Ts, Tzr); -yeccpars2_8(_, _, _, _, T, _, _) -> - yeccerror(T). - --dialyzer({nowarn_function, yeccpars2_9/7}). --compile({nowarn_unused_function, yeccpars2_9/7}). -yeccpars2_9(_S, '!=', Ss, Stack, T, Ts, Tzr) -> - NewStack = 'yeccpars2_9_!='(Stack), - yeccgoto_expr(hd(Ss), '!=', Ss, NewStack, T, Ts, Tzr); -yeccpars2_9(_S, '%', Ss, Stack, T, Ts, Tzr) -> - NewStack = 'yeccpars2_9_%'(Stack), - yeccgoto_expr(hd(Ss), '%', Ss, NewStack, T, Ts, Tzr); -yeccpars2_9(_S, '<', Ss, Stack, T, Ts, Tzr) -> - NewStack = 'yeccpars2_9_<'(Stack), - yeccgoto_expr(hd(Ss), '<', Ss, NewStack, T, Ts, Tzr); -yeccpars2_9(_S, '<=', Ss, Stack, T, Ts, Tzr) -> - NewStack = 'yeccpars2_9_<='(Stack), - yeccgoto_expr(hd(Ss), '<=', Ss, NewStack, T, Ts, Tzr); -yeccpars2_9(_S, '==', Ss, Stack, T, Ts, Tzr) -> - NewStack = 'yeccpars2_9_=='(Stack), - yeccgoto_expr(hd(Ss), '==', Ss, NewStack, T, Ts, Tzr); -yeccpars2_9(_S, '>', Ss, Stack, T, Ts, Tzr) -> - NewStack = 'yeccpars2_9_>'(Stack), - yeccgoto_expr(hd(Ss), '>', Ss, NewStack, T, Ts, Tzr); -yeccpars2_9(_S, '>=', Ss, Stack, T, Ts, Tzr) -> - NewStack = 'yeccpars2_9_>='(Stack), - yeccgoto_expr(hd(Ss), '>=', Ss, NewStack, T, Ts, Tzr); -yeccpars2_9(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - NewStack = yeccpars2_9_(Stack), - yeccgoto_plural_expr(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccpars2_10/7}). --compile({nowarn_unused_function, yeccpars2_10/7}). -yeccpars2_10(S, '!=', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 28, Ss, Stack, T, Ts, Tzr); -yeccpars2_10(S, '%', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 29, Ss, Stack, T, Ts, Tzr); -yeccpars2_10(S, '<', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 31, Ss, Stack, T, Ts, Tzr); -yeccpars2_10(S, '<=', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 32, Ss, Stack, T, Ts, Tzr); -yeccpars2_10(S, '==', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 33, Ss, Stack, T, Ts, Tzr); -yeccpars2_10(S, '>', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 34, Ss, Stack, T, Ts, Tzr); -yeccpars2_10(S, '>=', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 35, Ss, Stack, T, Ts, Tzr); -yeccpars2_10(_, _, _, _, T, _, _) -> - yeccerror(T). - --dialyzer({nowarn_function, yeccpars2_11/7}). --compile({nowarn_unused_function, yeccpars2_11/7}). -yeccpars2_11(S, '&&', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 20, Ss, Stack, T, Ts, Tzr); -yeccpars2_11(S, '?', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 22, Ss, Stack, T, Ts, Tzr); -yeccpars2_11(S, '||', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 23, Ss, Stack, T, Ts, Tzr); -yeccpars2_11(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - NewStack = yeccpars2_11_(Stack), - yeccgoto_plural_expr(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccpars2_12/7}). --compile({nowarn_unused_function, yeccpars2_12/7}). -yeccpars2_12(S, '(', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 12, Ss, Stack, T, Ts, Tzr); -yeccpars2_12(S, 'int', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 18, Ss, Stack, T, Ts, Tzr); -yeccpars2_12(S, 'n', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 14, Ss, Stack, T, Ts, Tzr); -yeccpars2_12(_, _, _, _, T, _, _) -> - yeccerror(T). - --dialyzer({nowarn_function, yeccpars2_13/7}). --compile({nowarn_unused_function, yeccpars2_13/7}). -yeccpars2_13(_S, '!=', Ss, Stack, T, Ts, Tzr) -> - NewStack = 'yeccpars2_13_!='(Stack), - yeccgoto_expr(hd(Ss), '!=', Ss, NewStack, T, Ts, Tzr); -yeccpars2_13(_S, '%', Ss, Stack, T, Ts, Tzr) -> - NewStack = 'yeccpars2_13_%'(Stack), - yeccgoto_expr(hd(Ss), '%', Ss, NewStack, T, Ts, Tzr); -yeccpars2_13(_S, '<', Ss, Stack, T, Ts, Tzr) -> - NewStack = 'yeccpars2_13_<'(Stack), - yeccgoto_expr(hd(Ss), '<', Ss, NewStack, T, Ts, Tzr); -yeccpars2_13(_S, '<=', Ss, Stack, T, Ts, Tzr) -> - NewStack = 'yeccpars2_13_<='(Stack), - yeccgoto_expr(hd(Ss), '<=', Ss, NewStack, T, Ts, Tzr); -yeccpars2_13(_S, '==', Ss, Stack, T, Ts, Tzr) -> - NewStack = 'yeccpars2_13_=='(Stack), - yeccgoto_expr(hd(Ss), '==', Ss, NewStack, T, Ts, Tzr); -yeccpars2_13(_S, '>', Ss, Stack, T, Ts, Tzr) -> - NewStack = 'yeccpars2_13_>'(Stack), - yeccgoto_expr(hd(Ss), '>', Ss, NewStack, T, Ts, Tzr); -yeccpars2_13(_S, '>=', Ss, Stack, T, Ts, Tzr) -> - NewStack = 'yeccpars2_13_>='(Stack), - yeccgoto_expr(hd(Ss), '>=', Ss, NewStack, T, Ts, Tzr); -yeccpars2_13(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - NewStack = yeccpars2_13_(Stack), - yeccgoto_plural_expr(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccpars2_14/7}). --compile({nowarn_unused_function, yeccpars2_14/7}). -yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - NewStack = yeccpars2_14_(Stack), - yeccgoto_expr(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccpars2_15/7}). --compile({nowarn_unused_function, yeccpars2_15/7}). -yeccpars2_15(S, ')', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 41, Ss, Stack, T, Ts, Tzr); -yeccpars2_15(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - NewStack = yeccpars2_15_(Stack), - yeccgoto_expr(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr). - -yeccpars2_16(S, ')', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 40, Ss, Stack, T, Ts, Tzr); -yeccpars2_16(S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_10(S, Cat, Ss, Stack, T, Ts, Tzr). - -yeccpars2_17(S, ')', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 21, Ss, Stack, T, Ts, Tzr); -yeccpars2_17(S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_26(S, Cat, Ss, Stack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccpars2_18/7}). --compile({nowarn_unused_function, yeccpars2_18/7}). -yeccpars2_18(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - NewStack = yeccpars2_18_(Stack), - yeccgoto_expr(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr). - -%% yeccpars2_19: see yeccpars2_12 - --dialyzer({nowarn_function, yeccpars2_20/7}). --compile({nowarn_unused_function, yeccpars2_20/7}). -yeccpars2_20(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - NewStack = yeccpars2_20_(Stack), - yeccgoto_bool_op(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccpars2_21/7}). --compile({nowarn_unused_function, yeccpars2_21/7}). -yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - [_,_|Nss] = Ss, - NewStack = yeccpars2_21_(Stack), - yeccgoto_bool_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr). - -%% yeccpars2_22: see yeccpars2_12 - --dialyzer({nowarn_function, yeccpars2_23/7}). --compile({nowarn_unused_function, yeccpars2_23/7}). -yeccpars2_23(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - NewStack = yeccpars2_23_(Stack), - yeccgoto_bool_op(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccpars2_24/7}). --compile({nowarn_unused_function, yeccpars2_24/7}). -yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - NewStack = yeccpars2_24_(Stack), - yeccgoto_expr(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr). - -yeccpars2_25(S, ':', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 30, Ss, Stack, T, Ts, Tzr); -yeccpars2_25(S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_10(S, Cat, Ss, Stack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccpars2_26/7}). --compile({nowarn_unused_function, yeccpars2_26/7}). -yeccpars2_26(S, '&&', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 20, Ss, Stack, T, Ts, Tzr); -yeccpars2_26(S, '?', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 22, Ss, Stack, T, Ts, Tzr); -yeccpars2_26(S, '||', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 23, Ss, Stack, T, Ts, Tzr); -yeccpars2_26(_, _, _, _, T, _, _) -> - yeccerror(T). - -%% yeccpars2_27: see yeccpars2_12 - --dialyzer({nowarn_function, yeccpars2_28/7}). --compile({nowarn_unused_function, yeccpars2_28/7}). -yeccpars2_28(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - NewStack = yeccpars2_28_(Stack), - yeccgoto_comp_op(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr). - -%% yeccpars2_29: see yeccpars2_12 - -%% yeccpars2_30: see yeccpars2_12 - --dialyzer({nowarn_function, yeccpars2_31/7}). --compile({nowarn_unused_function, yeccpars2_31/7}). -yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - NewStack = yeccpars2_31_(Stack), - yeccgoto_comp_op(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccpars2_32/7}). --compile({nowarn_unused_function, yeccpars2_32/7}). -yeccpars2_32(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - NewStack = yeccpars2_32_(Stack), - yeccgoto_comp_op(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccpars2_33/7}). --compile({nowarn_unused_function, yeccpars2_33/7}). -yeccpars2_33(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - NewStack = yeccpars2_33_(Stack), - yeccgoto_comp_op(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccpars2_34/7}). --compile({nowarn_unused_function, yeccpars2_34/7}). -yeccpars2_34(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - NewStack = yeccpars2_34_(Stack), - yeccgoto_comp_op(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccpars2_35/7}). --compile({nowarn_unused_function, yeccpars2_35/7}). -yeccpars2_35(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - NewStack = yeccpars2_35_(Stack), - yeccgoto_comp_op(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccpars2_36/7}). --compile({nowarn_unused_function, yeccpars2_36/7}). -yeccpars2_36(S, '!=', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 28, Ss, Stack, T, Ts, Tzr); -yeccpars2_36(S, '%', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 29, Ss, Stack, T, Ts, Tzr); -yeccpars2_36(S, '<', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 31, Ss, Stack, T, Ts, Tzr); -yeccpars2_36(S, '<=', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 32, Ss, Stack, T, Ts, Tzr); -yeccpars2_36(S, '==', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 33, Ss, Stack, T, Ts, Tzr); -yeccpars2_36(S, '>', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 34, Ss, Stack, T, Ts, Tzr); -yeccpars2_36(S, '>=', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 35, Ss, Stack, T, Ts, Tzr); -yeccpars2_36(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - [_,_,_,_|Nss] = Ss, - NewStack = yeccpars2_36_(Stack), - yeccgoto_if_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccpars2_37/7}). --compile({nowarn_unused_function, yeccpars2_37/7}). -yeccpars2_37(S, '%', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 29, Ss, Stack, T, Ts, Tzr); -yeccpars2_37(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - [_,_|Nss] = Ss, - NewStack = yeccpars2_37_(Stack), - yeccgoto_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccpars2_38/7}). --compile({nowarn_unused_function, yeccpars2_38/7}). -yeccpars2_38(S, '!=', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 28, Ss, Stack, T, Ts, Tzr); -yeccpars2_38(S, '%', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 29, Ss, Stack, T, Ts, Tzr); -yeccpars2_38(S, '<', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 31, Ss, Stack, T, Ts, Tzr); -yeccpars2_38(S, '<=', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 32, Ss, Stack, T, Ts, Tzr); -yeccpars2_38(S, '==', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 33, Ss, Stack, T, Ts, Tzr); -yeccpars2_38(S, '>', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 34, Ss, Stack, T, Ts, Tzr); -yeccpars2_38(S, '>=', Ss, Stack, T, Ts, Tzr) -> - yeccpars1(S, 35, Ss, Stack, T, Ts, Tzr); -yeccpars2_38(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - [_,_|Nss] = Ss, - NewStack = yeccpars2_38_(Stack), - yeccgoto_bool_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccpars2_39/7}). --compile({nowarn_unused_function, yeccpars2_39/7}). -yeccpars2_39(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - [_,_|Nss] = Ss, - NewStack = yeccpars2_39_(Stack), - yeccgoto_bool_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccpars2_40/7}). --compile({nowarn_unused_function, yeccpars2_40/7}). -yeccpars2_40(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - [_,_|Nss] = Ss, - NewStack = yeccpars2_40_(Stack), - yeccgoto_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccpars2_41/7}). --compile({nowarn_unused_function, yeccpars2_41/7}). -yeccpars2_41(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - [_,_|Nss] = Ss, - NewStack = yeccpars2_41_(Stack), - yeccgoto_if_expr(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccpars2_42/7}). --compile({nowarn_unused_function, yeccpars2_42/7}). -yeccpars2_42(_S, Cat, Ss, Stack, T, Ts, Tzr) -> - [_,_,_,_,_,_,_|Nss] = Ss, - NewStack = yeccpars2_42_(Stack), - yeccgoto_plural_form(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccgoto_bool_expr/7}). --compile({nowarn_unused_function, yeccgoto_bool_expr/7}). -yeccgoto_bool_expr(7, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_11(11, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_bool_expr(12, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_bool_expr(19=_S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_39(_S, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_bool_expr(22, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_26(26, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_bool_expr(27, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_26(26, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_bool_expr(29, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_26(26, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_bool_expr(30, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_26(26, Cat, Ss, Stack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccgoto_bool_op/7}). --compile({nowarn_unused_function, yeccgoto_bool_op/7}). -yeccgoto_bool_op(11, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_12(19, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_bool_op(17, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_12(19, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_bool_op(26, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_12(19, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_bool_op(39, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_12(19, Cat, Ss, Stack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccgoto_comp_op/7}). --compile({nowarn_unused_function, yeccgoto_comp_op/7}). -yeccgoto_comp_op(10, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_12(27, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_comp_op(16, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_12(27, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_comp_op(25, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_12(27, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_comp_op(36, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_12(27, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_comp_op(37, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_12(27, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_comp_op(38, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_12(27, Cat, Ss, Stack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccgoto_expr/7}). --compile({nowarn_unused_function, yeccgoto_expr/7}). -yeccgoto_expr(7, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_10(10, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_expr(12, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_16(16, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_expr(19, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_10(10, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_expr(22, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_25(25, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_expr(27, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_38(38, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_expr(29, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_37(37, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_expr(30, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_36(36, Cat, Ss, Stack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccgoto_if_expr/7}). --compile({nowarn_unused_function, yeccgoto_if_expr/7}). -yeccgoto_if_expr(7=_S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_9(_S, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_if_expr(12, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_15(15, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_if_expr(19=_S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_if_expr(22=_S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_if_expr(27=_S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_if_expr(29=_S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr); -yeccgoto_if_expr(30=_S, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccgoto_plural_expr/7}). --compile({nowarn_unused_function, yeccgoto_plural_expr/7}). -yeccgoto_plural_expr(7, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_8(8, Cat, Ss, Stack, T, Ts, Tzr). - --dialyzer({nowarn_function, yeccgoto_plural_form/7}). --compile({nowarn_unused_function, yeccgoto_plural_form/7}). -yeccgoto_plural_form(0, Cat, Ss, Stack, T, Ts, Tzr) -> - yeccpars2_1(1, Cat, Ss, Stack, T, Ts, Tzr). - --compile({inline,'yeccpars2_9_!='/1}). --dialyzer({nowarn_function, 'yeccpars2_9_!='/1}). --compile({nowarn_unused_function, 'yeccpars2_9_!='/1}). --file("expo_plural_forms_parser.yrl", 30). -'yeccpars2_9_!='(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - ___1 - end | __Stack]. - --compile({inline,'yeccpars2_9_%'/1}). --dialyzer({nowarn_function, 'yeccpars2_9_%'/1}). --compile({nowarn_unused_function, 'yeccpars2_9_%'/1}). --file("expo_plural_forms_parser.yrl", 30). -'yeccpars2_9_%'(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - ___1 - end | __Stack]. - --compile({inline,'yeccpars2_9_<'/1}). --dialyzer({nowarn_function, 'yeccpars2_9_<'/1}). --compile({nowarn_unused_function, 'yeccpars2_9_<'/1}). --file("expo_plural_forms_parser.yrl", 30). -'yeccpars2_9_<'(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - ___1 - end | __Stack]. - --compile({inline,'yeccpars2_9_<='/1}). --dialyzer({nowarn_function, 'yeccpars2_9_<='/1}). --compile({nowarn_unused_function, 'yeccpars2_9_<='/1}). --file("expo_plural_forms_parser.yrl", 30). -'yeccpars2_9_<='(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - ___1 - end | __Stack]. - --compile({inline,'yeccpars2_9_=='/1}). --dialyzer({nowarn_function, 'yeccpars2_9_=='/1}). --compile({nowarn_unused_function, 'yeccpars2_9_=='/1}). --file("expo_plural_forms_parser.yrl", 30). -'yeccpars2_9_=='(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - ___1 - end | __Stack]. - --compile({inline,'yeccpars2_9_>'/1}). --dialyzer({nowarn_function, 'yeccpars2_9_>'/1}). --compile({nowarn_unused_function, 'yeccpars2_9_>'/1}). --file("expo_plural_forms_parser.yrl", 30). -'yeccpars2_9_>'(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - ___1 - end | __Stack]. - --compile({inline,'yeccpars2_9_>='/1}). --dialyzer({nowarn_function, 'yeccpars2_9_>='/1}). --compile({nowarn_unused_function, 'yeccpars2_9_>='/1}). --file("expo_plural_forms_parser.yrl", 30). -'yeccpars2_9_>='(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - ___1 - end | __Stack]. - --compile({inline,yeccpars2_9_/1}). --dialyzer({nowarn_function, yeccpars2_9_/1}). --compile({nowarn_unused_function, yeccpars2_9_/1}). --file("expo_plural_forms_parser.yrl", 19). -yeccpars2_9_(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - ___1 - end | __Stack]. - --compile({inline,yeccpars2_11_/1}). --dialyzer({nowarn_function, yeccpars2_11_/1}). --compile({nowarn_unused_function, yeccpars2_11_/1}). --file("expo_plural_forms_parser.yrl", 18). -yeccpars2_11_(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - ___1 - end | __Stack]. - --compile({inline,'yeccpars2_13_!='/1}). --dialyzer({nowarn_function, 'yeccpars2_13_!='/1}). --compile({nowarn_unused_function, 'yeccpars2_13_!='/1}). --file("expo_plural_forms_parser.yrl", 29). -'yeccpars2_13_!='(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - value(___1) - end | __Stack]. - --compile({inline,'yeccpars2_13_%'/1}). --dialyzer({nowarn_function, 'yeccpars2_13_%'/1}). --compile({nowarn_unused_function, 'yeccpars2_13_%'/1}). --file("expo_plural_forms_parser.yrl", 29). -'yeccpars2_13_%'(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - value(___1) - end | __Stack]. - --compile({inline,'yeccpars2_13_<'/1}). --dialyzer({nowarn_function, 'yeccpars2_13_<'/1}). --compile({nowarn_unused_function, 'yeccpars2_13_<'/1}). --file("expo_plural_forms_parser.yrl", 29). -'yeccpars2_13_<'(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - value(___1) - end | __Stack]. - --compile({inline,'yeccpars2_13_<='/1}). --dialyzer({nowarn_function, 'yeccpars2_13_<='/1}). --compile({nowarn_unused_function, 'yeccpars2_13_<='/1}). --file("expo_plural_forms_parser.yrl", 29). -'yeccpars2_13_<='(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - value(___1) - end | __Stack]. - --compile({inline,'yeccpars2_13_=='/1}). --dialyzer({nowarn_function, 'yeccpars2_13_=='/1}). --compile({nowarn_unused_function, 'yeccpars2_13_=='/1}). --file("expo_plural_forms_parser.yrl", 29). -'yeccpars2_13_=='(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - value(___1) - end | __Stack]. - --compile({inline,'yeccpars2_13_>'/1}). --dialyzer({nowarn_function, 'yeccpars2_13_>'/1}). --compile({nowarn_unused_function, 'yeccpars2_13_>'/1}). --file("expo_plural_forms_parser.yrl", 29). -'yeccpars2_13_>'(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - value(___1) - end | __Stack]. - --compile({inline,'yeccpars2_13_>='/1}). --dialyzer({nowarn_function, 'yeccpars2_13_>='/1}). --compile({nowarn_unused_function, 'yeccpars2_13_>='/1}). --file("expo_plural_forms_parser.yrl", 29). -'yeccpars2_13_>='(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - value(___1) - end | __Stack]. - --compile({inline,yeccpars2_13_/1}). --dialyzer({nowarn_function, yeccpars2_13_/1}). --compile({nowarn_unused_function, yeccpars2_13_/1}). --file("expo_plural_forms_parser.yrl", 17). -yeccpars2_13_(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - value(___1) - end | __Stack]. - --compile({inline,yeccpars2_14_/1}). --dialyzer({nowarn_function, yeccpars2_14_/1}). --compile({nowarn_unused_function, yeccpars2_14_/1}). --file("expo_plural_forms_parser.yrl", 31). -yeccpars2_14_(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - n - end | __Stack]. - --compile({inline,yeccpars2_15_/1}). --dialyzer({nowarn_function, yeccpars2_15_/1}). --compile({nowarn_unused_function, yeccpars2_15_/1}). --file("expo_plural_forms_parser.yrl", 30). -yeccpars2_15_(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - ___1 - end | __Stack]. - --compile({inline,yeccpars2_18_/1}). --dialyzer({nowarn_function, yeccpars2_18_/1}). --compile({nowarn_unused_function, yeccpars2_18_/1}). --file("expo_plural_forms_parser.yrl", 29). -yeccpars2_18_(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - value(___1) - end | __Stack]. - --compile({inline,yeccpars2_20_/1}). --dialyzer({nowarn_function, yeccpars2_20_/1}). --compile({nowarn_unused_function, yeccpars2_20_/1}). --file("expo_plural_forms_parser.yrl", 41). -yeccpars2_20_(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - operator(___1) - end | __Stack]. - --compile({inline,yeccpars2_21_/1}). --dialyzer({nowarn_function, yeccpars2_21_/1}). --compile({nowarn_unused_function, yeccpars2_21_/1}). --file("expo_plural_forms_parser.yrl", 23). -yeccpars2_21_(__Stack0) -> - [___3,___2,___1 | __Stack] = __Stack0, - [begin - {paren, ___2} - end | __Stack]. - --compile({inline,yeccpars2_23_/1}). --dialyzer({nowarn_function, yeccpars2_23_/1}). --compile({nowarn_unused_function, yeccpars2_23_/1}). --file("expo_plural_forms_parser.yrl", 42). -yeccpars2_23_(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - operator(___1) - end | __Stack]. - --compile({inline,yeccpars2_24_/1}). --dialyzer({nowarn_function, yeccpars2_24_/1}). --compile({nowarn_unused_function, yeccpars2_24_/1}). --file("expo_plural_forms_parser.yrl", 30). -yeccpars2_24_(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - ___1 - end | __Stack]. - --compile({inline,yeccpars2_28_/1}). --dialyzer({nowarn_function, yeccpars2_28_/1}). --compile({nowarn_unused_function, yeccpars2_28_/1}). --file("expo_plural_forms_parser.yrl", 34). -yeccpars2_28_(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - operator(___1) - end | __Stack]. - --compile({inline,yeccpars2_31_/1}). --dialyzer({nowarn_function, yeccpars2_31_/1}). --compile({nowarn_unused_function, yeccpars2_31_/1}). --file("expo_plural_forms_parser.yrl", 37). -yeccpars2_31_(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - operator(___1) - end | __Stack]. - --compile({inline,yeccpars2_32_/1}). --dialyzer({nowarn_function, yeccpars2_32_/1}). --compile({nowarn_unused_function, yeccpars2_32_/1}). --file("expo_plural_forms_parser.yrl", 39). -yeccpars2_32_(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - operator(___1) - end | __Stack]. - --compile({inline,yeccpars2_33_/1}). --dialyzer({nowarn_function, yeccpars2_33_/1}). --compile({nowarn_unused_function, yeccpars2_33_/1}). --file("expo_plural_forms_parser.yrl", 36). -yeccpars2_33_(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - operator(___1) - end | __Stack]. - --compile({inline,yeccpars2_34_/1}). --dialyzer({nowarn_function, yeccpars2_34_/1}). --compile({nowarn_unused_function, yeccpars2_34_/1}). --file("expo_plural_forms_parser.yrl", 35). -yeccpars2_34_(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - operator(___1) - end | __Stack]. - --compile({inline,yeccpars2_35_/1}). --dialyzer({nowarn_function, yeccpars2_35_/1}). --compile({nowarn_unused_function, yeccpars2_35_/1}). --file("expo_plural_forms_parser.yrl", 38). -yeccpars2_35_(__Stack0) -> - [___1 | __Stack] = __Stack0, - [begin - operator(___1) - end | __Stack]. - --compile({inline,yeccpars2_36_/1}). --dialyzer({nowarn_function, yeccpars2_36_/1}). --compile({nowarn_unused_function, yeccpars2_36_/1}). --file("expo_plural_forms_parser.yrl", 25). -yeccpars2_36_(__Stack0) -> - [___5,___4,___3,___2,___1 | __Stack] = __Stack0, - [begin - {'if', ___1, ___3, ___5} - end | __Stack]. - --compile({inline,yeccpars2_37_/1}). --dialyzer({nowarn_function, yeccpars2_37_/1}). --compile({nowarn_unused_function, yeccpars2_37_/1}). --file("expo_plural_forms_parser.yrl", 28). -yeccpars2_37_(__Stack0) -> - [___3,___2,___1 | __Stack] = __Stack0, - [begin - {'%', ___1, ___3} - end | __Stack]. - --compile({inline,yeccpars2_38_/1}). --dialyzer({nowarn_function, yeccpars2_38_/1}). --compile({nowarn_unused_function, yeccpars2_38_/1}). --file("expo_plural_forms_parser.yrl", 21). -yeccpars2_38_(__Stack0) -> - [___3,___2,___1 | __Stack] = __Stack0, - [begin - {___2, ___1, ___3} - end | __Stack]. - --compile({inline,yeccpars2_39_/1}). --dialyzer({nowarn_function, yeccpars2_39_/1}). --compile({nowarn_unused_function, yeccpars2_39_/1}). --file("expo_plural_forms_parser.yrl", 22). -yeccpars2_39_(__Stack0) -> - [___3,___2,___1 | __Stack] = __Stack0, - [begin - {___2, ___1, ___3} - end | __Stack]. - --compile({inline,yeccpars2_40_/1}). --dialyzer({nowarn_function, yeccpars2_40_/1}). --compile({nowarn_unused_function, yeccpars2_40_/1}). --file("expo_plural_forms_parser.yrl", 32). -yeccpars2_40_(__Stack0) -> - [___3,___2,___1 | __Stack] = __Stack0, - [begin - ___2 - end | __Stack]. - --compile({inline,yeccpars2_41_/1}). --dialyzer({nowarn_function, yeccpars2_41_/1}). --compile({nowarn_unused_function, yeccpars2_41_/1}). --file("expo_plural_forms_parser.yrl", 26). -yeccpars2_41_(__Stack0) -> - [___3,___2,___1 | __Stack] = __Stack0, - [begin - {paren, ___2} - end | __Stack]. - --compile({inline,yeccpars2_42_/1}). --dialyzer({nowarn_function, yeccpars2_42_/1}). --compile({nowarn_unused_function, yeccpars2_42_/1}). --file("expo_plural_forms_parser.yrl", 15). -yeccpars2_42_(__Stack0) -> - [___8,___7,___6,___5,___4,___3,___2,___1 | __Stack] = __Stack0, - [begin - {value(___3), ___7} - end | __Stack]. - - --file("expo_plural_forms_parser.yrl", 53). diff --git a/gleam.toml b/gleam.toml index 548e219..a9dcf0d 100644 --- a/gleam.toml +++ b/gleam.toml @@ -15,6 +15,7 @@ target = "javascript" [dependencies] gleam_stdlib = ">= 0.34.0 and < 2.0.0" +nibble = ">= 1.1.1 and < 2.0.0" [dev-dependencies] gleeunit = ">= 1.0.0 and < 2.0.0" diff --git a/manifest.toml b/manifest.toml index 25ff755..f7ff669 100644 --- a/manifest.toml +++ b/manifest.toml @@ -5,10 +5,12 @@ packages = [ { name = "filepath", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "EFB6FF65C98B2A16378ABC3EE2B14124168C0CE5201553DE652E2644DCFDB594" }, { name = "gleam_stdlib", version = "0.37.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "5398BD6C2ABA17338F676F42F404B9B7BABE1C8DC7380031ACB05BBE1BCF3742" }, { name = "gleeunit", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "72CDC3D3F719478F26C4E2C5FED3E657AC81EC14A47D2D2DEBB8693CA3220C3B" }, + { name = "nibble", version = "1.1.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "nibble", source = "hex", outer_checksum = "67C6BEBC1AB6D771AB893B4A7B3E66C92668C6E7774C335FEFCD545B06435FE5" }, { name = "simplifile", version = "1.7.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "1D5DFA3A2F9319EC85825F6ED88B8E449F381B0D55A62F5E61424E748E7DDEB0" }, ] [requirements] gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" } gleeunit = { version = ">= 1.0.0 and < 2.0.0" } +nibble = { version = ">= 1.1.1 and < 2.0.0"} simplifile = { version = ">= 1.7.0 and < 2.0.0" } diff --git a/src/kielet.gleam b/src/kielet.gleam index ea59ec6..aaf894e 100644 --- a/src/kielet.gleam +++ b/src/kielet.gleam @@ -1,8 +1,25 @@ import gleam/io +import gleam/result import kielet/database.{type Database} +import kielet/plurals/parser +import kielet/plurals/tokenizer +import nibble pub fn main() { - io.println("Hello from kielet!") + let _ = + "nplurals=2; plural=n != 1;" + |> tokenizer.tokenize() + |> result.unwrap([]) + |> nibble.run(parser.main()) + |> io.debug() + + "nplurals=6; + plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 + : n%100>=11 ? 4 : 5;" + |> tokenizer.tokenize() + |> result.unwrap([]) + |> nibble.run(parser.main()) + |> io.debug() } pub fn gettext(db: Database, msgid: String, language_code: String) -> String { diff --git a/src/kielet/plurals.gleam b/src/kielet/plurals.gleam new file mode 100644 index 0000000..40ebace --- /dev/null +++ b/src/kielet/plurals.gleam @@ -0,0 +1,27 @@ +import gleam/result +import kielet/plurals/ast +import kielet/plurals/parser +import kielet/plurals/syntax_error +import kielet/plurals/tokenizer +import nibble + +pub type ParseError { + TokenizerError(err: syntax_error.SyntaxError) + ParserError(err: List(nibble.DeadEnd(tokenizer.Token, Nil))) +} + +pub type Plurals { + Plurals(total: Int, algorithm: ast.Ast) +} + +pub fn parse(input: String) { + use tokens <- result.try( + tokenizer.tokenize(input) + |> result.map_error(TokenizerError), + ) + use #(total, ast) <- result.try( + parser.parse(tokens) + |> result.map_error(ParserError), + ) + Ok(Plurals(total: total, algorithm: ast)) +} diff --git a/src/kielet/plurals/ast.gleam b/src/kielet/plurals/ast.gleam new file mode 100644 index 0000000..a3858e5 --- /dev/null +++ b/src/kielet/plurals/ast.gleam @@ -0,0 +1,19 @@ +pub type BinOp { + Equal + NotEqual + GreaterThan + GreaterThanOrEqual + LowerThan + LowerThanOrEqual + Remainder + And + Or +} + +pub type Ast { + N + Integer(Int) + BinaryOperation(operator: BinOp, lvalue: Ast, rvalue: Ast) + If(condition: Ast, truthy: Ast, falsy: Ast) + Paren(Ast) +} diff --git a/src/kielet/plurals/evaluator.gleam b/src/kielet/plurals/evaluator.gleam new file mode 100644 index 0000000..3900b80 --- /dev/null +++ b/src/kielet/plurals/evaluator.gleam @@ -0,0 +1,38 @@ +import kielet/plurals/ast + +pub fn eval(ast: ast.Ast, input: Int) { + case ast { + ast.N -> input + ast.Integer(i) -> i + ast.If(condition, truthy, falsy) -> { + let ast = case eval(condition, input) { + 1 -> truthy + _ -> falsy + } + eval(ast, input) + } + ast.Paren(content) -> eval(content, input) + ast.BinaryOperation(operator, lvalue, rvalue) -> { + let lvalue = eval(lvalue, input) + let rvalue = eval(rvalue, input) + case operator { + ast.Equal -> bool_to_int(lvalue == rvalue) + ast.NotEqual -> bool_to_int(lvalue != rvalue) + ast.GreaterThan -> bool_to_int(lvalue > rvalue) + ast.GreaterThanOrEqual -> bool_to_int(lvalue >= rvalue) + ast.LowerThan -> bool_to_int(lvalue < rvalue) + ast.LowerThanOrEqual -> bool_to_int(lvalue <= rvalue) + ast.Remainder -> lvalue % rvalue + ast.And -> bool_to_int(lvalue == 1 && rvalue == 1) + ast.Or -> bool_to_int(lvalue == 1 || rvalue == 1) + } + } + } +} + +fn bool_to_int(bool: Bool) { + case bool { + True -> 1 + False -> 0 + } +} diff --git a/src/kielet/plurals/parser.gleam b/src/kielet/plurals/parser.gleam new file mode 100644 index 0000000..698f801 --- /dev/null +++ b/src/kielet/plurals/parser.gleam @@ -0,0 +1,128 @@ +import gleam/option +import kielet/plurals/ast +import kielet/plurals/tokenizer +import nibble +import nibble/lexer +import nibble/pratt + +pub fn parse(input: List(lexer.Token(tokenizer.Token))) { + nibble.run(input, main()) +} + +pub fn main() { + use _ <- nibble.do(nibble.token(tokenizer.NPlurals)) + use _ <- nibble.do(nibble.token(tokenizer.Assignment)) + use nplurals <- nibble.do(int_parser()) + use _ <- nibble.do(nibble.token(tokenizer.Semicolon)) + use _ <- nibble.do(nibble.token(tokenizer.Plural)) + use _ <- nibble.do(nibble.token(tokenizer.Assignment)) + use ast <- nibble.do(plurals_parser()) + use _ <- nibble.do(nibble.optional(nibble.token(tokenizer.Semicolon))) + use _ <- nibble.do(nibble.token(tokenizer.End)) + use _ <- nibble.do(nibble.eof()) + + let assert ast.Integer(nplurals) = nplurals + + nibble.return(#(nplurals, ast)) +} + +fn plurals_parser() { + use maybe_cond <- nibble.do(expr_parser()) + + nibble.one_of([rest_of_ternary_parser(maybe_cond), nibble.return(maybe_cond)]) +} + +fn expr_parser() { + pratt.expression( + one_of: [ + fn(_) { int_parser() }, + fn(_) { n_parser() }, + fn(c) { paren_parser(c) }, + ], + and_then: [ + pratt.infix_left(200, nibble.token(tokenizer.And), fn(l, r) { + ast.BinaryOperation(ast.And, l, r) + }), + pratt.infix_left(200, nibble.token(tokenizer.Or), fn(l, r) { + ast.BinaryOperation(ast.Or, l, r) + }), + pratt.infix_left(300, nibble.token(tokenizer.Equals), fn(l, r) { + ast.BinaryOperation(ast.Equal, l, r) + }), + pratt.infix_left(300, nibble.token(tokenizer.NotEquals), fn(l, r) { + ast.BinaryOperation(ast.NotEqual, l, r) + }), + pratt.infix_left(300, nibble.token(tokenizer.GreaterThan), fn(l, r) { + ast.BinaryOperation(ast.GreaterThan, l, r) + }), + pratt.infix_left(300, nibble.token(tokenizer.LowerThan), fn(l, r) { + ast.BinaryOperation(ast.LowerThan, l, r) + }), + pratt.infix_left( + 300, + nibble.token(tokenizer.GreaterThanOrEquals), + fn(l, r) { ast.BinaryOperation(ast.GreaterThanOrEqual, l, r) }, + ), + pratt.infix_left(300, nibble.token(tokenizer.LowerThanOrEquals), fn(l, r) { + ast.BinaryOperation(ast.LowerThanOrEqual, l, r) + }), + pratt.infix_right(400, nibble.token(tokenizer.Remainder), fn(l, r) { + ast.BinaryOperation(ast.Remainder, l, r) + }), + ], + dropping: nibble.return(Nil), + ) +} + +fn paren_parser(c) { + use _ <- nibble.do(lparen_parser()) + use expr <- nibble.do(pratt.sub_expression(c, 0)) + use _ <- nibble.do(rparen_parser()) + + nibble.return(ast.Paren(expr)) +} + +fn rest_of_ternary_parser(cond: ast.Ast) { + use _ <- nibble.do(nibble.token(tokenizer.Ternary)) + use if_true <- nibble.do(plurals_parser()) + use _ <- nibble.do(nibble.token(tokenizer.TernaryElse)) + use if_false <- nibble.do(plurals_parser()) + + nibble.return(ast.If(cond, if_true, if_false)) +} + +fn int_parser() { + use tok <- nibble.take_map("An integer") + + case tok { + tokenizer.Int(i) -> option.Some(ast.Integer(i)) + _ -> option.None + } +} + +fn n_parser() { + use tok <- nibble.take_map("n") + + case tok { + tokenizer.N -> option.Some(ast.N) + _ -> option.None + } +} + +fn lparen_parser() { + use tok <- nibble.take_map("Left parenthesis") + + case tok { + tokenizer.LParen -> option.Some(Nil) + _ -> option.None + } +} + +fn rparen_parser() { + use tok <- nibble.take_map("Right parenthesis") + + case tok { + tokenizer.RParen -> option.Some(Nil) + _ -> option.None + } +} diff --git a/src/kielet/plurals/parser.notgleam b/src/kielet/plurals/parser.notgleam deleted file mode 100644 index f2c129f..0000000 --- a/src/kielet/plurals/parser.notgleam +++ /dev/null @@ -1,148 +0,0 @@ -import gleam/result -import kielet/plurals/syntax_error -import kielet/plurals/tokenizer - -pub type ParseError { - SyntaxError(err: syntax_error.SyntaxError) -} - -pub type PluralForms { - PluralForms(nplurals: Int, ast: Ast) -} - -type BinOp { - Equal - NotEqual - GreaterThan - GreaterThanOrEqual - LowerThan - LowerThanOrEqual - Remainder - And - Or -} - -pub opaque type Ast { - N - Integer(Int) - BinaryOperation(operator: BinOp, lvalue: Ast, rvalue: Ast) - If(condition: Ast, truthy: Ast, falsy: Ast) - Paren(Ast) -} - -pub fn parse(rules: String) { - use tokens <- result.try( - tokenizer.tokenize(rules) - |> result.map_error(SyntaxError), - ) - - do_parse(tokens) -} - -fn eval_ast(ast: Ast, input: Int) { - case ast { - N -> input - Integer(i) -> i - If(condition, truthy, falsy) -> { - let ast = case eval_ast(condition, input) { - 1 -> truthy - _ -> falsy - } - eval_ast(ast, input) - } - Paren(content) -> eval_ast(content, input) - BinaryOperation(operator, lvalue, rvalue) -> { - let lvalue = eval_ast(lvalue, input) - let rvalue = eval_ast(rvalue, input) - case operator { - Equal -> bool_to_int(lvalue == rvalue) - NotEqual -> bool_to_int(lvalue != rvalue) - GreaterThan -> bool_to_int(lvalue > rvalue) - GreaterThanOrEqual -> bool_to_int(lvalue >= rvalue) - LowerThan -> bool_to_int(lvalue < rvalue) - LowerThanOrEqual -> bool_to_int(lvalue <= rvalue) - Remainder -> lvalue % rvalue - And -> bool_to_int(lvalue == 1 && rvalue == 1) - Or -> bool_to_int(lvalue == 1 || rvalue == 1) - } - } - } -} - -fn bool_to_int(bool: Bool) { - case bool { - True -> 1 - False -> 0 - } -} - -type Location { - NoLocation - Line(Int) -} - -fn do_parse(tokens: List(tokenizer.Token)) { - yeccpars0(tokens, NoLocation, 0, [], []) -} - -fn yeccpars0( - tokens: List(tokenizer.Token), - location: Location, - state: Int, - states: List(Int), - vstack: List(tokenizer.Token), -) { - yeccpars1(tokens, location, state, states, vstack) -} - -fn yeccpars1( - tokens: List(tokenizer.Token), - location: Location, - state: Int, - states: List(Int), - vstack: List(tokenizer.Token), -) { - case tokens { - [token, ..rest] -> - yeccpars2(state, token, states, vstack, token, rest, location) - [] -> - case location { - NoLocation -> - yeccpars2( - state, - tokenizer.End, - states, - vstack, - #(tokenizer.End, 999_999), - [], - 999_999, - ) - Line(line) -> - yeccpars2( - state, - tokenizer.End, - states, - vstac, - #(tokenizer.End, line), - [], - line, - ) - } - } -} - -fn yeccpars1_2(state1, state, states, vstack, token0, tokens, location) { - case tokens { - [token, ..rest] -> - yeccpars2( - state, - token, - [state1, ..states], - [token0, ..vstack], - token, - rest, - location, - ) - [] -> yeccpars2() - } -} diff --git a/src/kielet/plurals/tokenizer.gleam b/src/kielet/plurals/tokenizer.gleam index 59e09da..6635ed1 100644 --- a/src/kielet/plurals/tokenizer.gleam +++ b/src/kielet/plurals/tokenizer.gleam @@ -3,13 +3,9 @@ import gleam/list import gleam/option import gleam/string import kielet/plurals/syntax_error.{SyntaxError} +import nibble/lexer pub type Token { - Token(type_: TokenType, line: Int) - Int(value: Int, line: Int) -} - -pub type TokenType { N NPlurals Plural @@ -29,58 +25,137 @@ pub type TokenType { LParen RParen End + Int(value: Int) } +pub type TokenType + pub fn tokenize(str: String) { do_tokenize(string.to_graphemes(str), [], 1, 1) } -fn do_tokenize(str: List(String), acc: List(Token), line: Int, col: Int) { +fn do_tokenize( + str: List(String), + acc: List(lexer.Token(Token)), + line: Int, + col: Int, +) { case str { - [] -> Ok(list.reverse([Token(End, line), ..acc])) + [] -> Ok(list.reverse([to_nibble(End, "", line, col), ..acc])) ["n", "p", "l", "u", "r", "a", "l", "s", ..rest] -> - do_tokenize(rest, [Token(NPlurals, line), ..acc], line, col + 8) + do_tokenize( + rest, + [to_nibble(NPlurals, "nplurals", line, col), ..acc], + line, + col + 8, + ) ["p", "l", "u", "r", "a", "l", ..rest] -> - do_tokenize(rest, [Token(Plural, line), ..acc], line, col + 6) - ["n", ..rest] -> do_tokenize(rest, [Token(N, line), ..acc], line, col + 1) + do_tokenize( + rest, + [to_nibble(Plural, "plural", line, col), ..acc], + line, + col + 6, + ) + ["n", ..rest] -> + do_tokenize(rest, [to_nibble(N, "n", line, col), ..acc], line, col + 1) ["\\", "\n", ..rest] -> do_tokenize(rest, acc, line + 1, 1) ["\n", ..rest] -> do_tokenize(rest, acc, line + 1, 1) [" ", ..rest] -> do_tokenize(rest, acc, line, col + 1) ["=", "=", ..rest] -> - do_tokenize(rest, [Token(Equals, line), ..acc], line, col + 2) + do_tokenize( + rest, + [to_nibble(Equals, "==", line, col), ..acc], + line, + col + 2, + ) ["!", "=", ..rest] -> - do_tokenize(rest, [Token(NotEquals, line), ..acc], line, col + 2) + do_tokenize( + rest, + [to_nibble(NotEquals, "!=", line, col), ..acc], + line, + col + 2, + ) [">", "=", ..rest] -> do_tokenize( rest, - [Token(GreaterThanOrEquals, line), ..acc], + [to_nibble(GreaterThanOrEquals, ">=", line, col), ..acc], line, col + 2, ) ["<", "=", ..rest] -> - do_tokenize(rest, [Token(LowerThanOrEquals, line), ..acc], line, col + 2) + do_tokenize( + rest, + [to_nibble(LowerThanOrEquals, "<=", line, col), ..acc], + line, + col + 2, + ) [">", ..rest] -> - do_tokenize(rest, [Token(GreaterThan, line), ..acc], line, col + 1) + do_tokenize( + rest, + [to_nibble(GreaterThan, ">", line, col), ..acc], + line, + col + 1, + ) ["<", ..rest] -> - do_tokenize(rest, [Token(LowerThan, line), ..acc], line, col + 1) + do_tokenize( + rest, + [to_nibble(LowerThan, "<", line, col), ..acc], + line, + col + 1, + ) ["=", ..rest] -> - do_tokenize(rest, [Token(Assignment, line), ..acc], line, col + 1) + do_tokenize( + rest, + [to_nibble(Assignment, "=", line, col), ..acc], + line, + col + 1, + ) ["?", ..rest] -> - do_tokenize(rest, [Token(Ternary, line), ..acc], line, col + 1) + do_tokenize( + rest, + [to_nibble(Ternary, "?", line, col), ..acc], + line, + col + 1, + ) [":", ..rest] -> - do_tokenize(rest, [Token(TernaryElse, line), ..acc], line, col + 1) + do_tokenize( + rest, + [to_nibble(TernaryElse, ":", line, col), ..acc], + line, + col + 1, + ) ["%", ..rest] -> - do_tokenize(rest, [Token(Remainder, line), ..acc], line, col + 1) + do_tokenize( + rest, + [to_nibble(Remainder, "%", line, col), ..acc], + line, + col + 1, + ) ["|", "|", ..rest] -> - do_tokenize(rest, [Token(Or, line), ..acc], line, col + 2) + do_tokenize(rest, [to_nibble(Or, "||", line, col), ..acc], line, col + 2) ["&", "&", ..rest] -> - do_tokenize(rest, [Token(And, line), ..acc], line, col + 2) + do_tokenize(rest, [to_nibble(And, "&&", line, col), ..acc], line, col + 2) [";", ..rest] -> - do_tokenize(rest, [Token(Semicolon, line), ..acc], line, col + 1) + do_tokenize( + rest, + [to_nibble(Semicolon, ";", line, col), ..acc], + line, + col + 1, + ) [")", ..rest] -> - do_tokenize(rest, [Token(RParen, line), ..acc], line, col + 1) + do_tokenize( + rest, + [to_nibble(RParen, ")", line, col), ..acc], + line, + col + 1, + ) ["(", ..rest] -> - do_tokenize(rest, [Token(LParen, line), ..acc], line, col + 1) + do_tokenize( + rest, + [to_nibble(LParen, "(", line, col), ..acc], + line, + col + 1, + ) [digit, ..rest] if digit == "0" || digit == "1" || digit == "2" @@ -102,7 +177,7 @@ fn do_tokenize(str: List(String), acc: List(Token), line: Int, col: Int) { fn read_digits( str: List(String), - acc: List(Token), + acc: List(lexer.Token(Token)), line: Int, col: Int, digit_acc: String, @@ -125,7 +200,7 @@ fn read_digits( Ok(int) -> do_tokenize( other, - [Int(int, line), ..acc], + [to_nibble(Int(int), digit_acc, line, col), ..acc], line, col + string.length(digit_acc), ) @@ -138,3 +213,16 @@ fn read_digits( } } } + +fn to_nibble(token: Token, lexeme: String, line: Int, col: Int) { + lexer.Token( + span: lexer.Span( + row_start: line, + row_end: line, + col_start: col, + col_end: col + string.length(lexeme), + ), + lexeme: lexeme, + value: token, + ) +} diff --git a/test/plurals_test.gleam b/test/plurals_test.gleam new file mode 100644 index 0000000..25d7413 --- /dev/null +++ b/test/plurals_test.gleam @@ -0,0 +1,184 @@ +import gleeunit/should +import kielet/plurals +import kielet/plurals/evaluator + +pub fn parenthesized_test() { + let input = "nplurals=1; plural=(n==1);" + should.be_ok(plurals.parse(input)) +} + +pub fn parenthesized_with_ternary_test() { + let input = "nplurals=1; plural=(n==1 ? 1 : 0);" + should.be_ok(plurals.parse(input)) +} + +pub fn no_ending_semicolon_test() { + let input = "nplurals=1; plural=0" + let assert Ok(plurals) = plurals.parse(input) + should.equal(plurals.total, 1) +} + +pub fn linefeed_test() { + let input = + "nplurals=1; + plural=0;" + let assert Ok(plurals) = plurals.parse(input) + should.equal(plurals.total, 1) +} + +pub fn linefeed_with_backslash_test() { + let input = + "nplurals=1; \\ + plural=0;" + let assert Ok(plurals) = plurals.parse(input) + should.equal(plurals.total, 1) +} + +pub fn one_test() { + let input = "nplurals=1; plural=0;" + let assert Ok(plurals) = plurals.parse(input) + should.equal(plurals.total, 1) + should.equal(evaluator.eval(plurals.algorithm, 1), 0) + should.equal(evaluator.eval(plurals.algorithm, 0), 0) + should.equal(evaluator.eval(plurals.algorithm, 8), 0) +} + +pub fn two_test() { + let input = "nplurals=2; plural=n != 1;" + let assert Ok(plurals) = plurals.parse(input) + should.equal(plurals.total, 2) + should.equal(evaluator.eval(plurals.algorithm, 0), 1) + should.equal(evaluator.eval(plurals.algorithm, 1), 0) + should.equal(evaluator.eval(plurals.algorithm, 2), 1) +} + +pub fn two_french_test() { + let input = "nplurals=2; plural=n>1;" + let assert Ok(plurals) = plurals.parse(input) + should.equal(plurals.total, 2) + should.equal(evaluator.eval(plurals.algorithm, 0), 0) + should.equal(evaluator.eval(plurals.algorithm, 1), 0) + should.equal(evaluator.eval(plurals.algorithm, 2), 1) +} + +pub fn latvian_test() { + let input = "nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2;" + let assert Ok(plurals) = plurals.parse(input) + should.equal(plurals.total, 3) + should.equal(evaluator.eval(plurals.algorithm, 0), 2) + should.equal(evaluator.eval(plurals.algorithm, 1), 0) + should.equal(evaluator.eval(plurals.algorithm, 2), 1) + should.equal(evaluator.eval(plurals.algorithm, 111), 1) + should.equal(evaluator.eval(plurals.algorithm, 112), 1) + should.equal(evaluator.eval(plurals.algorithm, 31), 0) + should.equal(evaluator.eval(plurals.algorithm, 9), 1) +} + +pub fn gaeilge_test() { + let input = "nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;" + let assert Ok(plurals) = plurals.parse(input) + should.equal(plurals.total, 3) + should.equal(evaluator.eval(plurals.algorithm, 1), 0) + should.equal(evaluator.eval(plurals.algorithm, 2), 1) + should.equal(evaluator.eval(plurals.algorithm, 0), 2) + should.equal(evaluator.eval(plurals.algorithm, 10), 2) +} + +pub fn gaeilge_alternate_test() { + let input = + "nplurals=5; plural=n == 1 ? 0 : n == 2 ? 1 : n >= 3 && n <= 6 ? 2 : n >= 7 && n <= 10 ? 3 : 4;" + let assert Ok(plurals) = plurals.parse(input) + should.equal(plurals.total, 5) + should.equal(evaluator.eval(plurals.algorithm, 1), 0) + should.equal(evaluator.eval(plurals.algorithm, 2), 1) + should.equal(evaluator.eval(plurals.algorithm, 4), 2) + should.equal(evaluator.eval(plurals.algorithm, 10), 3) + should.equal(evaluator.eval(plurals.algorithm, 133), 4) +} + +pub fn romanian_test() { + let input = + "nplurals=3; \\ + plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2;" + let assert Ok(plurals) = plurals.parse(input) + should.equal(plurals.total, 3) + should.equal(evaluator.eval(plurals.algorithm, 1), 0) + should.equal(evaluator.eval(plurals.algorithm, 0), 1) + should.equal(evaluator.eval(plurals.algorithm, 119), 1) + should.equal(evaluator.eval(plurals.algorithm, 121), 2) + should.equal(evaluator.eval(plurals.algorithm, 19), 1) + should.equal(evaluator.eval(plurals.algorithm, 80), 2) +} + +pub fn lithuanian_test() { + let input = + "nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2;" + should.be_ok(plurals.parse(input)) + let assert Ok(plurals) = plurals.parse(input) + should.equal(plurals.total, 3) + should.equal(evaluator.eval(plurals.algorithm, 81), 0) + should.equal(evaluator.eval(plurals.algorithm, 872), 1) + should.equal(evaluator.eval(plurals.algorithm, 112), 2) +} + +pub fn ukrainian_test() { + let input = + "nplurals=3; + plural=n%10==1 && n%100!=11 ? 0 : + n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;" + let assert Ok(plurals) = plurals.parse(input) + should.equal(plurals.total, 3) + should.equal(evaluator.eval(plurals.algorithm, 21), 0) + should.equal(evaluator.eval(plurals.algorithm, 42), 1) + should.equal(evaluator.eval(plurals.algorithm, 11), 2) +} + +pub fn czech_test() { + let input = + "nplurals=3; + plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;" + let assert Ok(plurals) = plurals.parse(input) + should.equal(plurals.total, 3) + should.equal(evaluator.eval(plurals.algorithm, 1), 0) + should.equal(evaluator.eval(plurals.algorithm, 3), 1) + should.equal(evaluator.eval(plurals.algorithm, 12), 2) +} + +pub fn polish_test() { + let input = + "nplurals=3; + plural=n==1 ? 0 : + n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;" + let assert Ok(plurals) = plurals.parse(input) + should.equal(plurals.total, 3) + should.equal(evaluator.eval(plurals.algorithm, 1), 0) + should.equal(evaluator.eval(plurals.algorithm, 102), 1) + should.equal(evaluator.eval(plurals.algorithm, 713), 2) +} + +pub fn slovenian_test() { + let input = + "nplurals=4; + plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3;" + let assert Ok(plurals) = plurals.parse(input) + should.equal(plurals.total, 4) + should.equal(evaluator.eval(plurals.algorithm, 320), 3) + should.equal(evaluator.eval(plurals.algorithm, 101), 0) + should.equal(evaluator.eval(plurals.algorithm, 202), 1) + should.equal(evaluator.eval(plurals.algorithm, 303), 2) +} + +pub fn arabic_test() { + let input = + "nplurals=6; + plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 + : n%100>=11 ? 4 : 5;" + let assert Ok(plurals) = plurals.parse(input) + should.equal(plurals.total, 6) + should.equal(evaluator.eval(plurals.algorithm, 0), 0) + should.equal(evaluator.eval(plurals.algorithm, 1), 1) + should.equal(evaluator.eval(plurals.algorithm, 2), 2) + should.equal(evaluator.eval(plurals.algorithm, 505), 3) + should.equal(evaluator.eval(plurals.algorithm, 733), 4) + should.equal(evaluator.eval(plurals.algorithm, 101), 5) +}