/* Carnap - a process oriented programming model and language for many-core processors, many many-core parallel and distributed systems. The process oriented programming model used by Carnap separates the concerns of data structures and the concurrent processes that create them and act upon them. Carnap is based on the language Ease, first specified at Yale University in 1990. In turn Ease is influenced by Occam, designed by David May, myself and others at INMOS, and Linda, designed at Yale University by David Gelernter. The formal basis of Occam, Ease and Carnap is CSP (Communicating Sequential Processes). Carnap is named in honor of the logician Rudolf Carnap (1891-1970). Rudolf Carnap made significant contributions to logic and the philosophy of science. His widely influential work includes "The Logical Structure of the World," "The Logical Syntax of Language," and "Meaning and Necessity." In "The Logical Structure of the World" Carnap argued, as do I, that natural apprehension is the product of a differentiation or "reduction" against the entire body of sense data. This positivist view is one that requires a certain non-locality. It is contrary to the view widely held in Computer Science since the work of Alan Turing. Turing recognized this non-locality but did not consider an explanation of it necessary. Hence, since Turing, the mainstream view has been integrative. That is, natural apprehension is viewed in contemporary Computer Science as an integration of the logical parts with strong locality. Hence, no language of Computer Science, as implemented by contemporary computer architectures, truly embodies the position taken by Carnap and myself. What is clear, however, is that the physical models that implement apprehension in the world are massively parallel, and the logical reductions from the whole that we seek are based upon a process interaction model in nature that is now poorly understood. Advancing this understanding is the core mission of IASE. The language here then will potentially evolve toward logical differentiation as the new generation of many-core devices become available. There are lessons to learn by engineering new process interaction fabrics that must implement our models, and we anticipate that new physical data from the life sciences will teach us more. These lessons may eventually enable a new type of device that can meet our goals. Only then will this language truly deserve the name "Carnap." -- Steven Ericsson-Zenith, IASE, Sunnyvale, March 2007. Version 2.10.04.04.2007 ANTLR (primary.secondary.release-version.month.year) This version is the second full language iteration and based on the 1.09 Ease grammar Copyright (C) 1991, 1992, 2007 Steven Ericsson Zenith Copyright (C) 2007 Institute for Advanced Science & Engineering. Sunnyvale, California. http://www.iase.info The Carnap project site is located at : http://www.carnap.info Creative commons license http://creativecommons.org/licenses/by-sa/3.0/ */ grammar carnap ; options { k=*; backtrack=false; output=AST;} tokens { /* -> => >| */ COERCE= '->'; COERCETRUNC= '->trunc'; COERCEROUND= '->round'; ASSERT= '=>'; CAST= '>|'; /* expression symbols */ /* * / % ^ */ MUL= '*'; DIV= '/'; REM= '%'; EXP= '^'; /* = <> > < >= <= */ EQ= '='; NE= '!='; GT= '>'; LT= '<'; GE= '>='; LE= '<='; /* /\ \/ >< */ BITAND= '/\\'; BITOR= '\\/'; BITXOR= '><'; /* >> << */ RSHIFT= '>>'; LSHIFT= '<<'; /* ~ ! */ COMPLEMENT= '~'; BOTTOM= '_'; /* boolean */ TRUE= 'true'; FALSE= 'false'; /* AST TAG */ BOOLEAN_TAG; BIT_TAG; LOGICAL_TAG; COND_TAG; OP_TAG; TYPE_TAG; ASSIGN_TAG; SUB_TAG; BASE_TAG; LIMIT_TAG; FIELD_TAG; LAMBDA_TAG; FUNC_TAG; ID_TAG; ARGS_TAG; BODY_TAG; NAME_TAG; PROC_TAG; REP_TAG; NAMELIST_TAG; IN_TAG; OUT_TAG; COOP_TAG; SUBORD_TAG; EXPR_TAG; EXPRLIST_TAG; FLOAT_TAG; INT_TAG; CHAR_TAG; BOOL_TAG; BAG_TAG; SHARED_TAG; PROG_TAG; ASSIGNMENT_TAG; CONTEXTASSIGNMENT_TAG; CONSTRUCTION_TAG; PROCESS_TAG; } @parser::header {package info.carnap.tools.comp.frontend.parser;} @lexer::header {package info.carnap.tools.comp.frontend.parser;} /* processes */ program : o ( specification o )+ ':' o construction -> ^(PROG_TAG specification+ construction) ; /* processes describe the structure of "behavior" */ process : ( ( specification o )+ ':' o -> ^(specification)+ )? ( action -> ^(action $process ) | 'unfold'? instance -> ^(instance 'unfold'? $process ) | construction -> ^(PROCESS_TAG ^(CONSTRUCTION_TAG construction) $process) ) ; /* actions are the elements of behavior */ action : assignment | interaction | 'stop' | 'skip' ; /* constructions describe the structure of processes */ construction : sequence | test | selection | choice | cooperation | subordination | repetition ; /* The behavior of a program is defined entirely by its actions Actions change state An assignment changes local state An interaction is an assignment that changes nonlocal state For convenience, the following assignments are equivalent to interactions context := expression -> write expression to context element := context -> read element from context context ! reference -> put reference to context context ? reference -> get reference from context Increment and decrement are abbreviations ++ v -> v := v + 1 -- v -> v := v - 1 Note that a similar monadic is available for use in expressions */ assignment : (element -> ^(element)) ( (assign -> ^(ASSIGNMENT_TAG assign $assignment)) | ('!' -> ^(IN_TAG $assignment)) | ('?' -> ^(OUT_TAG $assignment)) ) o expression ( 'at' address )? -> ^($assignment expression ^('at' address)?) | '++' element -> ^(OP_TAG '++' element) | '--' element -> ^(OP_TAG '--' element) ; interaction : input | output | combination | apply ; /* an input describes an interaction between a shared context and a local state */ input : read | get ; /* an output describes an interaction between a local state and a shared context */ output : write | put ; /* a read changes the local state */ read : 'read'^ element ( ',' o! element )* o! 'from' context ( 'at'^ address )? ; /* a write changes the state of a shared context */ write : 'write'^ element ( ',' o! element )* o! 'to' context ( 'at'^ address )? ; /* a get changes the local state and the state of the shared context an element of the shared context is moved to the local scope */ get : 'get'^ reference ( ',' o! reference )* o! 'from' context ( 'at'^ address )? ; /* a put changes the state of the shared context and the local state an element of the local scope is moved to the shared context */ put : 'put'^ reference ( ',' o! reference )* o! 'to' context ( 'at'^ address )? ; /* apply the specified transformation to the elements in the context the procedure must have a formal type profile that is valid for the context and the context must be specified to be a pliable type procedures are considered to have two type profiles one for variables, and one for constants and, recall, they are side-effect free e.g., procedure p ( int v, val bool b ) test b : ++v else --vv . ... apply p ( true ) to k applies the transformation p to elements in the pliable context k, k must possess a type context k := bag int pliable procedures are considered to have two type profiles one for variables, and one for constants This feature is experimental in this version of the language. Semantics: an apply is an abbreviation for the sequence { n := size of k || i for n : choice get v[i] from k : p( v[i], true ) else skip . . || i for n : k ! v[i] . } with all the semantics and nondeterminism that this implies Usage issues: 1. concurrent application - obviously more than one process can apply concurrently 2. there is no guarantee of the order of concurrent transformations 3. there is no guarantee that the transformation is applied to all elements */ apply : 'apply'^ instance o! 'to'! context ; context : element ; address : element ; /* a combination guarantees an interaction between two processes - think "RPC" */ combination : call | reply ; /* a call outputs a state for processing and is guaranteed the get input response */ call : 'call'^ output o! 'reply'! reference ; /* a reply inputs a state for processing and the output will satisfy the corresponding call */ reply : 'resource'^ get ( ':'! o! process )? ( 'write'^ expression | 'put'^ reference ) ; reference : NAME ; /* a sequence describes actions that occur according to their lexical order an "on stop" process is executed when the sequence terminates normally or by detectable exception this allows the developer to write processes for exceptional ternmination and debugging */ sequence : '{' o ( ( 'on' 'stop' o (p=process) ':' o )? ( process ooo )+ -> ^(BODY_TAG ('on' 'stop' $p)? ( process )+) | replicator ':' o process ooo -> ^(BODY_TAG replicator ':' process) ) '}' ; /* guarded sequences */ selector : expression ; match_list : expression ( ',' o expression )* -> ^(EXPRLIST_TAG expression+) ; test : 'test' o ( ( condition ':' o process ooo )+ -> ^('test' (condition process)+) | ( replicator ':' o condition ':' o process ooo -> ^('test' replicator condition process))) ( 'else' o p=process ooo )? end -> ^($test ^('else' $p)? end) ; selection : 'select'^ o! selector ':' o! ( match_list ':'! o! process ooo! )+ ( 'else'^ o! process ooo! )? end ; /* a choice is a guarded process - a "ready" process is executed ... pick one */ choice : 'choice'^ o! ( replicator ':'! o! alternative ooo! | ( alternative ooo! )+ ) ( 'else'^ ( 'after'^ time ':'! )? o! process ooo! )? end ; /* allow assignment abbreviations for inputs? assignment abbreviations for inputs are permitted, no other */ alternative : ( ( 'test'^ condition ':'! o! )? ( ( ( input | assignment ) o! )? ':'! o! process | reply ) ) ; time : float_expression ; /* a cooperation describes the behavior of cooperating processes a cooperation terminates when all the component processes terminate */ cooperation : '||' o ( replicator ':' o )? ( process ooo )+ end -> ^(COOP_TAG replicator? process+ end) ; /* a subordination describes a set of processes that terminate independently */ subordination : '//' o ( replicator ':' )? ( 'on' ( node | core ) ':' o )? process ooo end -> ^(SUBORD_TAG replicator? ('on' node? core? )? process end) ; /* a repetition is a sequence of guarded processes */ repetition : 'while'^ condition o! ':'! o! process | ('do' o process 'until' condition -> ^('do' condition process) ) ; /* a replicator specifies the number of processes to construct */ replicator : ( 'replicate' )? replicant 'for'^ count ( o! 'from'! base ( o! 'by'! step )? )? ; replicant : NAME ->^(ID_TAG NAME) ; /* substitution semantics. qname is a procid or qualified name that leads to a procid */ instance : qname '(' expression_list? ')' -> ^(PROC_TAG qname expression_list?) ; /* specifications */ specification : declaration | definition | 'use' classid 'as' NAME -> ^('use' classid NAME) // reserve name and optional type profile for later use | 'reserve'^ NAME ( '('! ( type ( ','! o! type )*)? ')'! )? ; /* a definition specifies a lexical substitution */ definition : procedure | function | prototype | typedef | classdef | alien ; /* a declaration gives a name to a state */ declaration : 'let'^ local_specifier ( ','! o! local_specifier )* | 'context' context_specifier ( ',' o context_specifier )* -> ^('context' context_specifier+) | 'enumerate'^ ( 'from'^ base )? NAME ( ','! o! NAME )* ; /* specifiers of constants, variables, and aliases. Note that types are derived from expressions. Typing is polymophic and statically determined by usage in expressions. */ local_specifier : NAME ( '=' o expression -> ^(COND_TAG '=' ^(ID_TAG NAME) expression) | ( ( ',' o NAME )* ( assign -> ^(assign ^(ID_TAG NAME)+) | 'allocate' -> ^('allocate' ^(ID_TAG NAME)+) ) o allocation -> ^($local_specifier allocation) | 'renames' o element -> ^('renames' ^(ID_TAG NAME) element) ) ) ; /* a pliable context can have transformations applied */ context_specifier : NAME assign typeid ( 'pliable' )? -> ^(CONTEXTASSIGNMENT_TAG assign NAME typeid 'pliable'?) ; allocation : expression ( 'on'! node )? ; node : 'node'^ expression ( 'at'! expression )? ; core : 'core'^ expression ; /* an alien process is written in a language other than Carnap and is beyond Carnap's checking capabilities alien processes behave like procedures, they may transform their formal parameters implementations must guarantee that the process is free of side effects alien processes can interact with Carnap contexts through an appropriate library the text passed in the text field here is entirely implementation dependent I suggest we specify an xml schema for this text we can, perhaps, consider inline Java code */ alien : 'alien' procid '(' o pformal_list? ')' o TEXT -> ^('alien' procid pformal_list? ^(BODY_TAG TEXT)) ; /* the semantics of substitution names specified for procedures, functions and modules are abbreviations semantically, procedures specify transformations upon their formal parameters, they are substituted by their process body and parameter specification functions are substituted by their lambda expression and parameter specification classes are abbreviated specification blocks that produce qualified names and provide class encapsulation given procedure p( v ) ++ v the instance p ( c ) is exactly equivalent to ++c given function f (x) = x^2 the expression f(5) is exactly equivalent to the lambda expression = 5^2 given class c public let v := _ -> int use c as o : is exactly equivalent to the specification let o.v := _ -> int : */ /* Unlike Ease, Carnap *does not* allow free variables to appear in procedures Carnap procedures are, strictly, named processes they are transformations of the specified formals this requirement enables process types undefined procedures are assigned behavior by input from contexts of process type an instance of an undefined procedure is invalid */ procedure : 'procedure'^ procid '('! o! pformal_list? ')'! o! ( process | 'undefined' ) ; procid : NAME ; pformal_list : pformal ( ',' o pformal )* -> ^(ARGS_TAG ^(pformal)+) ; /* procedures have two type profiles - one for variables and one for constants procedure p ( v, val bool b ) test b : ++ v else --v . has a polymophic type footprint v, and a constant bool footprint */ pformal : ( compliant )? NAME^ | 'val' compliant NAME^ ; function : 'function'^ funcid '('! o! fformal_list? ')'! o! function_expression ; funcid : NAME -> ^(NAME) ; function_expression : '=' expression ( 'where' o process )? -> ^(BODY_TAG expression ( ^('where' process) )?) ; fformal_list : fformal ( ',' o fformal )* -> ^(ARGS_TAG ^(ID_TAG fformal)+) ; fformal : ( compliant )? NAME^ ; compliant : type ; /* classes - classes are the only source of qualified names a qualified name is a reference to a specification made in a module thus the algebraic transformation of modules produces invalid Carnap code (but valid Carnap.Razor code) because qualified names are not allowed everywhere. The flattened intermediate form of Carnap, Carnap.Razor, is Carnap in it's simplified form. it has no has no modules, procedure or function specifications and all names are unique qualified names. Processes in Carnap.Razor are the sole units of program composition. The Carnap abstract machine specification, Carnap.Basis, specifies how Carnap.Razor programs are to be rewritten to the target machine. */ classdef : 'class' c1=classid o ( 'extends' c2=classid o )? publicdef ( privatedef )? ':' -> ^('class' $c1 ( ^( 'extends' $c2) )? publicdef (privatedef)? ) ; publicdef : 'public'^ o! ( specification ooo! )+ ; privatedef : 'private'^ o! ( specification ooo! )+ ; classid : NAME -> ^(NAME) ; /* types */ type : primitive_type -> ^(TYPE_TAG primitive_type) | tuple_type | array_type | record_type | query_type | 'counted'? integer_type '[' limit ']' '::' type | typeid | 'type'^ 'of' expression ; /* a word on process types and prototypes Contexts can contain process types allowing processes to pass around processes defined as procedures. This is experimental in this version of the langauge it is intended to enable process schedulers to be written in Carnap. here is how it works prototypes define the type profile of formals to a procedure prototype p ( int ) contexts can transport procedures with this formal profile type q context stream p context k := q since procedures specify transformations on their formals a process for which s is specified can then say || procedure r ( x ) ++ x :b ... } let i = 0 reserve n ( int ) : { get n from k ** n is now specified and can be respecified by subsequent inputs unfold n ( i ) ** n now unfolded ("executed") } . processes of this kind must be proceeded by the 'unfold' keyword processes of this kind must be self-contained - this means they cannot use non-standard libraries from outside their scope */ typedef : 'type' typeid ( 'is' type -> ^('type' ^('is' typeid type)) | 'context' bag ( '|' o bag )* -> ^('type' ^('context' typeid bag+)) ) ; /* a prototype specifies the formal profile "fingerprint" of a process type */ prototype : 'prototype'^ typeid '('! ( type ( ',!' o! type)* )? ')' ; typeid : NAME ; /* context types - shared types that can be created by and acted upon by concurrent processes */ bag : ( priority ':' o )? bag_type -> ^(SHARED_TAG bag_type+ priority?) ; /* the ordering of elements in contexts */ bag_type: ( '[' integer_expression ']' -> ^(SUB_TAG integer_expression) )* ( unordered -> ^(unordered $bag_type) | singleton -> ^(singleton $bag_type) | stream -> ^(stream $bag_type) | series -> ^(series $bag_type) | addressable -> ^(addressable $bag_type) | database -> ^(database $bag_type) | exchange -> ^(exchange $bag_type) | channel -> ^(channel $bag_type) ) ; /* why not call bags "sets" ? because we cannot implement the set operations with the strong locality that people would expect */ unordered : 'bag'^ type ; /* singletons are addressable and overwritten by outputs to them */ singleton : 'single'^ type ; /* streams are ordered according to interactions and the number of processes contributing to the stream */ stream : 'stream'^ type ; /* like streams but can be randomly accessed */ series : 'series'^ type ; /* point-to-point communication via channels a channel is a rendezvous point for processes that wish to wait on the readiness of a recipient process before proceeding or wait on a sender Ease semantics, not Occam semantics multi-directional usage, any process can use a channel that is in scope channels are essentially streams that do not buffer (i.e. channels block on output, they are the only context type that blocks on output) programmers will need strong discipline and usage checking tools to use channels This is Carnap's low level interaction type - all contexts can be transformed by equivalence to processes and interactions on channels. */ channel : 'channel'^ type ; /* resource call-reply semantics */ exchange : 'resource'^ type o! 'reply'! type ; /* an SQL context */ database : 'database' query_type o 'connect' ( element | TEXT ) -> ^('database' query_type ^(BODY_TAG element? TEXT? )) ; /* context types that can be located by a URI */ addressable : 'addressable'^ ( 'http' | 'folder' | 'file' ) ( 'known' 'as' ( element | TEXT ) )? ; priority : ( 'lo' | 'hi' | 'first' | 'last' ) ; /* primitive types */ primitive_type : 'bool' -> ^(BOOLEAN_TAG 'bool') | integer_type -> ^(INT_TAG integer_type) | 'unsigned' integer_type -> ^(INT_TAG integer_type 'unsigned') | float_type -> ^(FLOAT_TAG float_type) ; integer_type : 'int' | 'char' | 'int8' | 'int16' | 'int32' | 'int64' | 'int128' ; float_type : 'float' | 'float32' | 'float64' | 'float128' ; array_type : '[' integer_expression ']' type -> ^(SUB_TAG type integer_expression ) | '[]' type -> ^(SUB_TAG type) | 'string'^ ; tuple_type : 'tuple'^ '(.'! o! type ( ','! o! type )+ o! '.)'! ; /* the typeid in records and query types correspond to field names and provide addressable names for use in elements of the type */ record_type : 'record'^ '[$'! typeid ( ','! o! typeid )+ '$]'! ; /* the table returned by an SQL query will be addressed by the specified typeid name e.g., the expression sql_query[n]fieldname returns the value of the column with that name in row n queries must return tables with the exact number of fields */ query_type : 'query'^ '[$'! typeid ( ','! o! typeid )+ o! '$]'! ( 'sql'^ string )? ; /* elements and expressions */ literal : CHARACTER | TEXT | number | TRUE -> ^(BOOLEAN_TAG TRUE) | FALSE -> ^(BOOLEAN_TAG FALSE) | BOTTOM ; tuple : '(.' expression ( ',' o expression )+ '.)' -> ^(EXPR_TAG '(.' expression+) ; record : '[$' expression ( ',' o expression )* '$]' -> ^(EXPR_TAG '[$' expression+) ; table : '[' expression ( ',' o expression )* ']' -> ^(EXPR_TAG '[' expression+) ; /* elements, their constraints */ element : ( qname->^(qname) | tuple->^(tuple) | table->^(table) | record->^(record) | ('slice' TEXT->^('slice' TEXT)) ) ( '[' subscript o ( ']' -> ^($element ^(SUB_TAG subscript)) | '..)' -> ^($element ^(BASE_TAG subscript)) | ('for' count -> ^($element ^('for' subscript count)) | 'to' limit -> ^($element ^('to' subscript limit)) ) o ']' ) | '(..' limit o ']' -> ^($element ^(LIMIT_TAG limit)) | '$' fieldname ( ',' o fieldname )* '$' -> ^($element ^(FIELD_TAG fieldname+)) )* ; lambda : funcid '(' arg_list? ')' -> ^(FUNC_TAG ^(funcid) arg_list?) | ( declaration )+ ':' '(' function_expression ')' -> ^(LAMBDA_TAG declaration+ function_expression) ; arg_list : expression ( ',' o expression )* -> ^(ARGS_TAG expression+) ; /* integrates template language ST by Terrance Parr procedure page ( name, address, telephone ) let p = template "My name is $name$ and I live at $address$ my telephone number is $telephone$" [ name , address, telephone ] write p to webserver at uri ... q = template address_query [ name ] */ template: 'template'^ o! string o! ( '['! o! ( NAME assign^ )? expression ( ','! o! ( NAME assign^ )? expression )* o! ']'! ) // substitution on string templates ; /* a restricted string expression */ string : TEXT | qname ; primary : literal | element | template | lambda | '(' o ( expression -> ^(expression) | 'if' condition o ':' o ifexpr=expression o 'else' o elseexpr=expression -> ^('if' condition $ifexpr ^('else' $elseexpr) ) ) o ')' ; mon : ('+' -> ^(OP_TAG '+')) |('-' -> ^(OP_TAG '-')) |('!' -> ^(OP_TAG '!')) |(COMPLEMENT -> ^(OP_TAG COMPLEMENT)) |('size' 'of' -> ^(OP_TAG 'size')) |('++' -> ^(OP_TAG '++')) |('--' -> ^(OP_TAG '--')) ; monadic : (mon^)? primary ; assign : ':=' -> ^(ASSIGN_TAG) ; exponent : monadic ( EXP^ monadic )* ; multiplicative : (exponent->^(exponent)) ( ((e1=MUL|e1=DIV|e1=REM ) o e2=exponent) ->^(OP_TAG $e1 $e2 $multiplicative))* ; additive : (multiplicative -> ^(multiplicative)) ( ((a1='+'|a1='-') o a2=multiplicative) ->^(OP_TAG $a1 $a2 $additive))* ; shift : (additive->^(additive)) ( (s1=LSHIFT|s1=RSHIFT) o s2=additive ->^(OP_TAG $s1 $s2 $shift))* ; relational : (shift->^(shift)) ((r1=LT|r1=GT|r1=LE|r1=GE) o r2=shift ->^(COND_TAG $r1 $r2 $relational) )* ; equality : (relational ->^(relational)) ((e1='=' |e1='!=') o e2=relational ->^(COND_TAG $e1 $e2 $equality) )* ; bitwise : (equality->^(equality)) ((b1=BITAND |b1=BITOR |b1=BITXOR ) o b2=equality->^(BIT_TAG $b1 $b2 $bitwise) )* ; logical : (bitwise->^(bitwise)) ((b1='and' | b1='or' | b1='xor' ) o b2=bitwise->^(LOGICAL_TAG $b1 $b2 $logical) )* ; constraint : logical ( typing^ type )? ; typing : COERCE -> ^(TYPE_TAG COERCE) | COERCETRUNC -> ^(TYPE_TAG COERCETRUNC) | COERCEROUND -> ^(TYPE_TAG COERCEROUND) | ASSERT -> ^(TYPE_TAG ASSERT) | CAST -> ^(TYPE_TAG CAST) ; expression : constraint ; expression_list : expression ( ',' o expression )* -> ^(ARGS_TAG expression+) ; /* semantic typing limiters */ subscript : integer_expression ; fieldname : typeid ; base : integer_expression ; count : integer_expression ; limit : integer_expression ; step : integer_expression ; condition : expression ; // boolean_expression integer_expression : expression ; float_expression : expression ; /* Lexical Format: Newlines and colon for use in constructions and terminators */ o : NEWLINE*; ooo : NEWLINE+; /* end of construct */ end : '.'!; /* Names and qualified names */ qname : NAME ( '.' NAME )* -> ^(ID_TAG NAME+); NAME : VALIDNAME ; /* Literals */ TEXT : '"' ( CHAR )* '"' ; CHARACTER : '\'' CHAR '\'' ; number : INTEGER -> ^(INT_TAG INTEGER) | FLOAT -> ^(FLOAT_TAG FLOAT) ; /* Fragments */ fragment VALIDNAME : ('a'..'z'|'A'..'Z')('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'\'')* ; fragment CHAR : ~'"' ; INTEGER : '0'..'9'+|'#'('0'..'9'|'A'..'F'|'a'..'f')+ ; FLOAT : '0'..'9'+('.''0'..'9'+|(('e'|'E')('+'|'-')?'0'..'9'+'.''0'..'9'+)) ; /* Hidden input */ COMMENT : '/*' ( options {greedy=false;} : . )* '*/' { skip(); } | '**' ~( '\n' | '\r' )* '\r'? {skip();} ; WHITESPACE : ( ' ' | '\t' ) { skip(); }; NEWLINE : ( '\r' | '\u000C' | '\n' ) ;