Initial import of Sbeezg version 1.0 revision 2002.0317 sources.
Cat's Eye Technologies
12 years ago
0 | The Sbeezg Programming Language v2002.0317 | |
1 | ------------------------------- | |
2 | ||
3 | Sbeezg is single-assignment programming taken to the extreme. Each variable | |
4 | may only be assigned once. There is no scope. When a function is executed, | |
5 | a new copy of it is made, with all bound variable names altered to fresh ones, | |
6 | and this is executed instead. Execution is sequential in nature. Arguments | |
7 | and return value are given explicitly. There are no global names; there are | |
8 | only lambda function definitions available. There are five built-in operations. | |
9 | For convenience, there are three data types: atoms, integers, and closures. | |
10 | ||
11 | Here is a brief EBNF rundown of the syntax: | |
12 | ||
13 | Appl ::= Name "=" Val "(" Val {"," Val} ")". | |
14 | Val ::= Name | "*" Const | "{" Name {"," Name} "|" Appl {";" Appl} "|" Name "}". | |
15 | ||
16 | A program is an application, which consists of an assignment to a new (never | |
17 | before named in the program) variable, of a value or the result of a function | |
18 | call. Note that the arguments of a function call may only be simple values; | |
19 | further nested function calls are disallowed as their implicit 'piping' of | |
20 | values from one function to the next without an intervening variable name is | |
21 | counter to the intention of this purely single-assignment language. | |
22 | ||
23 | This documentation isn't really complete. | |
24 | ||
25 | Chris Pressey | |
26 | March 17 2002 | |
27 | Winnipeg, Manitoba |
0 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | |
1 | <html> | |
2 | <head> | |
3 | <title>Module sbeezg</title> | |
4 | </head> | |
5 | <body bgcolor="white"> | |
6 | <h1>Module sbeezg</h1> | |
7 | <ul><li> | |
8 | <a href="#index">Function index</a></li><li> | |
9 | <a href="#exported">Exported functions</a></li></ul> | |
10 | ||
11 | <h2>Description</h2> | |
12 | ||
13 | ||
14 | <h2><a name="index">Function Index</a></h2> | |
15 | ||
16 | <table width="100%" border="1"><tr><th colspan="2" align="left">Exported Functions</th></tr> | |
17 | <tr><td><a href="#run-1">run/1</a></td><td/></tr> | |
18 | <tr><td><a href="#test-1">test/1</a></td><td/></tr> | |
19 | </table> | |
20 | ||
21 | <h2><a name="exported">Exported Functions</a></h2> | |
22 | ||
23 | <h3><a name="run-1">run/1</a></h3> | |
24 | ||
25 | <p><code>run(Arg1) -> term()</code></p> | |
26 | <p> </p> | |
27 | ||
28 | <h3><a name="test-1">test/1</a></h3> | |
29 | ||
30 | <p><code>test(Arg1) -> term()</code></p> | |
31 | <p> </p></body> | |
32 | </html>⏎ |
0 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | |
1 | <html> | |
2 | <head> | |
3 | <title>Module sbeezg_parser</title> | |
4 | </head> | |
5 | <body bgcolor="white"> | |
6 | <h1>Module sbeezg_parser</h1> | |
7 | <ul><li> | |
8 | <a href="#index">Function index</a></li><li> | |
9 | <a href="#exported">Exported functions</a></li></ul> | |
10 | ||
11 | <h2>Description</h2> | |
12 | ||
13 | ||
14 | <h2><a name="index">Function Index</a></h2> | |
15 | ||
16 | <table width="100%" border="1"><tr><th colspan="2" align="left">Exported Functions</th></tr> | |
17 | <tr><td><a href="#format_error-1">format_error/1</a></td><td/></tr> | |
18 | <tr><td><a href="#parse-1">parse/1</a></td><td/></tr> | |
19 | <tr><td><a href="#parse_and_scan-1">parse_and_scan/1</a></td><td/></tr> | |
20 | </table> | |
21 | ||
22 | <h2><a name="exported">Exported Functions</a></h2> | |
23 | ||
24 | <h3><a name="format_error-1">format_error/1</a></h3> | |
25 | ||
26 | <p><code>format_error(Arg1) -> term()</code></p> | |
27 | <p> </p> | |
28 | ||
29 | <h3><a name="parse-1">parse/1</a></h3> | |
30 | ||
31 | <p><code>parse(Arg1) -> term()</code></p> | |
32 | <p> </p> | |
33 | ||
34 | <h3><a name="parse_and_scan-1">parse_and_scan/1</a></h3> | |
35 | ||
36 | <p><code>parse_and_scan(Arg1) -> term()</code></p> | |
37 | <p> </p></body> | |
38 | </html>⏎ |
0 | {application,sbeezg, | |
1 | [{description,"The Sbeezg Programming Language"}, | |
2 | {vsn,"2002.0317"}, | |
3 | {modules,[sbeezg, sbeezg_parser]}, | |
4 | {registered,[]}, | |
5 | {env,[]}, | |
6 | {applications,[kernel,stdlib]}]}. | |
7 |
Binary diff not shown
Binary diff not shown
0 | -module(sbeezg). | |
1 | -vsn('2002.0317'). | |
2 | -author('cpressey@catseye.mb.ca'). | |
3 | -copyright('Copyright (c)2002 Cat`s Eye Technologies. All rights reserved.'). | |
4 | ||
5 | %%% Redistribution and use in source and binary forms, with or without | |
6 | %%% modification, are permitted provided that the following conditions | |
7 | %%% are met: | |
8 | %%% | |
9 | %%% Redistributions of source code must retain the above copyright | |
10 | %%% notice, this list of conditions and the following disclaimer. | |
11 | %%% | |
12 | %%% Redistributions in binary form must reproduce the above copyright | |
13 | %%% notice, this list of conditions and the following disclaimer in | |
14 | %%% the documentation and/or other materials provided with the | |
15 | %%% distribution. | |
16 | %%% | |
17 | %%% Neither the name of Cat's Eye Technologies nor the names of its | |
18 | %%% contributors may be used to endorse or promote products derived | |
19 | %%% from this software without specific prior written permission. | |
20 | %%% | |
21 | %%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | |
22 | %%% CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, | |
23 | %%% INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
24 | %%% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
25 | %%% DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE | |
26 | %%% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, | |
27 | %%% OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
28 | %%% PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, | |
29 | %%% OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |
30 | %%% ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
31 | %%% OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
32 | %%% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
33 | %%% POSSIBILITY OF SUCH DAMAGE. | |
34 | ||
35 | -export([run/1, test/1]). | |
36 | ||
37 | %%% BEGIN sbeezg.erl %%% | |
38 | ||
39 | %%% A simple interpreter for the Sbeezg Programming Language. | |
40 | ||
41 | %% Interpreter --------------------------------------------------------- | |
42 | %% Call sbeezg:run("sbeezg-program") to interpret a Sbeezg program. | |
43 | %% Empties the process dictionary as a side effect. | |
44 | ||
45 | run(String) when list(String) -> | |
46 | {ok, Toks, N} = erl_scan:string(String), | |
47 | % io:fwrite("scan: ~s -> ~w~n", [String, Toks]), | |
48 | erase(), % clear process dictionary for parser | |
49 | case sbeezg_parser:parse(Toks ++ [{'$end',999}]) of | |
50 | {ok, Prog} -> | |
51 | % io:fwrite("parse: ~s -> ~w~n", [String, Prog]), | |
52 | erase(), % destroy the garbage left in the process dictionary | |
53 | run(Prog); | |
54 | {error, {Line, Module, Message}}=Q -> | |
55 | io:fwrite("Error: ~s~n", [Message]), | |
56 | Q | |
57 | end; | |
58 | run({assign, L, F, A}=C) -> | |
59 | % io:fwrite("~w~n", [C]), | |
60 | L0 = get_name(L), | |
61 | F0 = run(F), | |
62 | A0 = run(A), | |
63 | assign(L0, '$placeholder'), | |
64 | R0 = execute(F0, A0), | |
65 | assign(L0, R0); | |
66 | run({assign, L, R}=C) -> | |
67 | % io:fwrite("~w~n", [C]), | |
68 | L0 = get_name(L), | |
69 | R0 = run(R), | |
70 | assign(L0, R0); | |
71 | run({vlist, H, T}=C) -> | |
72 | % io:fwrite("~w~n", [C]), | |
73 | H0 = run(H), | |
74 | T0 = run(T), | |
75 | [H0 | T0]; | |
76 | run({lambda, N, A, R}=C) -> | |
77 | % io:fwrite("~w~n", [C]), | |
78 | {func, N, A, R}; | |
79 | run({alist, H, T}=C) -> | |
80 | % io:fwrite("~w~n", [C]), | |
81 | H0 = run(H), | |
82 | T0 = run(T), | |
83 | case T0 of | |
84 | [] -> H0; | |
85 | _ -> T0 | |
86 | end; | |
87 | run({lit,{atom,Line,Atom}}) -> Atom; | |
88 | run({lit,{integer,Line,Int}}) -> Int; | |
89 | run({name, {atom,Line,Atom}}) -> | |
90 | case get(Atom) of | |
91 | undefined -> | |
92 | io:fwrite("~w undefined!~n", [Atom]), | |
93 | Atom; | |
94 | N -> | |
95 | N | |
96 | end; | |
97 | run(nil) -> | |
98 | []; | |
99 | run(Q) -> | |
100 | io:fwrite("UNKNOWN ~w~n", [Q]), | |
101 | unknown. | |
102 | ||
103 | get_name({nlist, H, T}=C) -> | |
104 | % io:fwrite("~w~n", [C]), | |
105 | H0 = get_name(H), | |
106 | T0 = get_name(T), | |
107 | [H0 | T0]; | |
108 | get_name({name, {atom,Line,Atom}}) -> Atom; | |
109 | get_name(nil) -> []. | |
110 | ||
111 | %% Utility ------------------------------------------------------------- | |
112 | ||
113 | assign(Name, Value) -> | |
114 | % io:fwrite("Assigning ~w to ~w~n", [Value, Name]), | |
115 | case get(Name) of | |
116 | NonExist when NonExist == undefined; NonExist == '$placeholder' -> | |
117 | put(Name, Value); | |
118 | Exist -> | |
119 | io:fwrite("ERROR: Multiple Assignment to ~w=~w (~w)~n", | |
120 | [Name, Exist, Value]) | |
121 | end, | |
122 | Value. | |
123 | ||
124 | execute(print, [H | T]) -> | |
125 | io:fwrite("~w", [H]), | |
126 | execute(print, T); | |
127 | execute(print, []) -> ok; | |
128 | execute(is, [A, B, T, F]) -> | |
129 | % io:fwrite("~w", [C]), | |
130 | case A of | |
131 | B -> T; | |
132 | _ -> F | |
133 | end; | |
134 | execute(pred, [X]) -> | |
135 | % io:fwrite("pred ~w~n", [X]), | |
136 | X - 1; | |
137 | execute(succ, [X]) -> X + 1; | |
138 | execute(Func, Args) when atom(Func) -> | |
139 | io:fwrite("Unknown built-in '~w(~w)'~n", [Func, Args]), | |
140 | unknown; | |
141 | execute({func, P, B, R}, A) -> | |
142 | P0 = fresh(P), | |
143 | B0 = fresh(B), | |
144 | P1 = get_name(P0), | |
145 | bind(P1, A), | |
146 | run(B0), | |
147 | run(R). | |
148 | ||
149 | fresh({assign, L, F, A}=C) -> {assign, fresh(L), fresh(F), fresh(A)}; | |
150 | fresh({assign, L, R}=C) -> {assign, fresh(L), fresh(R)}; | |
151 | fresh({vlist, H, T}=C) -> {vlist, fresh(H), fresh(T)}; | |
152 | fresh({lambda, X, A}=C) -> {lambda, fresh(X), fresh(A)}; | |
153 | fresh({nlist, H, T}=C) -> {nlist, fresh(H), fresh(T)}; | |
154 | fresh({alist, H, T}=C) -> {alist, fresh(H), fresh(T)}; | |
155 | fresh({lit,X}=C) -> C; | |
156 | fresh({name,{atom,Line,Atom}}=C) -> | |
157 | case get(Atom) of | |
158 | undefined -> C; | |
159 | _ -> | |
160 | fresh({name, {atom, Line, list_to_atom([$_ | atom_to_list(Atom)])}}) | |
161 | end; | |
162 | fresh(X) -> X. | |
163 | ||
164 | bind([],[]) -> ok; | |
165 | bind([HN|TN],[HV|TV]) -> | |
166 | % io:fwrite("bind ~w to ~w~n", [HV,HN]), | |
167 | assign(HN,HV), | |
168 | bind(TN,TV). | |
169 | ||
170 | %% User interface ------------------------------------------------------ | |
171 | ||
172 | test([N]) -> test(list_to_integer(N)); | |
173 | test(N) -> | |
174 | R = run(prg(N)), | |
175 | E = erase(), | |
176 | {R, E}. | |
177 | ||
178 | prg(1) -> "a={b|p=*print;c=p(b)|b};d=a(*foo);e=a(*bar);f=a(*baz)"; | |
179 | prg(2) -> "a={b|p=*print;c=p(b)|b};d={e,f|g=e(f)|g};h=d(a,*hello)"; | |
180 | prg(3) -> "p=*print;i=*is;r=i(*a,*b,*troo,*fall);q=p(r)"; | |
181 | prg(4) -> "f={a,b|p=*print;g=p(a);k=b(a,b)|a};l=f(*hello,f)"; | |
182 | prg(5) -> "f={a,b|i=*is;s=*pred;p=*print;g=p(*beer);h=s(a);" | |
183 | "ln={x,m|z=x|x};lg={y,n|q=n(y,n)|y};j=i(h,0,ln,lg);" | |
184 | "k=j(h,b)|a};l=f(99,f)"; | |
185 | prg(6) -> "f=*a;f=*b"; % intentionally erroneous | |
186 | prg(_) -> unknown. | |
187 | ||
188 | %%% END of sbeezg.erl %%% |
0 | -module(sbeezg_parser). | |
1 | -define(THIS_MODULE, sbeezg_parser). | |
2 | -export([parse/1, parse_and_scan/1, format_error/1]). | |
3 | ||
4 | new_name({name,{atom,Line,Name}}=A) -> | |
5 | case get(A) of | |
6 | defn -> | |
7 | return_error(0, io_lib:format("Name '~w' already defined", [Name])); | |
8 | _ -> | |
9 | put(A, defn) | |
10 | end. | |
11 | ||
12 | existing_name({name,{atom,Line,Name}}=A) -> | |
13 | case get(A) of | |
14 | undefined -> | |
15 | return_error(0, io_lib:format("Name '~w' is not yet defined", [Name])); | |
16 | _ -> | |
17 | ok | |
18 | end. | |
19 | ||
20 | %%% END of sbeezg_parser.yrl %%% | |
21 | ||
22 | %% ``The contents of this file are subject to the Erlang Public License, | |
23 | %% Version 1.1, (the "License"); you may not use this file except in | |
24 | %% compliance with the License. You should have received a copy of the | |
25 | %% Erlang Public License along with this software. If not, it can be | |
26 | %% retrieved via the world wide web at http://www.erlang.org/. | |
27 | %% | |
28 | %% Software distributed under the License is distributed on an "AS IS" | |
29 | %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See | |
30 | %% the License for the specific language governing rights and limitations | |
31 | %% under the License. | |
32 | %% | |
33 | %% The Initial Developer of the Original Code is Ericsson Utvecklings AB. | |
34 | %% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings | |
35 | %% AB. All Rights Reserved.'' | |
36 | %% | |
37 | %% $Id$ | |
38 | %% | |
39 | ||
40 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
41 | % The parser generator will insert appropriate declarations before this line.% | |
42 | ||
43 | parse(Tokens) -> | |
44 | case catch yeccpars1(Tokens, false, 0, [], []) of | |
45 | error -> | |
46 | Errorline = | |
47 | if Tokens == [] -> 0; true -> element(2, hd(Tokens)) end, | |
48 | {error, | |
49 | {Errorline, ?THIS_MODULE, "syntax error at or after this line."}}; | |
50 | Other -> | |
51 | Other | |
52 | end. | |
53 | ||
54 | parse_and_scan({Mod, Fun, Args}) -> | |
55 | case apply(Mod, Fun, Args) of | |
56 | {eof, _} -> | |
57 | {ok, eof}; | |
58 | {error, Descriptor, _} -> | |
59 | {error, Descriptor}; | |
60 | {ok, Tokens, _} -> | |
61 | yeccpars1(Tokens, {Mod, Fun, Args}, 0, [], []) | |
62 | end. | |
63 | ||
64 | format_error(Message) -> | |
65 | case io_lib:deep_char_list(Message) of | |
66 | true -> | |
67 | Message; | |
68 | _ -> | |
69 | io_lib:write(Message) | |
70 | end. | |
71 | ||
72 | % To be used in grammar files to throw an error message to the parser toplevel. | |
73 | % Doesn't have to be exported! | |
74 | return_error(Line, Message) -> | |
75 | throw({error, {Line, ?THIS_MODULE, Message}}). | |
76 | ||
77 | ||
78 | % Don't change yeccpars1/6 too much, it is called recursively by yeccpars2/8! | |
79 | yeccpars1([Token | Tokens], Tokenizer, State, States, Vstack) -> | |
80 | yeccpars2(State, element(1, Token), States, Vstack, Token, Tokens, | |
81 | Tokenizer); | |
82 | yeccpars1([], {M, F, A}, State, States, Vstack) -> | |
83 | case catch apply(M, F, A) of | |
84 | {eof, Endline} -> | |
85 | {error, {Endline, ?THIS_MODULE, "end_of_file"}}; | |
86 | {error, Descriptor, Endline} -> | |
87 | {error, Descriptor}; | |
88 | {'EXIT', Reason} -> | |
89 | {error, {0, ?THIS_MODULE, Reason}}; | |
90 | {ok, Tokens, Endline} -> | |
91 | case catch yeccpars1(Tokens, {M, F, A}, State, States, Vstack) of | |
92 | error -> | |
93 | Errorline = element(2, hd(Tokens)), | |
94 | {error, {Errorline, ?THIS_MODULE, | |
95 | "syntax error at or after this line."}}; | |
96 | Other -> | |
97 | Other | |
98 | end | |
99 | end; | |
100 | yeccpars1([], false, State, States, Vstack) -> | |
101 | yeccpars2(State, '$end', States, Vstack, {'$end', 999999}, [], false). | |
102 | ||
103 | % For internal use only. | |
104 | yeccerror(Token) -> | |
105 | {error, | |
106 | {element(2, Token), ?THIS_MODULE, | |
107 | ["syntax error before: ", yecctoken2string(Token)]}}. | |
108 | ||
109 | yecctoken2string({atom, _, A}) -> io_lib:write(A); | |
110 | yecctoken2string({integer,_,N}) -> io_lib:write(N); | |
111 | yecctoken2string({float,_,F}) -> io_lib:write(F); | |
112 | yecctoken2string({char,_,C}) -> io_lib:write_char(C); | |
113 | yecctoken2string({var,_,V}) -> io_lib:format('~s', [V]); | |
114 | yecctoken2string({string,_,S}) -> io_lib:write_string(S); | |
115 | yecctoken2string({reserved_symbol, _, A}) -> io_lib:format('~w', [A]); | |
116 | yecctoken2string({Cat, _, Val}) -> io_lib:format('~w', [Val]); | |
117 | ||
118 | yecctoken2string({'dot', _}) -> io_lib:format('~w', ['.']); | |
119 | yecctoken2string({'$end', _}) -> | |
120 | []; | |
121 | yecctoken2string({Other, _}) when atom(Other) -> | |
122 | io_lib:format('~w', [Other]); | |
123 | yecctoken2string(Other) -> | |
124 | io_lib:write(Other). | |
125 | ||
126 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
127 | ||
128 | ||
129 | yeccpars2(0, atom, __Ss, __Stack, __T, __Ts, __Tzr) -> | |
130 | yeccpars1(__Ts, __Tzr, 3, [0 | __Ss], [__T | __Stack]); | |
131 | yeccpars2(0, _, _, _, __T, _, _) -> | |
132 | yeccerror(__T); | |
133 | yeccpars2(1, '$end', _, __Stack, _, _, _) -> | |
134 | {ok, hd(__Stack)}; | |
135 | yeccpars2(1, _, _, _, __T, _, _) -> | |
136 | yeccerror(__T); | |
137 | yeccpars2(2, ';', __Ss, __Stack, __T, __Ts, __Tzr) -> | |
138 | yeccpars1(__Ts, __Tzr, 27, [2 | __Ss], [__T | __Stack]); | |
139 | yeccpars2(2, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) -> | |
140 | __Val = {alist,__1,nil}, | |
141 | yeccpars2(yeccgoto(alist, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr); | |
142 | yeccpars2(3, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) -> | |
143 | __Val = {name,__1}, | |
144 | yeccpars2(yeccgoto(name, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr); | |
145 | yeccpars2(4, '=', __Ss, __Stack, __T, __Ts, __Tzr) -> | |
146 | yeccpars1(__Ts, __Tzr, 5, [4 | __Ss], [__T | __Stack]); | |
147 | yeccpars2(4, _, _, _, __T, _, _) -> | |
148 | yeccerror(__T); | |
149 | yeccpars2(5, atom, __Ss, __Stack, __T, __Ts, __Tzr) -> | |
150 | yeccpars1(__Ts, __Tzr, 3, [5 | __Ss], [__T | __Stack]); | |
151 | yeccpars2(5, integer, __Ss, __Stack, __T, __Ts, __Tzr) -> | |
152 | yeccpars1(__Ts, __Tzr, 7, [5 | __Ss], [__T | __Stack]); | |
153 | yeccpars2(5, '*', __Ss, __Stack, __T, __Ts, __Tzr) -> | |
154 | yeccpars1(__Ts, __Tzr, 6, [5 | __Ss], [__T | __Stack]); | |
155 | yeccpars2(5, '{', __Ss, __Stack, __T, __Ts, __Tzr) -> | |
156 | yeccpars1(__Ts, __Tzr, 10, [5 | __Ss], [__T | __Stack]); | |
157 | yeccpars2(5, _, _, _, __T, _, _) -> | |
158 | yeccerror(__T); | |
159 | yeccpars2(6, atom, __Ss, __Stack, __T, __Ts, __Tzr) -> | |
160 | yeccpars1(__Ts, __Tzr, 26, [6 | __Ss], [__T | __Stack]); | |
161 | yeccpars2(6, _, _, _, __T, _, _) -> | |
162 | yeccerror(__T); | |
163 | yeccpars2(7, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) -> | |
164 | __Val = {lit,__1}, | |
165 | yeccpars2(yeccgoto(val, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr); | |
166 | yeccpars2(8, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) -> | |
167 | __Val = begin | |
168 | existing_name(__1), __1 | |
169 | end, | |
170 | yeccpars2(yeccgoto(val, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr); | |
171 | yeccpars2(9, '(', __Ss, __Stack, __T, __Ts, __Tzr) -> | |
172 | yeccpars1(__Ts, __Tzr, 20, [9 | __Ss], [__T | __Stack]); | |
173 | yeccpars2(9, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) -> | |
174 | __Val = begin | |
175 | new_name(__1), {assign,__1,__3} | |
176 | end, | |
177 | __Nss = lists:nthtail(2, __Ss), | |
178 | yeccpars2(yeccgoto(appl, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr); | |
179 | yeccpars2(10, atom, __Ss, __Stack, __T, __Ts, __Tzr) -> | |
180 | yeccpars1(__Ts, __Tzr, 3, [10 | __Ss], [__T | __Stack]); | |
181 | yeccpars2(10, _, _, _, __T, _, _) -> | |
182 | yeccerror(__T); | |
183 | yeccpars2(11, ',', __Ss, __Stack, __T, __Ts, __Tzr) -> | |
184 | yeccpars1(__Ts, __Tzr, 18, [11 | __Ss], [__T | __Stack]); | |
185 | yeccpars2(11, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) -> | |
186 | __Val = begin | |
187 | new_name(__1), {nlist,__1,nil} | |
188 | end, | |
189 | yeccpars2(yeccgoto(nlist, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr); | |
190 | yeccpars2(12, '|', __Ss, __Stack, __T, __Ts, __Tzr) -> | |
191 | yeccpars1(__Ts, __Tzr, 13, [12 | __Ss], [__T | __Stack]); | |
192 | yeccpars2(12, _, _, _, __T, _, _) -> | |
193 | yeccerror(__T); | |
194 | yeccpars2(13, atom, __Ss, __Stack, __T, __Ts, __Tzr) -> | |
195 | yeccpars1(__Ts, __Tzr, 3, [13 | __Ss], [__T | __Stack]); | |
196 | yeccpars2(13, _, _, _, __T, _, _) -> | |
197 | yeccerror(__T); | |
198 | yeccpars2(14, '|', __Ss, __Stack, __T, __Ts, __Tzr) -> | |
199 | yeccpars1(__Ts, __Tzr, 15, [14 | __Ss], [__T | __Stack]); | |
200 | yeccpars2(14, _, _, _, __T, _, _) -> | |
201 | yeccerror(__T); | |
202 | yeccpars2(15, atom, __Ss, __Stack, __T, __Ts, __Tzr) -> | |
203 | yeccpars1(__Ts, __Tzr, 3, [15 | __Ss], [__T | __Stack]); | |
204 | yeccpars2(15, _, _, _, __T, _, _) -> | |
205 | yeccerror(__T); | |
206 | yeccpars2(16, '}', __Ss, __Stack, __T, __Ts, __Tzr) -> | |
207 | yeccpars1(__Ts, __Tzr, 17, [16 | __Ss], [__T | __Stack]); | |
208 | yeccpars2(16, _, _, _, __T, _, _) -> | |
209 | yeccerror(__T); | |
210 | yeccpars2(17, __Cat, __Ss, [__7,__6,__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) -> | |
211 | __Val = {lambda,__2,__4,__6}, | |
212 | __Nss = lists:nthtail(6, __Ss), | |
213 | yeccpars2(yeccgoto(val, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr); | |
214 | yeccpars2(18, atom, __Ss, __Stack, __T, __Ts, __Tzr) -> | |
215 | yeccpars1(__Ts, __Tzr, 3, [18 | __Ss], [__T | __Stack]); | |
216 | yeccpars2(18, _, _, _, __T, _, _) -> | |
217 | yeccerror(__T); | |
218 | yeccpars2(19, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) -> | |
219 | __Val = begin | |
220 | new_name(__1), {nlist,__1,__3} | |
221 | end, | |
222 | __Nss = lists:nthtail(2, __Ss), | |
223 | yeccpars2(yeccgoto(nlist, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr); | |
224 | yeccpars2(20, atom, __Ss, __Stack, __T, __Ts, __Tzr) -> | |
225 | yeccpars1(__Ts, __Tzr, 3, [20 | __Ss], [__T | __Stack]); | |
226 | yeccpars2(20, integer, __Ss, __Stack, __T, __Ts, __Tzr) -> | |
227 | yeccpars1(__Ts, __Tzr, 7, [20 | __Ss], [__T | __Stack]); | |
228 | yeccpars2(20, '*', __Ss, __Stack, __T, __Ts, __Tzr) -> | |
229 | yeccpars1(__Ts, __Tzr, 6, [20 | __Ss], [__T | __Stack]); | |
230 | yeccpars2(20, '{', __Ss, __Stack, __T, __Ts, __Tzr) -> | |
231 | yeccpars1(__Ts, __Tzr, 10, [20 | __Ss], [__T | __Stack]); | |
232 | yeccpars2(20, _, _, _, __T, _, _) -> | |
233 | yeccerror(__T); | |
234 | yeccpars2(21, ',', __Ss, __Stack, __T, __Ts, __Tzr) -> | |
235 | yeccpars1(__Ts, __Tzr, 24, [21 | __Ss], [__T | __Stack]); | |
236 | yeccpars2(21, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) -> | |
237 | __Val = {vlist,__1,nil}, | |
238 | yeccpars2(yeccgoto(vlist, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr); | |
239 | yeccpars2(22, ')', __Ss, __Stack, __T, __Ts, __Tzr) -> | |
240 | yeccpars1(__Ts, __Tzr, 23, [22 | __Ss], [__T | __Stack]); | |
241 | yeccpars2(22, _, _, _, __T, _, _) -> | |
242 | yeccerror(__T); | |
243 | yeccpars2(23, __Cat, __Ss, [__6,__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) -> | |
244 | __Val = begin | |
245 | new_name(__1), {assign,__1,__3,__5} | |
246 | end, | |
247 | __Nss = lists:nthtail(5, __Ss), | |
248 | yeccpars2(yeccgoto(appl, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr); | |
249 | yeccpars2(24, atom, __Ss, __Stack, __T, __Ts, __Tzr) -> | |
250 | yeccpars1(__Ts, __Tzr, 3, [24 | __Ss], [__T | __Stack]); | |
251 | yeccpars2(24, integer, __Ss, __Stack, __T, __Ts, __Tzr) -> | |
252 | yeccpars1(__Ts, __Tzr, 7, [24 | __Ss], [__T | __Stack]); | |
253 | yeccpars2(24, '*', __Ss, __Stack, __T, __Ts, __Tzr) -> | |
254 | yeccpars1(__Ts, __Tzr, 6, [24 | __Ss], [__T | __Stack]); | |
255 | yeccpars2(24, '{', __Ss, __Stack, __T, __Ts, __Tzr) -> | |
256 | yeccpars1(__Ts, __Tzr, 10, [24 | __Ss], [__T | __Stack]); | |
257 | yeccpars2(24, _, _, _, __T, _, _) -> | |
258 | yeccerror(__T); | |
259 | yeccpars2(25, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) -> | |
260 | __Val = {vlist,__1,__3}, | |
261 | __Nss = lists:nthtail(2, __Ss), | |
262 | yeccpars2(yeccgoto(vlist, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr); | |
263 | yeccpars2(26, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) -> | |
264 | __Val = {lit,__2}, | |
265 | __Nss = lists:nthtail(1, __Ss), | |
266 | yeccpars2(yeccgoto(val, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr); | |
267 | yeccpars2(27, atom, __Ss, __Stack, __T, __Ts, __Tzr) -> | |
268 | yeccpars1(__Ts, __Tzr, 3, [27 | __Ss], [__T | __Stack]); | |
269 | yeccpars2(27, _, _, _, __T, _, _) -> | |
270 | yeccerror(__T); | |
271 | yeccpars2(28, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) -> | |
272 | __Val = {alist,__1,__3}, | |
273 | __Nss = lists:nthtail(2, __Ss), | |
274 | yeccpars2(yeccgoto(alist, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr); | |
275 | yeccpars2(__Other, _, _, _, _, _, _) -> | |
276 | exit({parser, __Other, missing_state_in_action_table}). | |
277 | ||
278 | yeccgoto(alist, 0) -> | |
279 | 1; | |
280 | yeccgoto(alist, 13) -> | |
281 | 14; | |
282 | yeccgoto(alist, 27) -> | |
283 | 28; | |
284 | yeccgoto(appl, 0) -> | |
285 | 2; | |
286 | yeccgoto(appl, 13) -> | |
287 | 2; | |
288 | yeccgoto(appl, 27) -> | |
289 | 2; | |
290 | yeccgoto(name, 0) -> | |
291 | 4; | |
292 | yeccgoto(name, 5) -> | |
293 | 8; | |
294 | yeccgoto(name, 10) -> | |
295 | 11; | |
296 | yeccgoto(name, 13) -> | |
297 | 4; | |
298 | yeccgoto(name, 15) -> | |
299 | 16; | |
300 | yeccgoto(name, 18) -> | |
301 | 11; | |
302 | yeccgoto(name, 20) -> | |
303 | 8; | |
304 | yeccgoto(name, 24) -> | |
305 | 8; | |
306 | yeccgoto(name, 27) -> | |
307 | 4; | |
308 | yeccgoto(nlist, 10) -> | |
309 | 12; | |
310 | yeccgoto(nlist, 18) -> | |
311 | 19; | |
312 | yeccgoto(val, 5) -> | |
313 | 9; | |
314 | yeccgoto(val, 20) -> | |
315 | 21; | |
316 | yeccgoto(val, 24) -> | |
317 | 21; | |
318 | yeccgoto(vlist, 20) -> | |
319 | 22; | |
320 | yeccgoto(vlist, 24) -> | |
321 | 25; | |
322 | yeccgoto(__Symbol, __State) -> | |
323 | exit({__Symbol, __State, missing_in_goto_table}). | |
324 | ||
325 |
0 | %%% -grammar(sbeezg_parser). | |
1 | %%% -vsn('2002.0317'). | |
2 | %%% -author('cpressey@catseye.mb.ca'). | |
3 | %%% -copyright('Copyright (c)2002 Cat`s Eye Technologies. All rights reserved.'). | |
4 | ||
5 | %%% Redistribution and use in source and binary forms, with or without | |
6 | %%% modification, are permitted provided that the following conditions | |
7 | %%% are met: | |
8 | %%% | |
9 | %%% Redistributions of source code must retain the above copyright | |
10 | %%% notice, this list of conditions and the following disclaimer. | |
11 | %%% | |
12 | %%% Redistributions in binary form must reproduce the above copyright | |
13 | %%% notice, this list of conditions and the following disclaimer in | |
14 | %%% the documentation and/or other materials provided with the | |
15 | %%% distribution. | |
16 | %%% | |
17 | %%% Neither the name of Cat's Eye Technologies nor the names of its | |
18 | %%% contributors may be used to endorse or promote products derived | |
19 | %%% from this software without specific prior written permission. | |
20 | %%% | |
21 | %%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | |
22 | %%% CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, | |
23 | %%% INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
24 | %%% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
25 | %%% DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE | |
26 | %%% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, | |
27 | %%% OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
28 | %%% PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, | |
29 | %%% OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |
30 | %%% ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
31 | %%% OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
32 | %%% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
33 | %%% POSSIBILITY OF SUCH DAMAGE. | |
34 | ||
35 | %%% BEGIN sbeezg_parser.yrl %%% | |
36 | ||
37 | Nonterminals vlist val nlist name alist appl. | |
38 | Terminals '=' '*' '(' ')' '{' '|' '}' ',' ';' atom integer. | |
39 | Rootsymbol alist. | |
40 | ||
41 | %%% EBNF: | |
42 | %%% Appl ::= Name "=" Val "(" Val {"," Val} ")". | |
43 | %%% Val ::= Name | "*" Const | "{" Name {"," Name} "|" Appl {";" Appl} "|" Name "}". | |
44 | ||
45 | %%% Recursive Version (no {}'s): | |
46 | %%% Appl ::= Name "=" Val ["(" Vlist ")"]. | |
47 | %%% Vlist ::= Val ["," Vlist]. | |
48 | %%% Val ::= Name | "*" Name | "{" Nlist "|" Alist "|" Name "}". | |
49 | %%% Nlist ::= Name ["," Nlist]. | |
50 | %%% Alist ::= Appl [";" Alist]. | |
51 | ||
52 | appl -> name '=' val '(' vlist ')' : new_name('$1'), {assign, '$1', '$3', '$5'}. | |
53 | appl -> name '=' val : new_name('$1'), {assign, '$1', '$3'}. | |
54 | vlist -> val ',' vlist : {vlist, '$1', '$3'}. | |
55 | vlist -> val : {vlist, '$1', nil}. | |
56 | val -> '{' nlist '|' alist '|' name '}' : {lambda, '$2', '$4', '$6'}. | |
57 | val -> '*' atom : {lit, '$2'}. | |
58 | val -> integer : {lit, '$1'}. | |
59 | val -> name : existing_name('$1'), '$1'. | |
60 | nlist -> name ',' nlist : new_name('$1'), {nlist, '$1', '$3'}. | |
61 | nlist -> name : new_name('$1'), {nlist, '$1', nil}. | |
62 | alist -> appl ';' alist : {alist, '$1', '$3'}. | |
63 | alist -> appl : {alist, '$1', nil}. | |
64 | name -> atom : {name, '$1'}. | |
65 | ||
66 | Erlang code. | |
67 | ||
68 | new_name({name,{atom,Line,Name}}=A) -> | |
69 | case get(A) of | |
70 | defn -> | |
71 | return_error(0, io_lib:format("Name '~w' already defined", [Name])); | |
72 | _ -> | |
73 | put(A, defn) | |
74 | end. | |
75 | ||
76 | existing_name({name,{atom,Line,Name}}=A) -> | |
77 | case get(A) of | |
78 | undefined -> | |
79 | return_error(0, io_lib:format("Name '~w' is not yet defined", [Name])); | |
80 | _ -> | |
81 | ok | |
82 | end. | |
83 | ||
84 | %%% END of sbeezg_parser.yrl %%% |