This should go in the docs ..
How to do literals
==============
Step 1. Define the lexicology.
+++++++++++++++++++++++
You will typically make a file like
lib/grammar/grammar_float_lexer.flxh
shown below. Don't forget to add this to the syntax file list
lib/grammar/grammar.files
so it is included. You may also open the syntax in two steps:
first add the dssl (Domain Specific Sublanguage) name to the
requirements for felix in:
lib/grammar/grammar_lexer.flxh
which includes:
syntax lexer {
requires global_regdefs;
requires felix_ident_lexer;
requires felix_ident_lexer;
requires felix_int_lexer;
requires felix_float_lexer;
requires felix_string_lexer;
}
which it present is a security check, and also ensures your
grammar is opened (because it's required by felix
in lib/grammar/felix.flxh, and opened in
lib/grammar/save.flxh which is the file that actually
builds the automaton).
Your definition for floating literals is like this:
// lib/grammar/grammar_float_lexer.flxh
syntax felix_float_lexer {
// provide some regular definition helpers
regdef decimal_string = digit (underscore? digit) *;
regdef hexadecimal_string = hexdigit (underscore? hexdigit) *;
regdef decimal_fractional_constant =
decimal_string '.' decimal_string;
regdef hexadecimal_fractional_constant =
("0x" |"0X")
hexadecimal_string '.' hexadecimal_string;
regdef decimal_exponent = ('E'|'e') ('+'|'-')? decimal_string;
regdef binary_exponent = ('P'|'p') ('+'|'-')? decimal_string;
regdef floating_suffix = 'L' | 'l' | 'F' | 'f' | 'D' | 'd';
// here's the final definition for floats
regdef floating_literal =
(
decimal_fractional_constant decimal_exponent? |
hexadecimal_fractional_constant binary_exponent?
)
floating_suffix?;
// Now a nice shorthand
regdef sfloat = floating_literal;
// Now, use the literal keyword to lift the regular
// expression "sfloat" into the grammar, that is,
// make it a non-terminal
// The Scheme action code makes a tripe
//
// ( felix-type value C-encoding)
//
// which it does by examining the lexeme
literal sfloat =># """
(let*
(
(val (stripus _1))
(val (tolower-string val))
(n (string-length val))
(n-1 (- n 1))
(ch (substring val n-1 n))
(rest (substring val 0 n-1))
(result
(if (equal? ch "l") `("ldouble" ,val ,val)
(if (equal? ch "f") `("float" ,val ,val) `("double" ,val ,val))
)
)
)
result
)
""";
// Now all we have to do is convert the literal value
// into an actual AST value of literal type
// and tell the parser the non-terminal sfloat
// is a sliteral with a new production for sliteral
sliteral := sfloat =># "`(ast_literal ,_sr ,@_1)";
// if you check the grammar for expressions you'll
// fine sliteral's are already counted as expressions
// so we just added a new kind of expression
}
Step 2: Define the type
++++++++++++++++++
We now have to define the types we introduced
in the **top level** of some library file.
For the floats this has been done in
lib/plat/ctypedefs.flx:
pod type float = "float";
pod type double = "double";
pod type ldouble = "long double";
Note this is a generated file (so don't look in
src/lib/ for it, look in build/release/lib/plat
instead).
Of course, one has to also define operations on
these types .. but you already know now to do that
in Felix!
So now you can write
var x = 0.2f; // float literal
and the ability to write 0.2f as part of the Felix language
is now entirely defined in the library. The compiler
knows nothing about it.
--
john skaller
[email protected]
http://felix-lang.org
------------------------------------------------------------------------------
Better than sec? Nothing is better than sec when it comes to
monitoring Big Data applications. Try Boundary one-second
resolution app monitoring today. Free.
http://p.sf.net/sfu/Boundary-dev2dev
_______________________________________________
Felix-language mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/felix-language