Welcome to a another fun feature: String Grammars.

////////////////////////////
#import <flx.flxh>
syntax extension {
  sexpr := extn =># "_1";
  extn : string = "my" "silly" sname (, sname)* strint?;
}
open syntax extension;

println$ (my silly x, y 42);
println$ (my silly x, y) + "!!";
/////////////////////////

my silly x , y 42
my silly x , y!!
//////////////////////

A string rule is introduced by the syntax:

        nt : string = rhs ;

The RHS can consist of any token, or any nonterminal
returning a string. The result is a string expression.

sname returns a string.

The following special nonterminals exist:

strint            integer as string
strfloat          float as string
strstring         string with quotes
strtrue           "true"
strfalse          "false"
strepsilon        ""

All keywords, user keywords and user symbols return their
spelling as a string. The nonterminal 'sstring' returns
the *contents* of a string, i.e. unquoted.

The general rule is to concatenate the strings with a single
space as separator. Null strings are not separated though.
(to avoid gratuitous spaces)

The metarules * + ? and () all work as expected with strings.

String rules MAY have user actions which override the default
concatenation rule.

The 'string' property is NOT associated with a nonterminal,
only a particular rule (including any synthesised meta-rules).
A valid Scheme string value is returned. If a string rule
tries to use a non-string non-terminal value, a Scheme Error
occurs whilst parsing.

The effect of (the default) string rules is simply to parse
some text and convert it to a string, in other words, all it
does is syntax check the text.

The purpose of introducing this features was to facilitate the
sqlite3 SQL syntax support. Since sqlite3 accepts SQL in the
form of strings, a string grammar provides a lazy way to 
construct these strings with syntactic validation without
having to specify complex user actions. Of course the result
is that no real checking (eg no typechecks) are done.

Note: at present an exact (case-sensitive) match is required.
A way to do insensitive matches and normalise the result to
one case would be useful.

EXTENSION IDEA
**************

The rhs symbol:

        "silly"

is used to match an identifier spelled silly. This is a 
"poor mans keyword". A real keyword would parse faster
and reduce ambiguities, but this form doesn't spend
an identifier globally.

This is implemented by:

(a) We tell Dypgen to look for a NAME:

      | STRING _ -> Dyp.Ter Dyp_symbols.t_NAME

(b) we check we got the right one and Giveup otherwise:

         | STRING (_,s1),`Obj_NAME (sr,s2) ->
            if s1 <> s2 then raise Giveup;
            slift sr,Sstring s1
             
Now .. the check 

        s1 <> s2

could easily be generalised to:

        regmatch s1 s2

that is, there's no real reason not to match against a regular
expression (except that Ocaml provides a broken regexp engine ;)


        
-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
_______________________________________________
Felix-language mailing list
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to