2016 Update
This commit is contained in:
parent
948b86eafa
commit
dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions
|
|
@ -1,10 +1,18 @@
|
|||
[[wp:S-Expression|S-Expressions]] are one convenient way to parse and store data.
|
||||
[[wp:S-Expression|S-Expressions]] are one convenient way to parse and store data.
|
||||
|
||||
|
||||
;Task:
|
||||
Write a simple reader and writer for S-Expressions that handles quoted and unquoted strings, integers and floats.
|
||||
|
||||
The reader should read a single but nested S-Expression from a string and store it in a suitable datastructure (list, array, etc). Newlines and other whitespace may be ignored unless contained within a quoted string. “<tt>()</tt>” inside quoted strings are not interpreted, but treated as part of the string. Handling escaped quotes inside a string is optional; thus “<tt>(foo"bar)</tt>” maybe treated as a string “<tt>foo"bar</tt>”, or as an error.
|
||||
The reader should read a single but nested S-Expression from a string and store it in a suitable datastructure (list, array, etc).
|
||||
|
||||
For this, the reader need not recognise “<tt>\</tt>” for escaping, but should, in addition, recognize numbers if the language has appropriate datatypes.
|
||||
Newlines and other whitespace may be ignored unless contained within a quoted string.
|
||||
|
||||
“<tt>()</tt>” inside quoted strings are not interpreted, but treated as part of the string.
|
||||
|
||||
Handling escaped quotes inside a string is optional; thus “<tt>(foo"bar)</tt>” maybe treated as a string “<tt>foo"bar</tt>”, or as an error.
|
||||
|
||||
For this, the reader need not recognize “<tt>\</tt>” for escaping, but should, in addition, recognize numbers if the language has appropriate datatypes.
|
||||
|
||||
Languages that support it may treat unquoted strings as symbols.
|
||||
|
||||
|
|
@ -18,4 +26,7 @@ and turn it into a native datastructure. (see the [[#Pike|Pike]], [[#Python|Pyth
|
|||
The writer should be able to take the produced list and turn it into a new S-Expression.
|
||||
Strings that don't contain whitespace or parentheses () don't need to be quoted in the resulting S-Expression, but as a simplification, any string may be quoted.
|
||||
|
||||
'''Extra Credit:''' Let the writer produce pretty printed output with indenting and line-breaks
|
||||
|
||||
;Extra Credit:
|
||||
Let the writer produce pretty printed output with indenting and line-breaks.
|
||||
<br><br>
|
||||
|
|
|
|||
127
Task/S-Expressions/ALGOL-68/s-expressions.alg
Normal file
127
Task/S-Expressions/ALGOL-68/s-expressions.alg
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
# S-Expressions #
|
||||
CHAR nl = REPR 10;
|
||||
# mode representing an S-expression #
|
||||
MODE SEXPR = STRUCT( UNION( VOID, STRING, REF SEXPR ) element, REF SEXPR next );
|
||||
# creates an initialises an SEXPR #
|
||||
PROC new s expr = REF SEXPR: HEAP SEXPR := ( EMPTY, NIL );
|
||||
# reports an error #
|
||||
PROC error = ( STRING msg )VOID: print( ( "**** ", msg, newline ) );
|
||||
# S-expression reader - reads and returns an S-expression from the string s #
|
||||
PROC s reader = ( STRING s )REF SEXPR:
|
||||
BEGIN
|
||||
PROC at end = BOOL: s pos > UPB s;
|
||||
PROC curr = CHAR: IF at end THEN REPR 0 ELSE s[ s pos ] FI;
|
||||
PROC skip spaces = VOID: WHILE NOT at end AND ( curr = " " OR curr = nl ) DO s pos +:= 1 OD;
|
||||
PROC end of list = BOOL: at end OR curr = ")";
|
||||
INT s pos := LWB s;
|
||||
INT t pos;
|
||||
[ ( UPB s - LWB s ) + 1 ]CHAR token; # token text - large enough to hold the whole string if necessary #
|
||||
# adds the current character to the token #
|
||||
PROC add curr = VOID: token[ t pos +:= 1 ] := curr;
|
||||
# get an s expression element from s #
|
||||
PROC get element = REF SEXPR:
|
||||
BEGIN
|
||||
REF SEXPR result = new s expr;
|
||||
skip spaces;
|
||||
# get token text #
|
||||
IF at end THEN
|
||||
# no element #
|
||||
element OF result := EMPTY
|
||||
ELIF curr = "(" THEN
|
||||
s pos +:= 1;
|
||||
skip spaces;
|
||||
IF NOT end of list
|
||||
THEN
|
||||
REF SEXPR nested expression = get element;
|
||||
REF SEXPR element pos := nested expression;
|
||||
element OF result := nested expression;
|
||||
skip spaces;
|
||||
WHILE NOT end of list
|
||||
DO
|
||||
element pos := next OF element pos := get element;
|
||||
skip spaces
|
||||
OD
|
||||
FI;
|
||||
IF curr = ")" THEN
|
||||
s pos +:= 1
|
||||
ELSE
|
||||
error( "Missing "")""" )
|
||||
FI
|
||||
ELIF curr = ")" THEN
|
||||
s pos +:= 1;
|
||||
error( "Unexpected "")""" );
|
||||
element OF result := EMPTY
|
||||
ELSE
|
||||
# quoted or unquoted string #
|
||||
t pos := LWB token - 1;
|
||||
IF curr /= """" THEN
|
||||
# unquoted string #
|
||||
WHILE add curr;
|
||||
s pos +:= 1;
|
||||
NOT at end AND curr /= " " AND curr /= "("
|
||||
AND curr /= ")" AND curr /= """"
|
||||
AND curr /= nl
|
||||
DO SKIP OD
|
||||
ELSE
|
||||
# quoted string #
|
||||
WHILE add curr;
|
||||
s pos +:= 1;
|
||||
NOT at end AND curr /= """"
|
||||
DO SKIP OD;
|
||||
IF curr /= """" THEN
|
||||
# missing string quote #
|
||||
error( "Unterminated string: <<" + token[ : t pos ] + ">>" )
|
||||
ELSE
|
||||
# have the closing quote #
|
||||
add curr;
|
||||
s pos +:= 1
|
||||
FI
|
||||
FI;
|
||||
element OF result := token[ : t pos ]
|
||||
FI;
|
||||
result
|
||||
END # get element # ;
|
||||
|
||||
REF SEXPR s expr = get element;
|
||||
skip spaces;
|
||||
IF NOT at end THEN
|
||||
# extraneuos text after the expression #
|
||||
error( "Unexpected text at end of expression: " + s[ s pos : ] )
|
||||
FI;
|
||||
|
||||
s expr
|
||||
END # s reader # ;
|
||||
# prints an S expression #
|
||||
PROC s writer = ( REF SEXPR s expr )VOID:
|
||||
BEGIN
|
||||
# prints an S expression with a suitable indent #
|
||||
PROC print indented s expression = ( REF SEXPR s expr, INT indent )VOID:
|
||||
BEGIN
|
||||
REF SEXPR s pos := s expr;
|
||||
WHILE REF SEXPR( s pos ) ISNT REF SEXPR( NIL ) DO
|
||||
FOR i TO indent DO print( ( " " ) ) OD;
|
||||
CASE element OF s pos
|
||||
IN (VOID ): print( ( "()", newline ) )
|
||||
, (STRING s): print( ( s, newline ) )
|
||||
, (REF SEXPR e): BEGIN
|
||||
print( ( "(", newline ) );
|
||||
print indented s expression( e, indent + 4 );
|
||||
FOR i TO indent DO print( ( " " ) ) OD;
|
||||
print( ( ")", newline ) )
|
||||
END
|
||||
OUT
|
||||
error( "Unexpected S expression element" )
|
||||
ESAC;
|
||||
s pos := next OF s pos
|
||||
OD
|
||||
END # print indented s expression # ;
|
||||
|
||||
print indented s expression( s expr, 0 )
|
||||
END # s writer # ;
|
||||
# test the eader and writer with the example from the task #
|
||||
s writer( s reader( "((data ""quoted data"" 123 4.5)"
|
||||
+ nl
|
||||
+ " (data (!@# (4.5) ""(more"" ""data)"")))"
|
||||
+ nl
|
||||
)
|
||||
)
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import Text.ParserCombinators.Parsec ((<|>), (<?>), many, many1, char, try, parse, sepBy, choice)
|
||||
import Text.ParserCombinators.Parsec.Char (noneOf)
|
||||
import Text.ParserCombinators.Parsec.Token (integer, float, whiteSpace, stringLiteral, makeTokenParser)
|
||||
import Text.ParserCombinators.Parsec.Language (haskellDef)
|
||||
|
||||
import Data.Functor
|
||||
import Text.Parsec ((<|>), (<?>), many, many1, char, try, parse, sepBy, choice)
|
||||
import Text.Parsec.Char (noneOf)
|
||||
import Text.Parsec.Token (integer, float, whiteSpace, stringLiteral, makeTokenParser)
|
||||
import Text.Parsec.Language (haskell)
|
||||
|
||||
data Val = Int Integer
|
||||
| Float Double
|
||||
|
|
@ -10,40 +10,19 @@ data Val = Int Integer
|
|||
| Symbol String
|
||||
| List [Val] deriving (Eq, Show)
|
||||
|
||||
lexer = makeTokenParser haskellDef
|
||||
|
||||
tInteger = (integer lexer) >>= (return . Int) <?> "integer"
|
||||
|
||||
tFloat = (float lexer) >>= (return . Float) <?> "floating point number"
|
||||
|
||||
tString = (stringLiteral lexer) >>= (return . String) <?> "string"
|
||||
|
||||
tSymbol = (many1 $ noneOf "()\" \t\n\r") >>= (return . Symbol) <?> "symbol"
|
||||
|
||||
tAtom = choice [try tFloat, try tInteger, tSymbol, tString] <?> "atomic expression"
|
||||
|
||||
tExpr = do
|
||||
whiteSpace lexer
|
||||
expr <- tList <|> tAtom
|
||||
whiteSpace lexer
|
||||
return expr
|
||||
<?> "expression"
|
||||
|
||||
tList = do
|
||||
char '('
|
||||
list <- many tExpr
|
||||
char ')'
|
||||
return $ List list
|
||||
<?> "list"
|
||||
|
||||
tProg = many tExpr <?> "program"
|
||||
where tExpr = between ws ws (tList <|> tAtom) <?> "expression"
|
||||
ws = whiteSpace haskell
|
||||
tAtom = try (Int <$> integer haskell) <?> "integer"
|
||||
<|> try (Float <$> float haskell) <?> "floating point number"
|
||||
<|> String <$> stringLiteral haskell <?> "string"
|
||||
<|> Symbol <$> many1 (noneOf "()\"\t\n\r") <?> "symbol"
|
||||
<?> "atomic expression"
|
||||
tList = List <$> between (char '(') (char ')') (many tExpr) <?> "list"
|
||||
|
||||
p ex = case parse tProg "" ex of
|
||||
Right x -> putStrLn $ unwords $ map show x
|
||||
Left err -> print err
|
||||
p = either print (putStrLn . unwords . map show) . parse tProg ""
|
||||
|
||||
main = do
|
||||
let expr = "((data \"quoted data\" 123 4.5)\n (data (!@# (4.5) \"(more\" \"data)\")))"
|
||||
putStrLn $ "The input:\n" ++ expr ++ "\n"
|
||||
putStr "Parsed as:\n"
|
||||
putStrLn ("The input:\n" ++ expr ++ "\nParsed as:")
|
||||
p expr
|
||||
|
|
|
|||
|
|
@ -1,34 +1,55 @@
|
|||
use Text::Balanced qw(extract_delimited extract_bracketed);
|
||||
#!/usr/bin/perl -w
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub sexpr
|
||||
{
|
||||
my $txt = $_[0];
|
||||
$txt =~ s/^\s+//s;
|
||||
$txt =~ s/\s+$//s;
|
||||
$txt =~ /^\((.*)\)$/s or die "Not an s-expression: <<<$txt>>>";
|
||||
$txt = $1;
|
||||
my @stack = ([]);
|
||||
local $_ = $_[0];
|
||||
|
||||
my $ret = [];
|
||||
my $w;
|
||||
while ($txt ne '') {
|
||||
my $c = substr $txt,0,1;
|
||||
if ($c eq '(') {
|
||||
($w, $txt) = extract_bracketed($txt, '()');
|
||||
$w = sexpr($w);
|
||||
} elsif ($c eq '"') {
|
||||
($w, $txt) = extract_delimited($txt, '"');
|
||||
$w =~ s/^"(.*)"/$1/;
|
||||
while (m{
|
||||
\G # start match right at the end of the previous one
|
||||
\s*+ # skip whitespaces
|
||||
# now try to match any of possible tokens in THIS order:
|
||||
(?<lparen>\() |
|
||||
(?<rparen>\)) |
|
||||
(?<FLOAT>[0-9]*+\.[0-9]*+) |
|
||||
(?<INT>[0-9]++) |
|
||||
(?:"(?<STRING>([^\"\\]|\\.)*+)") |
|
||||
(?<IDENTIFIER>[^\s()]++)
|
||||
# Flags:
|
||||
# g = match the same string repeatedly
|
||||
# m = ^ and $ match at \n
|
||||
# s = dot and \s matches \n
|
||||
# x = allow comments within regex
|
||||
}gmsx)
|
||||
{
|
||||
die "match error" if 0+(keys %+) != 1;
|
||||
|
||||
my $token = (keys %+)[0];
|
||||
my $val = $+{$token};
|
||||
|
||||
if ($token eq 'lparen') {
|
||||
my $a = [];
|
||||
push @{$stack[$#stack]}, $a;
|
||||
push @stack, $a;
|
||||
} elsif ($token eq 'rparen') {
|
||||
pop @stack;
|
||||
} else {
|
||||
$txt =~ s/^(\S+)// and $w = $1;
|
||||
push @{$stack[$#stack]}, bless \$val, $token;
|
||||
}
|
||||
push @$ret, $w;
|
||||
$txt =~ s/^\s+//s;
|
||||
}
|
||||
return $ret;
|
||||
return $stack[0]->[0];
|
||||
}
|
||||
|
||||
sub quote
|
||||
{ (local $_ = $_[0]) =~ /[\s\"\(\)]/s ? do{s/\"/\\\"/gs; qq{"$_"}} : $_; }
|
||||
|
||||
sub sexpr2txt
|
||||
{ qq{(@{[ map { ref($_) eq '' ? quote($_) : sexpr2txt($_) } @{$_[0]} ]})} }
|
||||
{
|
||||
qq{(@{[ map {
|
||||
ref($_) eq '' ? quote($_) :
|
||||
ref($_) eq 'STRING' ? quote($$_) :
|
||||
ref($_) eq 'ARRAY' ? sexpr2txt($_) : $$_
|
||||
} @{$_[0]} ]})}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,24 +1,24 @@
|
|||
/*REXX program parses an S-expression and displays the results. */
|
||||
/*REXX program parses an S-expression and displays the results. */
|
||||
input= '((data "quoted data" 123 4.5) (data (!@# (4.5) "(more" "data)")))'
|
||||
say 'input:'; say input /*display the input data string to term*/
|
||||
say copies('═',length(input)) /*also, display a header fence. */
|
||||
groupO.= /*default value for grouping symbols. */
|
||||
groupO.1 = '{' ; groupC.1 = '}' /*grouping symbols (Open & Close). */
|
||||
groupO.2 = '[' ; groupC.2 = ']' /* " " " " " */
|
||||
groupO.3 = '(' ; groupC.3 = ')' /* " " " " " */
|
||||
# = 0 /*the number of tokens found (so far). */
|
||||
tabs = 10 /*used for the indenting of the levels.*/
|
||||
q.1 = "'" /*literal string delimiter, first. */
|
||||
q.2 = '"' /* " " " second. */
|
||||
numLits = 2 /*the number of kinds of literals. */
|
||||
seps = ',;' /*characters used for separation. */
|
||||
atoms = ' 'seps /*characters used to separate atoms. */
|
||||
level = 0 /*the current level being processed. */
|
||||
quoted = 0 /*quotation level (when nested). */
|
||||
groupu = /*used to go ↑ an expression level. */
|
||||
groupd = /* " " " ↓ " " " */
|
||||
$.= /*the stem array to hold the tokens. */
|
||||
do n=1 while groupO.n\=='' /*handle the number of grouping symbols*/
|
||||
say 'input:'; say input /*display the input data string to term*/
|
||||
say copies('═', length(input)) /*also, display a header fence. */
|
||||
groupO.= /*default value for grouping symbols. */
|
||||
groupO.1 = '{' ; groupC.1 = "}" /*grouping symbols (Open & Close). */
|
||||
groupO.2 = '[' ; groupC.2 = "]" /* " " " " " */
|
||||
groupO.3 = '(' ; groupC.3 = ")" /* " " " " " */
|
||||
# = 0 /*the number of tokens found (so far). */
|
||||
tabs = 10 /*used for the indenting of the levels.*/
|
||||
q.1 = "'" /*literal string delimiter, first. */
|
||||
q.2 = '"' /* " " " second. */
|
||||
numLits = 2 /*the number of kinds of literals. */
|
||||
seps = ',;' /*characters used for separation. */
|
||||
atoms = ' 'seps /*characters used to separate atoms. */
|
||||
level = 0 /*the current level being processed. */
|
||||
quoted = 0 /*quotation level (when nested). */
|
||||
groupu = /*used to go ↑ an expression level. */
|
||||
groupd = /* " " " ↓ " " " */
|
||||
$.= /*the stem array to hold the tokens. */
|
||||
do n=1 while groupO.n\=='' /*handle the number of grouping symbols*/
|
||||
atoms =atoms || groupO.n || groupC.n
|
||||
groupu=groupu || groupO.n
|
||||
groupd=groupd || groupC.n
|
||||
|
|
@ -28,38 +28,37 @@ literals=
|
|||
literals=literals || q.k
|
||||
end /*k*/
|
||||
!=
|
||||
/*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ text parsing ▒▒▒▒▒▒▒▒*/
|
||||
do j=1 to length(input); _=substr(input,j,1) /*▒*/
|
||||
/*▒*/
|
||||
if quoted then do; !=! || _ /*▒*/
|
||||
if _==literalStart then quoted=0 /*▒*/
|
||||
iterate /*▒*/
|
||||
end /*▒*/
|
||||
/*▒*/
|
||||
if pos(_,literals)\==0 then do; literalStart=_ /*▒*/
|
||||
!=! || _ /*▒*/
|
||||
quoted=1 /*▒*/
|
||||
iterate /*▒*/
|
||||
end /*▒*/
|
||||
/*▒*/
|
||||
if pos(_,atoms)==0 then do; !=! || _ ; iterate; end /*▒*/
|
||||
else do; call add!; !=_; end /*▒*/
|
||||
/*▒*/
|
||||
if pos(_,literals)==0 then do /*▒*/
|
||||
if pos(_,groupu)\==0 then level=level+1 /*▒*/
|
||||
call add! /*▒*/
|
||||
if pos(_,groupd)\==0 then level=level-1 /*▒*/
|
||||
if level<0 then say 'oops, mismatched' _ /*▒*/
|
||||
end /*▒*/
|
||||
end /*j*/ /*▒*/
|
||||
/*▒*/
|
||||
call add! /*handle any residual tokens.*/ /*▒*/
|
||||
if level\==0 then say 'oops, mismatched grouping symbol' /*▒*/
|
||||
if quoted then say 'oops, no end of quoted literal' literalStart /*▒*/
|
||||
/*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒*/
|
||||
/*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ text parsing ▒▒▒▒▒▒▒▒*/
|
||||
do j=1 to length(input); _=substr(input,j,1) /*▒*/
|
||||
/*▒*/
|
||||
if quoted then do; !=! || _ /*▒*/
|
||||
if _==literalStart then quoted=0 /*▒*/
|
||||
iterate /*▒*/
|
||||
end /*▒*/
|
||||
/*▒*/
|
||||
if pos(_,literals)\==0 then do; literalStart=_ /*▒*/
|
||||
!=! || _ /*▒*/
|
||||
quoted=1 /*▒*/
|
||||
iterate /*▒*/
|
||||
end /*▒*/
|
||||
/*▒*/
|
||||
if pos(_,atoms)==0 then do; !=! || _ ; iterate; end /*▒*/
|
||||
else do; call add!; !=_; end /*▒*/
|
||||
/*▒*/
|
||||
if pos(_,literals)==0 then do; if pos(_,groupu)\==0 then level=level+1 /*▒*/
|
||||
call add! /*▒*/
|
||||
if pos(_,groupd)\==0 then level=level-1 /*▒*/
|
||||
if level<0 then say 'oops, mismatched' _ /*▒*/
|
||||
end /*▒*/
|
||||
end /*j*/ /*▒*/
|
||||
/*▒*/
|
||||
call add! /*handle any residual tokens.*/ /*▒*/
|
||||
if level\==0 then say 'oops, mismatched grouping symbol' /*▒*/
|
||||
if quoted then say 'oops, no end of quoted literal' literalStart /*▒*/
|
||||
/*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒*/
|
||||
|
||||
do j=1 for #; say $.j; end /*display the tokens to the terminal. */
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*────────────────────────────────────────────────────────────────────────────*/
|
||||
add!: if !\='' then do; #=#+1; $.#=left('', max(0, tabs*(level-1)))!; end; !=
|
||||
return
|
||||
do m=1 for #; say $.m; end /*m*/ /*display the tokens to the terminal. */
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
add!: if !\='' then do; #=#+1; $.#=left('', max(0, tabs*(level-1)))!; end; !=
|
||||
return
|
||||
|
|
|
|||
|
|
@ -1,4 +1,44 @@
|
|||
$ txr -c '@(do (print (read)) (put-line ""))'
|
||||
((data "quoted data" 123 4.5) <- input from TTY
|
||||
(data (!@# (4.5) "(more" "data)")))
|
||||
((data "quoted data" 123 4.5) (data (! (sys:var #) (4.5) "(more" "data)"))) <- output
|
||||
@(define float (f))@\
|
||||
@(local (tok))@\
|
||||
@(cases)@\
|
||||
@{tok /[+\-]?\d+\.\d*([Ee][+\-]?\d+)?/}@\
|
||||
@(or)@\
|
||||
@{tok /[+\-]?\d*\.\d+([Ee][+\-]?\d+)?/}@\
|
||||
@(or)@\
|
||||
@{tok /[+\-]?\d+[Ee][+\-]?\d+/}@\
|
||||
@(end)@\
|
||||
@(bind f @(flo-str tok))@\
|
||||
@(end)
|
||||
@(define int (i))@\
|
||||
@(local (tok))@\
|
||||
@{tok /[+\-]?\d+/}@\
|
||||
@(bind i @(int-str tok))@\
|
||||
@(end)
|
||||
@(define sym (s))@\
|
||||
@(local (tok))@\
|
||||
@{tok /[^\s()]+/}@\
|
||||
@(bind s @(intern tok))@\
|
||||
@(end)
|
||||
@(define str (s))@\
|
||||
@(local (tok))@\
|
||||
@{tok /"(\\"|[^"])*"/}@\
|
||||
@(bind s @[tok 1..-1])@\
|
||||
@(end)
|
||||
@(define atom (a))@\
|
||||
@(cases)@\
|
||||
@(float a)@(or)@(int a)@(or)@(str a)@(or)@(sym a)@\
|
||||
@(end)@\
|
||||
@(end)
|
||||
@(define expr (e))@\
|
||||
@(cases)@\
|
||||
@/\s*/@(atom e)@\
|
||||
@(or)@\
|
||||
@/\s*\(\s*/@(coll :vars (e))@(expr e)@/\s*/@(last))@(end)@\
|
||||
@(end)@\
|
||||
@(end)
|
||||
@(freeform)
|
||||
@(expr e)@junk
|
||||
@(output)
|
||||
expr: @(format nil "~s" e)
|
||||
junk: @junk
|
||||
@(end)
|
||||
|
|
|
|||
|
|
@ -1,44 +1 @@
|
|||
@(define float (f))@\
|
||||
@(local (tok))@\
|
||||
@(cases)@\
|
||||
@{tok /[+\-]?\d+\.\d*([Ee][+\-]?\d+)?/}@\
|
||||
@(or)@\
|
||||
@{tok /[+\-]?\d*\.\d+([Ee][+\-]?\d+)?/}@\
|
||||
@(or)@\
|
||||
@{tok /[+\-]?\d+[Ee][+\-]?\d+/}@\
|
||||
@(end)@\
|
||||
@(bind f @(flo-str tok))@\
|
||||
@(end)
|
||||
@(define int (i))@\
|
||||
@(local (tok))@\
|
||||
@{tok /[+\-]?\d+/}@\
|
||||
@(bind i @(int-str tok))@\
|
||||
@(end)
|
||||
@(define sym (s))@\
|
||||
@(local (tok))@\
|
||||
@{tok /[^\s()]+/}@\
|
||||
@(bind s @(intern tok))@\
|
||||
@(end)
|
||||
@(define str (s))@\
|
||||
@(local (tok))@\
|
||||
@{tok /"(\\"|[^"])*"/}@\
|
||||
@(bind s @[tok 1..-1])@\
|
||||
@(end)
|
||||
@(define atom (a))@\
|
||||
@(cases)@\
|
||||
@(float a)@(or)@(int a)@(or)@(str a)@(or)@(sym a)@\
|
||||
@(end)@\
|
||||
@(end)
|
||||
@(define expr (e))@\
|
||||
@(cases)@\
|
||||
@/\s*/@(atom e)@\
|
||||
@(or)@\
|
||||
@/\s*\(\s*/@(coll :vars (e))@(expr e)@/\s*/@(last))@(end)@\
|
||||
@(end)@\
|
||||
@(end)
|
||||
@(freeform)
|
||||
@(expr e)@junk
|
||||
@(output)
|
||||
expr: @(format nil "~s" e)
|
||||
junk: @junk
|
||||
@(end)
|
||||
@/\s*\(\s*/@(coll :vars (e))@(expr e)@/\s*/@(last))@(end)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue