1. Cat's Eye Technologies
  2. Sbeezg

Commits

Cat's Eye Technologies  committed d7fec4e

Initial import of Sbeezg version 1.0 revision 2002.0317 sources.

  • Participants
  • Branches default
  • Tags rel_1_0_2002_0317

Comments (0)

Files changed (9)

File README

View file
  • Ignore whitespace
+The Sbeezg Programming Language                                   v2002.0317
+-------------------------------
+
+Sbeezg is single-assignment programming taken to the extreme.  Each variable
+may only be assigned once.  There is no scope.  When a function is executed,
+a new copy of it is made, with all bound variable names altered to fresh ones,
+and this is executed instead.  Execution is sequential in nature.  Arguments
+and return value are given explicitly.  There are no global names; there are
+only lambda function definitions available.  There are five built-in operations.
+For convenience, there are three data types: atoms, integers, and closures.
+
+Here is a brief EBNF rundown of the syntax:
+
+Appl ::= Name "=" Val "(" Val  {"," Val} ")".
+Val  ::= Name | "*" Const | "{" Name {"," Name} "|" Appl {";" Appl} "|" Name "}".
+
+A program is an application, which consists of an assignment to a new (never
+before named in the program) variable, of a value or the result of a function
+call.  Note that the arguments of a function call may only be simple values;
+further nested function calls are disallowed as their implicit 'piping' of
+values from one function to the next without an intervening variable name is
+counter to the intention of this purely single-assignment language.
+
+This documentation isn't really complete.
+
+Chris Pressey
+March 17 2002
+Winnipeg, Manitoba

File doc/sbeezg.html

View file
  • Ignore whitespace
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Module sbeezg</title>
+</head>
+<body bgcolor="white">
+<h1>Module sbeezg</h1>
+<ul><li>
+<a href="#index">Function index</a></li><li>
+<a href="#exported">Exported functions</a></li></ul>
+
+<h2>Description</h2>
+
+
+<h2><a name="index">Function Index</a></h2>
+
+<table width="100%" border="1"><tr><th colspan="2" align="left">Exported Functions</th></tr>
+<tr><td><a href="#run-1">run/1</a></td><td/></tr>
+<tr><td><a href="#test-1">test/1</a></td><td/></tr>
+</table>
+
+<h2><a name="exported">Exported Functions</a></h2>
+
+<h3><a name="run-1">run/1</a></h3>
+
+<p><code>run(Arg1) -> term()</code></p>
+<p> </p>
+
+<h3><a name="test-1">test/1</a></h3>
+
+<p><code>test(Arg1) -> term()</code></p>
+<p> </p></body>
+</html>

File doc/sbeezg_parser.html

View file
  • Ignore whitespace
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Module sbeezg_parser</title>
+</head>
+<body bgcolor="white">
+<h1>Module sbeezg_parser</h1>
+<ul><li>
+<a href="#index">Function index</a></li><li>
+<a href="#exported">Exported functions</a></li></ul>
+
+<h2>Description</h2>
+
+
+<h2><a name="index">Function Index</a></h2>
+
+<table width="100%" border="1"><tr><th colspan="2" align="left">Exported Functions</th></tr>
+<tr><td><a href="#format_error-1">format_error/1</a></td><td/></tr>
+<tr><td><a href="#parse-1">parse/1</a></td><td/></tr>
+<tr><td><a href="#parse_and_scan-1">parse_and_scan/1</a></td><td/></tr>
+</table>
+
+<h2><a name="exported">Exported Functions</a></h2>
+
+<h3><a name="format_error-1">format_error/1</a></h3>
+
+<p><code>format_error(Arg1) -> term()</code></p>
+<p> </p>
+
+<h3><a name="parse-1">parse/1</a></h3>
+
+<p><code>parse(Arg1) -> term()</code></p>
+<p> </p>
+
+<h3><a name="parse_and_scan-1">parse_and_scan/1</a></h3>
+
+<p><code>parse_and_scan(Arg1) -> term()</code></p>
+<p> </p></body>
+</html>

File ebin/sbeezg.app

View file
  • Ignore whitespace
+{application,sbeezg,
+ [{description,"The Sbeezg Programming Language"},
+  {vsn,"2002.0317"},
+  {modules,[sbeezg, sbeezg_parser]},
+  {registered,[]},
+  {env,[]},
+  {applications,[kernel,stdlib]}]}.
+

File ebin/sbeezg.beam

  • Ignore whitespace
Binary file added.

File ebin/sbeezg_parser.beam

  • Ignore whitespace
Binary file added.

File src/sbeezg.erl

View file
  • Ignore whitespace
+-module(sbeezg).
+-vsn('2002.0317').
+-author('cpressey@catseye.mb.ca').
+-copyright('Copyright (c)2002 Cat`s Eye Technologies. All rights reserved.').
+
+%%% Redistribution and use in source and binary forms, with or without
+%%% modification, are permitted provided that the following conditions
+%%% are met:
+%%%
+%%%   Redistributions of source code must retain the above copyright
+%%%   notice, this list of conditions and the following disclaimer.
+%%%
+%%%   Redistributions in binary form must reproduce the above copyright
+%%%   notice, this list of conditions and the following disclaimer in
+%%%   the documentation and/or other materials provided with the
+%%%   distribution.
+%%%
+%%%   Neither the name of Cat's Eye Technologies nor the names of its
+%%%   contributors may be used to endorse or promote products derived
+%%%   from this software without specific prior written permission.
+%%%
+%%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+%%% CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+%%% INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+%%% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+%%% DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+%%% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+%%% OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+%%% PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+%%% OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+%%% ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+%%% OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+%%% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+%%% POSSIBILITY OF SUCH DAMAGE. 
+
+-export([run/1, test/1]).
+
+%%% BEGIN sbeezg.erl %%%
+
+%%% A simple interpreter for the Sbeezg Programming Language.
+
+%% Interpreter ---------------------------------------------------------
+%% Call sbeezg:run("sbeezg-program") to interpret a Sbeezg program.
+%% Empties the process dictionary as a side effect.
+
+run(String) when list(String) ->
+  {ok, Toks, N} = erl_scan:string(String),
+  % io:fwrite("scan: ~s -> ~w~n", [String, Toks]),
+  erase(), % clear process dictionary for parser
+  case sbeezg_parser:parse(Toks ++ [{'$end',999}]) of
+    {ok, Prog} -> 
+      % io:fwrite("parse: ~s -> ~w~n", [String, Prog]),
+      erase(), % destroy the garbage left in the process dictionary
+      run(Prog);
+    {error, {Line, Module, Message}}=Q ->
+      io:fwrite("Error: ~s~n", [Message]),
+      Q
+  end;
+run({assign, L, F, A}=C) ->
+  % io:fwrite("~w~n", [C]),
+  L0 = get_name(L),
+  F0 = run(F),
+  A0 = run(A),
+  assign(L0, '$placeholder'),
+  R0 = execute(F0, A0),
+  assign(L0, R0);
+run({assign, L, R}=C) ->
+  % io:fwrite("~w~n", [C]),
+  L0 = get_name(L),
+  R0 = run(R),
+  assign(L0, R0);
+run({vlist, H, T}=C) ->
+  % io:fwrite("~w~n", [C]),
+  H0 = run(H),
+  T0 = run(T),
+  [H0 | T0];
+run({lambda, N, A, R}=C) ->
+  % io:fwrite("~w~n", [C]),
+  {func, N, A, R};
+run({alist, H, T}=C) ->
+  % io:fwrite("~w~n", [C]),
+  H0 = run(H),
+  T0 = run(T),
+  case T0 of
+    [] -> H0;
+    _  -> T0
+  end;
+run({lit,{atom,Line,Atom}}) -> Atom;
+run({lit,{integer,Line,Int}}) -> Int;
+run({name, {atom,Line,Atom}}) ->
+  case get(Atom) of
+    undefined ->
+      io:fwrite("~w undefined!~n", [Atom]),
+      Atom;
+    N ->
+      N
+  end;
+run(nil) ->
+  [];
+run(Q) ->
+  io:fwrite("UNKNOWN ~w~n", [Q]),
+  unknown.
+
+get_name({nlist, H, T}=C) ->
+  % io:fwrite("~w~n", [C]),
+  H0 = get_name(H),
+  T0 = get_name(T),
+  [H0 | T0];
+get_name({name, {atom,Line,Atom}}) -> Atom;
+get_name(nil) -> [].
+
+%% Utility -------------------------------------------------------------
+
+assign(Name, Value) ->
+  % io:fwrite("Assigning ~w to ~w~n", [Value, Name]),
+  case get(Name) of
+    NonExist when NonExist == undefined; NonExist == '$placeholder' ->
+      put(Name, Value);
+    Exist ->
+      io:fwrite("ERROR: Multiple Assignment to ~w=~w (~w)~n",
+        [Name, Exist, Value])
+  end,
+  Value.
+  
+execute(print, [H | T]) ->
+  io:fwrite("~w", [H]),
+  execute(print, T);
+execute(print, []) -> ok;
+execute(is, [A, B, T, F]) ->
+  % io:fwrite("~w", [C]),
+  case A of
+    B -> T;
+    _ -> F
+  end;
+execute(pred, [X]) ->
+  % io:fwrite("pred ~w~n", [X]),
+  X - 1;
+execute(succ, [X]) -> X + 1;
+execute(Func, Args) when atom(Func) ->
+  io:fwrite("Unknown built-in '~w(~w)'~n", [Func, Args]),
+  unknown;
+execute({func, P, B, R}, A) ->
+  P0 = fresh(P),
+  B0 = fresh(B),
+  P1 = get_name(P0),
+  bind(P1, A),
+  run(B0),
+  run(R).
+
+fresh({assign, L, F, A}=C) -> {assign, fresh(L), fresh(F), fresh(A)};
+fresh({assign, L, R}=C)    -> {assign, fresh(L), fresh(R)};
+fresh({vlist, H, T}=C)     -> {vlist, fresh(H), fresh(T)};
+fresh({lambda, X, A}=C)    -> {lambda, fresh(X), fresh(A)};
+fresh({nlist, H, T}=C)     -> {nlist, fresh(H), fresh(T)};
+fresh({alist, H, T}=C)     -> {alist, fresh(H), fresh(T)};
+fresh({lit,X}=C)           -> C;
+fresh({name,{atom,Line,Atom}}=C)  ->
+  case get(Atom) of
+    undefined -> C;
+    _ ->
+      fresh({name, {atom, Line, list_to_atom([$_ | atom_to_list(Atom)])}})
+  end;
+fresh(X)                   -> X.
+
+bind([],[]) -> ok;
+bind([HN|TN],[HV|TV]) ->
+  % io:fwrite("bind ~w to ~w~n", [HV,HN]),
+  assign(HN,HV),
+  bind(TN,TV).
+
+%% User interface ------------------------------------------------------
+
+test([N]) -> test(list_to_integer(N));
+test(N) ->
+  R = run(prg(N)),
+  E = erase(),
+  {R, E}.
+
+prg(1) -> "a={b|p=*print;c=p(b)|b};d=a(*foo);e=a(*bar);f=a(*baz)";
+prg(2) -> "a={b|p=*print;c=p(b)|b};d={e,f|g=e(f)|g};h=d(a,*hello)";
+prg(3) -> "p=*print;i=*is;r=i(*a,*b,*troo,*fall);q=p(r)";
+prg(4) -> "f={a,b|p=*print;g=p(a);k=b(a,b)|a};l=f(*hello,f)";
+prg(5) -> "f={a,b|i=*is;s=*pred;p=*print;g=p(*beer);h=s(a);"
+          "ln={x,m|z=x|x};lg={y,n|q=n(y,n)|y};j=i(h,0,ln,lg);"
+	  "k=j(h,b)|a};l=f(99,f)";
+prg(6) -> "f=*a;f=*b";  % intentionally erroneous
+prg(_) -> unknown.
+
+%%% END of sbeezg.erl %%%

File src/sbeezg_parser.erl

View file
  • Ignore whitespace
+-module(sbeezg_parser).
+-define(THIS_MODULE, sbeezg_parser).
+-export([parse/1, parse_and_scan/1, format_error/1]).
+
+new_name({name,{atom,Line,Name}}=A) ->
+  case get(A) of
+    defn ->
+      return_error(0, io_lib:format("Name '~w' already defined", [Name]));
+    _ ->
+      put(A, defn)
+  end.
+
+existing_name({name,{atom,Line,Name}}=A) ->
+  case get(A) of
+    undefined ->
+      return_error(0, io_lib:format("Name '~w' is not yet defined", [Name]));
+    _ ->
+      ok
+  end.
+
+%%% END of sbeezg_parser.yrl %%%
+
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved via the world wide web at http://www.erlang.org/.
+%% 
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%% 
+%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+%% AB. All Rights Reserved.''
+%% 
+%%     $Id$
+%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% The parser generator will insert appropriate declarations before this line.%
+
+parse(Tokens) ->
+    case catch yeccpars1(Tokens, false, 0, [], []) of
+	error ->
+	    Errorline =
+		if Tokens == [] -> 0; true -> element(2, hd(Tokens)) end,
+	    {error,
+	     {Errorline, ?THIS_MODULE, "syntax error at or after this line."}};
+	Other ->
+	    Other
+    end.
+
+parse_and_scan({Mod, Fun, Args}) ->
+    case apply(Mod, Fun, Args) of
+	{eof, _} ->
+	    {ok, eof};
+	{error, Descriptor, _} ->
+	    {error, Descriptor};
+	{ok, Tokens, _} ->
+	    yeccpars1(Tokens, {Mod, Fun, Args}, 0, [], [])
+    end.
+
+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!
+return_error(Line, Message) ->
+    throw({error, {Line, ?THIS_MODULE, Message}}).
+
+
+% Don't change yeccpars1/6 too much, it is called recursively by yeccpars2/8!
+yeccpars1([Token | Tokens], Tokenizer, State, States, Vstack) ->
+    yeccpars2(State, element(1, Token), States, Vstack, Token, Tokens,
+	      Tokenizer);
+yeccpars1([], {M, F, A}, State, States, Vstack) ->
+    case catch apply(M, F, A) of
+        {eof, Endline} ->
+            {error, {Endline, ?THIS_MODULE, "end_of_file"}};
+        {error, Descriptor, Endline} ->
+            {error, Descriptor};
+        {'EXIT', Reason} ->
+            {error, {0, ?THIS_MODULE, Reason}};
+        {ok, Tokens, Endline} ->
+	    case catch yeccpars1(Tokens, {M, F, A}, State, States, Vstack) of
+		error ->
+		    Errorline = element(2, hd(Tokens)),
+		    {error, {Errorline, ?THIS_MODULE,
+			     "syntax error at or after this line."}};
+		Other ->
+		    Other
+	    end
+    end;
+yeccpars1([], false, State, States, Vstack) ->
+    yeccpars2(State, '$end', States, Vstack, {'$end', 999999}, [], false).
+
+% For internal use only.
+yeccerror(Token) ->
+    {error,
+     {element(2, Token), ?THIS_MODULE,
+      ["syntax error before: ", yecctoken2string(Token)]}}.
+
+yecctoken2string({atom, _, A}) -> io_lib:write(A);
+yecctoken2string({integer,_,N}) -> io_lib:write(N);
+yecctoken2string({float,_,F}) -> io_lib:write(F);
+yecctoken2string({char,_,C}) -> io_lib:write_char(C);
+yecctoken2string({var,_,V}) -> io_lib:format('~s', [V]);
+yecctoken2string({string,_,S}) -> io_lib:write_string(S);
+yecctoken2string({reserved_symbol, _, A}) -> io_lib:format('~w', [A]);
+yecctoken2string({Cat, _, Val}) -> io_lib:format('~w', [Val]);
+
+yecctoken2string({'dot', _}) -> io_lib:format('~w', ['.']);
+yecctoken2string({'$end', _}) ->
+    [];
+yecctoken2string({Other, _}) when atom(Other) ->
+    io_lib:format('~w', [Other]);
+yecctoken2string(Other) ->
+    io_lib:write(Other).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+yeccpars2(0, atom, __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 3, [0 | __Ss], [__T | __Stack]);
+yeccpars2(0, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(1, '$end', _, __Stack, _, _, _) ->
+ {ok, hd(__Stack)};
+yeccpars2(1, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(2, ';', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 27, [2 | __Ss], [__T | __Stack]);
+yeccpars2(2, __Cat, __Ss,  [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val =  {alist,__1,nil},
+ yeccpars2(yeccgoto(alist, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(3, __Cat, __Ss,  [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val =  {name,__1},
+ yeccpars2(yeccgoto(name, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(4, '=', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 5, [4 | __Ss], [__T | __Stack]);
+yeccpars2(4, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(5, atom, __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 3, [5 | __Ss], [__T | __Stack]);
+yeccpars2(5, integer, __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 7, [5 | __Ss], [__T | __Stack]);
+yeccpars2(5, '*', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 6, [5 | __Ss], [__T | __Stack]);
+yeccpars2(5, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 10, [5 | __Ss], [__T | __Stack]);
+yeccpars2(5, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(6, atom, __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 26, [6 | __Ss], [__T | __Stack]);
+yeccpars2(6, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(7, __Cat, __Ss,  [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val =  {lit,__1},
+ yeccpars2(yeccgoto(val, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(8, __Cat, __Ss,  [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = begin
+   existing_name(__1), __1
+  end,
+ yeccpars2(yeccgoto(val, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(9, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 20, [9 | __Ss], [__T | __Stack]);
+yeccpars2(9, __Cat, __Ss,  [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = begin
+   new_name(__1), {assign,__1,__3}
+  end,
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(appl, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(10, atom, __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 3, [10 | __Ss], [__T | __Stack]);
+yeccpars2(10, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(11, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 18, [11 | __Ss], [__T | __Stack]);
+yeccpars2(11, __Cat, __Ss,  [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = begin
+   new_name(__1), {nlist,__1,nil}
+  end,
+ yeccpars2(yeccgoto(nlist, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(12, '|', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 13, [12 | __Ss], [__T | __Stack]);
+yeccpars2(12, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(13, atom, __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 3, [13 | __Ss], [__T | __Stack]);
+yeccpars2(13, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(14, '|', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 15, [14 | __Ss], [__T | __Stack]);
+yeccpars2(14, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(15, atom, __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 3, [15 | __Ss], [__T | __Stack]);
+yeccpars2(15, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(16, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 17, [16 | __Ss], [__T | __Stack]);
+yeccpars2(16, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(17, __Cat, __Ss,  [__7,__6,__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val =  {lambda,__2,__4,__6},
+ __Nss = lists:nthtail(6, __Ss),
+ yeccpars2(yeccgoto(val, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(18, atom, __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 3, [18 | __Ss], [__T | __Stack]);
+yeccpars2(18, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(19, __Cat, __Ss,  [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = begin
+   new_name(__1), {nlist,__1,__3}
+  end,
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(nlist, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(20, atom, __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 3, [20 | __Ss], [__T | __Stack]);
+yeccpars2(20, integer, __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 7, [20 | __Ss], [__T | __Stack]);
+yeccpars2(20, '*', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 6, [20 | __Ss], [__T | __Stack]);
+yeccpars2(20, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 10, [20 | __Ss], [__T | __Stack]);
+yeccpars2(20, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(21, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 24, [21 | __Ss], [__T | __Stack]);
+yeccpars2(21, __Cat, __Ss,  [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val =  {vlist,__1,nil},
+ yeccpars2(yeccgoto(vlist, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(22, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [22 | __Ss], [__T | __Stack]);
+yeccpars2(22, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(23, __Cat, __Ss,  [__6,__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = begin
+   new_name(__1), {assign,__1,__3,__5}
+  end,
+ __Nss = lists:nthtail(5, __Ss),
+ yeccpars2(yeccgoto(appl, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(24, atom, __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 3, [24 | __Ss], [__T | __Stack]);
+yeccpars2(24, integer, __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 7, [24 | __Ss], [__T | __Stack]);
+yeccpars2(24, '*', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 6, [24 | __Ss], [__T | __Stack]);
+yeccpars2(24, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 10, [24 | __Ss], [__T | __Stack]);
+yeccpars2(24, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(25, __Cat, __Ss,  [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val =  {vlist,__1,__3},
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(vlist, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(26, __Cat, __Ss,  [__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val =  {lit,__2},
+ __Nss = lists:nthtail(1, __Ss),
+ yeccpars2(yeccgoto(val, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(27, atom, __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 3, [27 | __Ss], [__T | __Stack]);
+yeccpars2(27, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(28, __Cat, __Ss,  [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val =  {alist,__1,__3},
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(alist, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(__Other, _, _, _, _, _, _) ->
+ exit({parser, __Other, missing_state_in_action_table}).
+
+yeccgoto(alist, 0) ->
+ 1;
+yeccgoto(alist, 13) ->
+ 14;
+yeccgoto(alist, 27) ->
+ 28;
+yeccgoto(appl, 0) ->
+ 2;
+yeccgoto(appl, 13) ->
+ 2;
+yeccgoto(appl, 27) ->
+ 2;
+yeccgoto(name, 0) ->
+ 4;
+yeccgoto(name, 5) ->
+ 8;
+yeccgoto(name, 10) ->
+ 11;
+yeccgoto(name, 13) ->
+ 4;
+yeccgoto(name, 15) ->
+ 16;
+yeccgoto(name, 18) ->
+ 11;
+yeccgoto(name, 20) ->
+ 8;
+yeccgoto(name, 24) ->
+ 8;
+yeccgoto(name, 27) ->
+ 4;
+yeccgoto(nlist, 10) ->
+ 12;
+yeccgoto(nlist, 18) ->
+ 19;
+yeccgoto(val, 5) ->
+ 9;
+yeccgoto(val, 20) ->
+ 21;
+yeccgoto(val, 24) ->
+ 21;
+yeccgoto(vlist, 20) ->
+ 22;
+yeccgoto(vlist, 24) ->
+ 25;
+yeccgoto(__Symbol, __State) ->
+ exit({__Symbol, __State, missing_in_goto_table}).
+
+

File src/sbeezg_parser.yrl

View file
  • Ignore whitespace
+%%% -grammar(sbeezg_parser).
+%%% -vsn('2002.0317').
+%%% -author('cpressey@catseye.mb.ca').
+%%% -copyright('Copyright (c)2002 Cat`s Eye Technologies. All rights reserved.').
+
+%%% Redistribution and use in source and binary forms, with or without
+%%% modification, are permitted provided that the following conditions
+%%% are met:
+%%%
+%%%   Redistributions of source code must retain the above copyright
+%%%   notice, this list of conditions and the following disclaimer.
+%%%
+%%%   Redistributions in binary form must reproduce the above copyright
+%%%   notice, this list of conditions and the following disclaimer in
+%%%   the documentation and/or other materials provided with the
+%%%   distribution.
+%%%
+%%%   Neither the name of Cat's Eye Technologies nor the names of its
+%%%   contributors may be used to endorse or promote products derived
+%%%   from this software without specific prior written permission.
+%%%
+%%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+%%% CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+%%% INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+%%% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+%%% DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+%%% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+%%% OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+%%% PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+%%% OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+%%% ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+%%% OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+%%% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+%%% POSSIBILITY OF SUCH DAMAGE. 
+
+%%% BEGIN sbeezg_parser.yrl %%%
+
+Nonterminals vlist val nlist name alist appl.
+Terminals '=' '*' '(' ')' '{' '|' '}' ',' ';' atom integer.
+Rootsymbol alist.
+
+%%% EBNF:
+%%% Appl ::= Name "=" Val "(" Val  {"," Val} ")".
+%%% Val  ::= Name | "*" Const | "{" Name {"," Name} "|" Appl {";" Appl} "|" Name "}".
+
+%%% Recursive Version (no {}'s):
+%%% Appl  ::= Name "=" Val ["(" Vlist ")"].
+%%% Vlist ::= Val ["," Vlist].
+%%% Val   ::= Name | "*" Name | "{" Nlist "|" Alist "|" Name "}".
+%%% Nlist ::= Name ["," Nlist].
+%%% Alist ::= Appl [";" Alist].
+
+appl  -> name '=' val '(' vlist ')'       : new_name('$1'), {assign, '$1', '$3', '$5'}.
+appl  -> name '=' val                     : new_name('$1'), {assign, '$1', '$3'}.
+vlist -> val ',' vlist                    : {vlist, '$1', '$3'}.
+vlist -> val                              : {vlist, '$1', nil}.
+val   -> '{' nlist '|' alist '|' name '}' : {lambda, '$2', '$4', '$6'}.
+val   -> '*' atom                         : {lit, '$2'}.
+val   -> integer                          : {lit, '$1'}.
+val   -> name                             : existing_name('$1'), '$1'.
+nlist -> name ',' nlist                   : new_name('$1'), {nlist, '$1', '$3'}.
+nlist -> name                             : new_name('$1'), {nlist, '$1', nil}.
+alist -> appl ';' alist                   : {alist, '$1', '$3'}.
+alist -> appl                             : {alist, '$1', nil}.
+name  -> atom                             : {name, '$1'}.
+
+Erlang code.
+
+new_name({name,{atom,Line,Name}}=A) ->
+  case get(A) of
+    defn ->
+      return_error(0, io_lib:format("Name '~w' already defined", [Name]));
+    _ ->
+      put(A, defn)
+  end.
+
+existing_name({name,{atom,Line,Name}}=A) ->
+  case get(A) of
+    undefined ->
+      return_error(0, io_lib:format("Name '~w' is not yet defined", [Name]));
+    _ ->
+      ok
+  end.
+
+%%% END of sbeezg_parser.yrl %%%