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