145 lines
3.4 KiB
Erlang
145 lines
3.4 KiB
Erlang
% @doc bikeshed proctrastination head into vim warmup thing
|
|
% sophia compiler from scratch by PRH
|
|
%
|
|
% based on original sophia compiler
|
|
%
|
|
% parse layers:
|
|
% 1. sfc_tokenizer: SrcStr -> (Tokens | SigTokens)
|
|
%
|
|
% SigTokens = not comment/whitespace
|
|
%
|
|
% layers:
|
|
% a. sfc_strmatch : matches string shapes
|
|
% b. sfc_so_scan : converts to so_scan shapes
|
|
%
|
|
% 2. sfc_ast: SigTokens -> AST
|
|
%
|
|
% terminology:
|
|
%
|
|
% - `slurp`/`barf` borrowed from emacs paredit mode:
|
|
%
|
|
% slurp : (a b) c -> (a b c)
|
|
% barf : (a b c) -> a (b c)
|
|
%
|
|
% * `slurp` usually involves *transforming* input
|
|
% into a new type (e.g. slurp a token from src
|
|
% string); think of slurp as a verb meaning to
|
|
% consume and then digest
|
|
% * `barf` basically means blindly splitting off
|
|
% input
|
|
%
|
|
% @end
|
|
|
|
% TODO:
|
|
% - barf for outputs, slurp for inputs
|
|
% - architecture needs more careful thought but only after something works
|
|
% - too fuzzy right now
|
|
% - possibly:
|
|
% - rename parser layers sequentially:
|
|
% - sfc_
|
|
-module(sfc).
|
|
|
|
|
|
-export_type([
|
|
token/0
|
|
]).
|
|
|
|
-export([
|
|
sigtokens_from_file/1,
|
|
sigtokens_from_string/1,
|
|
tokens_from_file/1,
|
|
tokens_from_string/1,
|
|
ast_from_file/1,
|
|
ast_from_string/1,
|
|
ast_from_tokens/1
|
|
]).
|
|
|
|
-include("$sfc_include/sfc.hrl").
|
|
|
|
%-----------------------------------------
|
|
% types
|
|
%-----------------------------------------
|
|
|
|
-type token() :: sfc_token().
|
|
|
|
%-----------------------------------------
|
|
% functions
|
|
%-----------------------------------------
|
|
|
|
sigtokens_from_file(X) ->
|
|
case tokens_from_file(X) of
|
|
{ok, Y} -> {ok, sfc_tokens:filter_significant(Y)};
|
|
Err -> Err
|
|
end.
|
|
|
|
sigtokens_from_string(X) ->
|
|
case tokens_from_string(X) of
|
|
{ok, Y} -> {ok, sfc_tokens:filter_significant(Y)};
|
|
Err -> Err
|
|
end.
|
|
|
|
|
|
-spec tokens_from_file(FilePath) -> Perhaps
|
|
when FilePath :: string(),
|
|
Perhaps :: {ok, Tokens}
|
|
| {error, sfc_err() | any()},
|
|
Tokens :: [sfc_token()].
|
|
|
|
tokens_from_file(FilePath) ->
|
|
case file:read_file(FilePath) of
|
|
{ok, FBytes} -> tokens_from_string(FBytes);
|
|
Error -> Error
|
|
end.
|
|
|
|
|
|
|
|
|
|
-spec tokens_from_string(SrcStr) -> Result
|
|
when SrcStr :: string(),
|
|
Result :: {ok, Tokens}
|
|
| {error, sfc_err()},
|
|
Tokens :: [sfc_token()].
|
|
|
|
tokens_from_string(SrcStr) ->
|
|
sfc_tokens:tokens(SrcStr).
|
|
|
|
|
|
|
|
-spec ast_from_file(FilePath) -> Perhaps
|
|
when FilePath :: string(),
|
|
Perhaps :: {ok, AST} | {error, sfc_err()},
|
|
AST :: sfc_ast().
|
|
|
|
ast_from_file(FilePath) ->
|
|
case file:read_file(FilePath) of
|
|
{ok, FileBytes} -> ast_from_string(FileBytes);
|
|
Error -> Error
|
|
end.
|
|
|
|
|
|
|
|
-spec ast_from_string(SrcStr) -> Perhaps
|
|
when SrcStr :: string(),
|
|
Perhaps :: {ok, AST} | {error, sfc_err()},
|
|
AST :: sfc_ast().
|
|
|
|
ast_from_string(SrcStr) ->
|
|
case sfc_tokens:significant_tokens(SrcStr) of
|
|
{ok, SigTks} -> ast_from_tokens(SigTks);
|
|
Error -> Error
|
|
end.
|
|
|
|
|
|
|
|
-spec ast_from_tokens(SrcTokens) -> Perhaps
|
|
when SrcTokens :: [sfc_token()],
|
|
Perhaps :: {ok, AST} | {error, sfc_err()},
|
|
AST :: sfc_ast().
|
|
|
|
ast_from_tokens(Tks) ->
|
|
SigTks = sfc_tokens:filter_significant(Tks),
|
|
case sfc_ast:gulp_file(SigTks) of
|
|
{gulp, AST} -> {ok, AST};
|
|
Error -> Error
|
|
end.
|