aboutsummaryrefslogtreecommitdiff
path: root/frontend/parse.icl
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/parse.icl')
-rw-r--r--frontend/parse.icl2811
1 files changed, 2811 insertions, 0 deletions
diff --git a/frontend/parse.icl b/frontend/parse.icl
new file mode 100644
index 0000000..78c3780
--- /dev/null
+++ b/frontend/parse.icl
@@ -0,0 +1,2811 @@
+implementation module parse
+
+import StdEnv
+import scanner, syntax, hashtable, utilities, predef
+
+// RWS ...
+ParseOnly :== False
+import RWSDebug
+
+// +++ move to utilities?
+
+groupBy :: (a a -> Bool) [a] -> [[a]]
+groupBy eq []
+ = []
+groupBy eq [h : t]
+ = [[h : this] : groupBy eq other]
+ where
+ (this, other)
+ = span (eq h) t
+/*
+ident = { id_name = "id name", id_info = nilPtr }
+Start
+ = is_record_update [{nu_selectors=[PS_Record ident No],nu_update_expr=PE_Empty}]
+
+is_record_update :: [NestedUpdate] -> Bool
+is_record_update [{nu_selectors=[(PS_Record _ _) : _]}]
+ = True ->> "is_record_update"
+is_record_update updates
+ = False ->> ("not is_record_update", updates)
+*/
+
+// ... RWS
+
+/*
+
+Parser for Clean 2.0
+
+Conventions:
+
+- Parsing funtions with a name of the form try.. can fail without generating an error.
+ The parser will try an other alternative.
+- Parsing functions with a name of the form want.. should succeed. If these functions
+ fail an error message is generated.
+- Functions with names containing the character '_' are local functions.
+- All functions should consume the tokens taken form the state or given as argument,
+ or put these tokens back themselves.
+
+*/
+
+:: *ParseErrorAdmin =
+ { pea_file :: !*File
+ , pea_ok :: !Bool
+ }
+
+:: *ParseState =
+ { ps_scanState :: !ScanState
+ , ps_error :: !*ParseErrorAdmin
+ , ps_skipping :: !Bool
+ , ps_hash_table :: !*HashTable
+ , ps_pre_def_symbols :: !*PredefinedSymbols
+ }
+
+appScanState :: (ScanState -> ScanState) !ParseState -> ParseState
+appScanState f pState=:{ps_scanState}
+ # ps_scanState = f ps_scanState
+ = { pState & ps_scanState = ps_scanState }
+
+accScanState :: (ScanState -> (.t,ScanState)) !ParseState -> (.t,ParseState)
+accScanState f pState=:{ps_scanState}
+ # ( x, ps_scanState) = f ps_scanState
+ = ( x, {pState & ps_scanState = ps_scanState })
+
+makeStringTypeSymbol pState=:{ps_pre_def_symbols}
+ #! string_id = ps_pre_def_symbols.[PD_StringType]
+ = (MakeNewTypeSymbIdent string_id.pds_ident 0, pState)
+
+makeListTypeSymbol arity pState=:{ps_pre_def_symbols}
+ #! list_id = ps_pre_def_symbols.[PD_ListType]
+ = (MakeNewTypeSymbIdent list_id.pds_ident arity, pState)
+
+makeLazyArraySymbol arity pState=:{ps_pre_def_symbols}
+ #! lazy_array_id = ps_pre_def_symbols.[PD_LazyArrayType]
+ = (MakeNewTypeSymbIdent lazy_array_id.pds_ident arity, pState)
+
+makeStrictArraySymbol arity pState=:{ps_pre_def_symbols}
+ #! strict_array_id = ps_pre_def_symbols.[PD_StrictArrayType]
+ = (MakeNewTypeSymbIdent strict_array_id.pds_ident arity, pState)
+
+makeUnboxedArraySymbol arity pState=:{ps_pre_def_symbols}
+ #! unboxed_array_id = ps_pre_def_symbols.[PD_UnboxedArrayType]
+ = (MakeNewTypeSymbIdent unboxed_array_id.pds_ident arity, pState)
+
+makeTupleTypeSymbol form_arity act_arity pState=:{ps_pre_def_symbols}
+ #! tuple_id = ps_pre_def_symbols.[GetTupleTypeIndex form_arity]
+ = (MakeNewTypeSymbIdent tuple_id.pds_ident act_arity, pState)
+
+makeNilExpression pState=:{ps_pre_def_symbols}
+ #! nil_id = ps_pre_def_symbols.[PD_NilSymbol]
+ = (PE_List [PE_Ident nil_id.pds_ident], pState)
+
+makeConsExpression a1 a2 pState=:{ps_pre_def_symbols}
+ #! cons_id = ps_pre_def_symbols.[PD_ConsSymbol]
+ = (PE_List [PE_Ident cons_id.pds_ident, a1, a2], pState)
+
+class try a :: !Token !*ParseState -> (!Optional a, !*ParseState)
+class want a :: !*ParseState -> (!a, !*ParseState)
+
+stringToIdent :: !String !IdentClass !*ParseState -> (!Ident, !*ParseState)
+stringToIdent ident ident_class pState=:{ps_hash_table}
+ # (ident, ps_hash_table) = putIdentInHashTable ident ident_class ps_hash_table
+ = (ident, { pState & ps_hash_table = ps_hash_table } )
+
+internalIdent :: !String !*ParseState -> (!Ident, !*ParseState)
+internalIdent prefix pState
+ # ({fp_line,fp_col},pState=:{ps_hash_table}) = getPosition pState
+ case_string = prefix +++ toString fp_line +++ "_" +++ toString fp_col
+ (case_ident, ps_hash_table) = putIdentInHashTable case_string IC_Expression ps_hash_table
+ = (case_ident, { pState & ps_hash_table = ps_hash_table } )
+
+erroneousIdent = { id_name = "", id_info = nilPtr }
+
+/*
+ Some general overloaded parsing routines
+*/
+
+wantSequence :: !Token !Context !*ParseState -> (!.[a],!*ParseState) | want a
+wantSequence separator context pState
+ # (first, pState) = want pState
+ (token, pState) = nextToken context pState
+ | separator == token
+ # (rest, pState) = wantSequence separator context pState
+ = ([first : rest], pState)
+ // otherwise // separator <> token
+ = ([first], tokenBack pState)
+/*
+optionalSequence start_token separator context pState
+ # (token, pState) = nextToken context pState
+ | token == start_token
+ = wantSequence separator context pState
+ = ([], tokenBack pState)
+*/
+parseList try_fun pState :== parse_list pState // try_fun *
+//parseList try_fun pState = parse_list pState
+ where
+ // parse_list :: !*ParseState -> (tree, *ParseState)
+ parse_list pState
+ # (succ, tree, pState) = try_fun pState
+ | succ
+ # (trees, pState) = parse_list pState
+ = ([tree : trees], pState)
+ = ([], pState)
+
+//wantSepList msg sep_token context try_fun pState = want_list msg pState
+wantSepList msg sep_token context try_fun pState :== want_list msg pState // try_fun (sep_token tryfun)*
+ where
+ want_list msg pState
+ # (succ, tree, pState) = try_fun pState
+ | succ
+ # (token, pState) = nextToken context pState
+ | token == sep_token
+ # (trees, pState) = optSepList sep_token context try_fun pState
+ = ([tree : trees], pState)
+ // otherwise // token <> sep_token
+ = ([tree], tokenBack pState)
+ # (token, pState) = nextToken GeneralContext pState
+ = ([tree], parseError "wantList" (Yes token) msg pState)
+
+//optSepList sep_token context try_fun pState = want_list msg pState
+optSepList sep_token context try_fun pState :== want_list pState // [ try_fun (sep_token tryfun)* ]
+ where
+ want_list pState
+ # (succ, tree, pState) = try_fun pState
+ | succ
+ # (token, pState) = nextToken context pState
+ | token == sep_token
+ # (trees, pState) = want_list pState
+ = ([tree : trees], pState)
+ // otherwise // token <> sep_token
+ = ([tree], tokenBack pState)
+ = ([], pState)
+
+//wantList msg try_fun pState = want_list msg pState
+wantList msg try_fun pState :== want_list msg pState // try_fun +
+ where
+ want_list msg pState
+ # (succ, tree, pState) = try_fun pState
+ | succ
+ # (trees, pState) = parseList try_fun pState
+ = ([tree : trees], pState)
+ # (token, pState) = nextToken GeneralContext pState
+ = ([tree], parseError "wantList" (Yes token) msg pState)
+/*
+instance want (a,b) | want a & want b
+where
+ want pState
+ # (x, pState) = want pState
+ (y, pState) = want pState
+ = ((x,y), pState)
+*/
+wantIdents :: !Context !IdentClass !ParseState -> (![Ident], !ParseState)
+wantIdents context ident_class pState
+ # (first_name, pState) = want pState
+ (first_ident, pState) = stringToIdent first_name ident_class pState
+ (token, pState) = nextToken context pState
+ | token == CommaToken
+ # (rest, pState) = wantIdents context ident_class pState
+ = ([first_ident : rest], pState)
+ = ([first_ident], tokenBack pState)
+
+optionalPriority :: !Bool !Token !ParseState -> (Priority, !ParseState)
+optionalPriority isinfix (PriorityToken prio) pState
+ = (prio, pState)
+optionalPriority isinfix token pState
+ | isinfix
+ = (DummyPriority, tokenBack pState)
+ = (NoPrio, tokenBack pState)
+
+/*
+ Modules
+*/
+
+:: ParseContext :== Int
+
+cICLContext :== 1
+cGlobalContext :== 2
+cDCLContext :== 0
+cLocalContext :== 1
+
+SetGlobalContext iclmodule
+ | iclmodule
+ = cICLContext bitor cGlobalContext
+ = cDCLContext bitor cGlobalContext
+
+SetLocalContext context :== context bitand (bitnot cGlobalContext)
+
+isLocalContext context :== context bitand cGlobalContext == 0
+isGlobalContext context :== not (isLocalContext context)
+
+isDclContext context :== context bitand cICLContext == 0
+isIclContext context :== not (isDclContext context)
+
+cWantIclFile :== True
+cWantDclFile :== False
+
+wantModule :: !Bool !Ident !*HashTable !*File !SearchPaths !*PredefinedSymbols !*Files
+ -> (!Bool, !ParsedModule, !*HashTable, !*File, !*PredefinedSymbols, !*Files)
+wantModule iclmodule file_id=:{id_name} hash_table error searchPaths pre_def_symbols files
+ # file_name = if iclmodule (id_name +++ ".icl") (id_name +++ ".dcl")
+ = case openScanner file_name searchPaths files of
+ (Yes scanState, files) -> initModule file_name scanState pre_def_symbols files
+ (No , files) -> let mod = { mod_name = file_id, mod_type = MK_None, mod_imports = [], mod_imported_objects = [], mod_defs = [] } in
+ (False, mod, hash_table, error <<< "Could not open: " <<< file_name, pre_def_symbols, files)
+where
+ initModule :: String ScanState !*PredefinedSymbols *Files -> (!Bool, !ParsedModule, !*HashTable, !*File, !*PredefinedSymbols, !*Files)
+ initModule file_name scanState pre_def_symbols files
+ # (succ, mod_type, mod_name, scanState) = try_module_header iclmodule scanState
+ | succ
+ # pState = { ps_scanState = scanState
+ , ps_error = { pea_file = error, pea_ok = True }
+ , ps_skipping = False
+ , ps_hash_table = hash_table
+ , ps_pre_def_symbols = pre_def_symbols
+ }
+ pState = verify_name mod_name id_name file_name pState
+ (mod_ident, pState) = stringToIdent mod_name IC_Module pState
+ pState = check_layout_rule pState
+ (defs, pState) = want_definitions (SetGlobalContext iclmodule) pState
+ {ps_scanState,ps_hash_table,ps_error,ps_pre_def_symbols}
+ = pState
+// RWS ...
+ defs = if (ParseOnly && id_name <> "StdOverloaded" && id_name <> "StdArray" && id_name <> "StdEnum" && id_name <> "StdBool" && id_name <> "StdDynamics")
+ [PD_Import imports \\ PD_Import imports <- defs]
+ defs
+// ... RWS
+ mod = { mod_name = mod_ident, mod_type = mod_type, mod_imports = [], mod_imported_objects = [], mod_defs = defs }
+ = ( ps_error.pea_ok
+ , mod, ps_hash_table
+ , ps_error.pea_file
+ , ps_pre_def_symbols
+ , closeScanner ps_scanState files
+ )
+ // otherwise // ~ succ
+ # mod = { mod_name = file_id, mod_type = mod_type, mod_imports = [], mod_imported_objects = [], mod_defs = [] }
+ = (False, mod, hash_table, error <<< '[' <<< file_id <<< "]: " <<< "incorrect module header", pre_def_symbols, files)
+
+ try_module_header :: !Bool !ScanState -> (!Bool,!ModuleKind,!String,!ScanState)
+ try_module_header is_icl_mod scanState
+ # (token, scanState) = nextToken GeneralContext scanState
+ | is_icl_mod
+ | token == ModuleToken
+ # (token, scanState) = nextToken GeneralContext scanState
+ = try_module_name token MK_Main scanState
+ | token == ImpModuleToken
+ = try_module_token MK_Module scanState
+ | token == SysModuleToken
+ = try_module_token MK_System scanState
+ = (False, MK_None, "", tokenBack scanState)
+ | token == DefModuleToken
+ = try_module_token MK_Module scanState
+ | token == SysModuleToken
+ = try_module_token MK_System scanState
+ = (False, MK_None, "", tokenBack scanState)
+
+ try_module_token :: !ModuleKind !ScanState -> (!Bool,!ModuleKind!,!String,!ScanState)
+ try_module_token mod_type scanState
+ # (token, scanState) = nextToken GeneralContext scanState
+ | token == ModuleToken
+ # (token, scanState) = nextToken GeneralContext scanState
+ = try_module_name token mod_type scanState
+ = (False, mod_type, "", tokenBack scanState)
+
+ try_module_name (IdentToken name) mod_type scanState
+ = (True, mod_type, name, scanState) //-->> ("module",name)
+ try_module_name token mod_type scanState
+ = (False, mod_type, "", tokenBack scanState)
+
+ verify_name name id_name file_name pState=:{ps_error={pea_file}}
+ | name == id_name
+ = pState
+ # pea_file = pea_file <<< "Module name \"" <<< name <<< "\" does not match file name \"" <<< file_name <<< "\"\n"
+ = { pState & ps_error = { pea_file = pea_file, pea_ok = False }}
+
+ check_layout_rule pState
+ # (token, pState) = nextToken GeneralContext pState
+ use_layout = token <> SemicolonToken && token <> EndOfFileToken // '&& token <> EndOfFileToken' to handle end groups of empty modules
+ | use_layout = appScanState (setUseLayout use_layout) (tokenBack pState)
+ = appScanState (setUseLayout use_layout) pState
+
+ want_definitions :: !ParseContext !ParseState -> (![ParsedDefinition], !ParseState)
+ want_definitions context pState
+ = want_acc_definitions [] pState
+ where
+ want_acc_definitions :: ![ParsedDefinition] !ParseState -> (![ParsedDefinition], !ParseState)
+ want_acc_definitions acc pState
+ # (defs, pState) = wantDefinitions context pState
+ acc = acc ++ defs
+ pState = wantEndModule pState
+ (token, pState) = nextToken FunctionContext pState
+ | token == EndOfFileToken
+ = (acc, pState)
+ # pState = parseError "want definitions" (Yes token) "End of file" pState
+ pState = wantEndOfDefinition "definitions" pState
+ = want_acc_definitions acc pState
+/*
+ [Definition] on local and global level
+*/
+
+wantDefinitions :: !ParseContext !ParseState -> (![ParsedDefinition], !ParseState)
+wantDefinitions context pState
+ = parseList (tryDefinition context) pState
+
+DummyPriority :== Prio LeftAssoc 9
+
+cHasPriority :== True
+cHasNoPriority :== False
+
+tryDefinition :: !ParseContext !ParseState -> (!Bool, ParsedDefinition, !ParseState)
+tryDefinition context pState
+ # (token, pState) = nextToken GeneralContext pState
+ (fname, linenr, pState) = getFileAndLineNr pState
+ = try_definition context token (LinePos fname linenr) pState
+where
+ try_definition :: !ParseContext !Token !Position !ParseState -> (!Bool, ParsedDefinition, !ParseState)
+ try_definition context DoubleColonToken pos pState
+ # (def, pState) = wantTypeDef context pos pState
+ = (True, def, pState)
+ try_definition _ ImportToken pos pState
+// RWS ...
+ # (token, pState) = nextToken FunctionContext pState
+ | token == CodeToken && isIclContext context
+ # (importedObjects, pState) = wantCodeImports pState
+ = (True, PD_ImportedObjects importedObjects, pState)
+ # pState = tokenBack pState
+// ... RWS
+ # (imports, pState) = wantImports pState
+ = (True, PD_Import imports, pState)
+ try_definition _ FromToken pos pState
+ # (imp, pState) = wantFromImports pState
+ = (True, PD_Import [imp], pState) -->> imp
+/* try_definition _ ExportToken pos pState
+ # (exports, pState) = wantExportDef pState
+ = (True, PD_Export exports, pState)
+ try_definition _ ExportAllToken pos pState
+ = (True, PD_Export ExportAll, pState)
+*/ try_definition context ClassToken pos pState
+ # (classdef, pState) = wantClassDefinition context pos pState
+ = (True, classdef, pState)
+ try_definition context InstanceToken pos pState
+ # (instdef, pState) = wantInstanceDeclaration context pos pState
+ = (True, instdef, pState)
+ try_definition context token pos pState
+ | isLhsStartToken token
+ # (lhs, pState) = want_lhs_of_def token pState
+ (token, pState) = nextToken FunctionContext pState
+ (def, pState) = want_rhs_of_def context lhs token (determine_position lhs pos) pState //-->> token
+ = (True, def, pState) -->> def
+ with
+ determine_position (Yes (name, _), _) (LinePos f l) = FunPos f l name.id_name
+ determine_position lhs pos = pos
+ = (False, abort "no def(1)", tokenBack pState)
+
+ want_lhs_of_def :: !Token !ParseState -> (!(Optional (Ident, Bool), ![ParsedExpr]), !ParseState)
+ want_lhs_of_def token pState
+ # (succ, fname, is_infix, pState) = try_function_symbol token pState
+ | succ
+ # (args, pState) = parseList trySimpleLhsExpression pState
+ = ((Yes (fname, is_infix), args), pState)
+ # (_, exp, pState) = trySimpleLhsExpression pState
+ = ((No, [exp]), pState)
+ where
+ try_function_symbol :: !Token !ParseState -> (!Bool, Ident, !Bool, !ParseState) // (Success, Ident, Infix, ParseState)
+ try_function_symbol (IdentToken name) pState
+ # (id, pState) = stringToIdent name IC_Expression pState
+ = (True, id, False, pState)
+ try_function_symbol OpenToken pState
+ # (token, pState) = nextToken FunctionContext pState
+ = case token of
+ (IdentToken name)
+ # (token, pState) = nextToken FunctionContext pState
+ | CloseToken == token
+ # (id, pState) = stringToIdent name IC_Expression pState
+ -> (True, id, True, pState)
+ -> (False, abort "no name", False, tokenBack (tokenBack (tokenBack pState)))
+ _
+ -> (False, abort "no name", False, tokenBack (tokenBack pState))
+ try_function_symbol token pState
+ = (False, abort "name", False, tokenBack pState)
+
+ want_rhs_of_def :: !ParseContext !(Optional (Ident, Bool), [ParsedExpr]) !Token !Position !ParseState -> (ParsedDefinition, !ParseState)
+ want_rhs_of_def context (opt_name, args) DoubleColonToken pos pState
+ # (name, is_infix, pState) = check_name_and_fixity opt_name cHasNoPriority pState
+ (tspec, pState) = want pState // SymbolType
+ | isDclContext context
+ # (specials, pState) = optionalSpecials pState
+ = (PD_TypeSpec pos name (if is_infix DummyPriority NoPrio) (Yes tspec) specials, wantEndOfDefinition "type definition (1)" pState)
+ = (PD_TypeSpec pos name (if is_infix DummyPriority NoPrio) (Yes tspec) SP_None, wantEndOfDefinition "type definition (2)" pState)
+ want_rhs_of_def context (opt_name, args) (PriorityToken prio) pos pState
+ # (name, _, pState) = check_name_and_fixity opt_name cHasPriority pState
+ (token, pState) = nextToken TypeContext pState
+ | token == DoubleColonToken
+ # (tspec, pState) = want pState
+ | isDclContext context
+ # (specials, pState) = optionalSpecials pState
+ = (PD_TypeSpec pos name prio (Yes tspec) specials, wantEndOfDefinition "type definition (3)" pState)
+ = (PD_TypeSpec pos name prio (Yes tspec) SP_None, wantEndOfDefinition "type definition (4)" pState)
+ = (PD_TypeSpec pos name prio No SP_None, wantEndOfDefinition "type defenition (5)" (tokenBack pState))
+ want_rhs_of_def context (No, args) token pos pState
+ # pState = want_node_def_token pState token
+ (rhs, pState) = wantRhs isEqualToken (tokenBack pState)
+ | isGlobalContext context
+ = (PD_NodeDef pos (combine_args args) rhs, parseError "RHS" No "<global definition>" pState)
+ = (PD_NodeDef pos (combine_args args) rhs, pState)
+ where
+ want_node_def_token s EqualToken = s
+ want_node_def_token s DefinesColonToken = replaceToken EqualToken s
+ want_node_def_token s token = parseError "RHS" (Yes token) "defines token (= or =:)" s
+
+ combine_args [arg] = arg
+ combine_args args = PE_List args
+ want_rhs_of_def context (Yes (name, False), []) token pos pState
+ | isIclContext context && isLocalContext context && (token == DefinesColonToken || token == EqualToken)
+ # (rhs, pState) = wantRhs (\_ -> True) (tokenBack pState)
+ = (PD_NodeDef pos (PE_Ident name) rhs, pState)
+ want_rhs_of_def context (Yes (name, is_infix), args) token pos pState
+ # (fun_kind, code_allowed, pState) = token_to_fun_kind pState token
+ (token, pState) = nextToken FunctionContext pState
+ | isIclContext context && token == CodeToken
+ # (rhs, pState) = wantCodeRhs pState
+ | code_allowed
+ = (PD_Function pos name is_infix args rhs fun_kind, pState)
+ // otherwise // ~ code_allowed
+ = (PD_Function pos name is_infix args rhs fun_kind, parseError "rhs of def" No "no code" pState)
+ # pState = tokenBack (tokenBack pState)
+ (rhs, pState) = wantRhs isRhsStartToken pState
+ = case fun_kind of
+ FK_Function | isDclContext context
+ -> (PD_Function pos name is_infix args rhs fun_kind, parseError "RHS" No "<type specification>" pState)
+ FK_Caf | ~(isEmpty args)
+ -> (PD_Function pos name is_infix [] rhs fun_kind, parseError "CAF" No "No arguments for a CAF" pState)
+ _ -> (PD_Function pos name is_infix args rhs fun_kind, pState)
+ where
+ token_to_fun_kind s BarToken = (FK_Function, False, s)
+ token_to_fun_kind s (SeqLetToken _) = (FK_Function, False, s)
+ token_to_fun_kind s EqualToken = (FK_Function, True, s)
+ token_to_fun_kind s ColonDefinesToken = (FK_Macro, False, s)
+ token_to_fun_kind s DoubleArrowToken = (FK_Function, True, s)
+ token_to_fun_kind s DefinesColonToken = (FK_Caf, False, s)
+ token_to_fun_kind s token = (FK_Unknown, False, parseError "RHS" (Yes token) "defines token (=, => or =:) or argument" s)
+
+ check_name_and_fixity No hasprio pState
+ = (erroneousIdent, False, parseError "Definition" No "identifier" pState)
+ check_name_and_fixity (Yes (name,is_infix)) hasprio pState
+ | not is_infix && hasprio // XXXXXXX
+ = (name, False, parseError "Definition" No "Infix operator should be inside parentheses; no infix" pState)
+ = (name, is_infix, pState)
+
+isEqualToken :: !Token -> Bool
+isEqualToken EqualToken = True
+isEqualToken _ = False
+
+isRhsStartToken :: !Token -> Bool
+isRhsStartToken EqualToken = True
+isRhsStartToken ColonDefinesToken = True
+isRhsStartToken DefinesColonToken = True
+isRhsStartToken _ = False
+
+optionalSpecials :: !ParseState -> (!Specials, !ParseState)
+optionalSpecials pState
+ # (token, pState) = nextToken TypeContext pState
+ | token == SpecialToken
+ # (specials, pState) = wantList "<special statement>" try_substitutions pState
+ = (SP_ParsedSubstitutions specials, wantEndGroup "specials" pState)
+ // otherwise // token <> SpecialToken
+ = (SP_None, tokenBack pState)
+where
+ try_substitutions pState
+ # (succ, type_var, pState) = tryTypeVar pState
+ | succ
+ # (subst, pState) = want_rest_substitutions type_var pState
+ = (True, subst, wantEndOfDefinition "substitution" pState)
+ = (False, [], pState)
+
+ want_rest_substitutions type_var pState
+ # pState = wantToken GeneralContext "specials" EqualToken pState
+ (type, pState) = want pState
+ (token, pState) = nextToken GeneralContext pState
+ | token == CommaToken
+ # (next_type_var, pState) = want pState
+ (substs, pState) = want_rest_substitutions next_type_var pState
+ = ([{ bind_src = type, bind_dst = type_var } : substs], pState)
+ = ([{ bind_src = type, bind_dst = type_var }], tokenBack pState)
+/*
+ For parsing right-hand sides of functions only
+*/
+
+wantCodeRhs :: !ParseState -> (Rhs, !ParseState)
+wantCodeRhs pState
+ # (expr, pState) = want_code_expr pState
+ = ( { rhs_alts = UnGuardedExpr
+ { ewl_nodes = []
+ , ewl_locals = LocalParsedDefs []
+ , ewl_expr = expr
+ }
+ , rhs_locals = LocalParsedDefs []
+ }
+ , wantEndOfDefinition "code rhs" pState
+ )
+where
+ want_code_expr :: !ParseState -> (!ParsedExpr, !ParseState)
+ want_code_expr pState
+ # (token, pState) = nextToken CodeContext pState
+ = case token of
+ OpenToken
+ # (input, pState) = want_bindings [] True pState
+ pState = wantToken CodeContext "input bindings of code block" CloseToken pState
+ pState = wantToken CodeContext "output bindings of code block" OpenToken pState
+ (out, pState) = want_bindings [] False pState
+ pState = wantToken CodeContext "output bindings of code block" CloseToken pState
+ (token, pState) = nextToken CodeContext pState
+ -> case token of
+ CodeBlockToken the_code
+ -> (PE_Any_Code input out the_code, pState)
+ _ -> (PE_Any_Code input out [] , parseError "code rhs (any code)" (Yes token) "code block" pState)
+ InlineToken
+ # (token, pState) = nextToken CodeContext pState
+ -> case token of
+ CodeBlockToken the_code
+ -> (PE_ABC_Code the_code True, pState)
+ token
+ -> (PE_ABC_Code [] True, parseError "inline code" (Yes token) "code block" pState)
+ CodeBlockToken the_code
+ -> (PE_ABC_Code the_code False, pState)
+ token
+ -> (PE_Empty, parseError "code rhs" (Yes token) "<code rhs>" pState)
+
+ want_bindings :: !(CodeBinding Ident) !Bool !ParseState -> (!CodeBinding Ident, !ParseState)
+ want_bindings acc mayBeEmpty pState
+ # (token, pState) = nextToken CodeContext pState
+ = case token of
+ IdentToken name
+ # (token, pState) = nextToken CodeContext pState
+ | token == EqualToken || token == DefinesColonToken
+ # (token, pState) = nextToken CodeContext pState
+ -> case token of
+ IdentToken value
+ # (ident, pState) = stringToIdent name IC_Expression pState
+ acc = [{ bind_dst = ident, bind_src = value }: acc]
+ (token, pState) = nextToken CodeContext pState
+ | token == CommaToken
+ -> want_bindings acc mayBeEmpty pState
+ // token <> CommaToken
+ -> (reverse acc, tokenBack pState)
+ token
+ -> (acc, parseError "bindings in code block" (Yes token) "value" pState)
+ // token <> EqualToken && token <> DefinesColonToken
+ -> (acc, parseError "bindings in code block" (Yes token) "= or =:" pState)
+ CloseToken
+ | mayBeEmpty
+ -> (acc, tokenBack pState) // to handle empty input bindings
+ -> (acc, parseError "code bindings" (Yes token) "output bindings" pState)
+ token
+ -> (acc, parseError "bindings in code block" (Yes token) "identifier" pState)
+/*
+ For parsing right-hand sides of functions and case expressions
+*/
+
+
+/* Syntax:
+ FunctionAltDefRhs = FunctionBody // Rhs
+ [ LocalFunctionAltDefs ]
+ FunctionBody = exprWithLocals // OptGuardedAlts : GuardedAlts
+ | GuardedAlts // : UnGuardedExpr
+ GuardedAlts = { [ LetBefore ] '|' [ StrictLet ] Guard FunctionBody }+ [ ExprWithLocals ]
+ ExprWithLocals = [ LetBefore ] sep RootExpression endOfDefinition [ LocalFunctionDefs ]
+*/
+
+wantRhs :: !(!Token -> Bool) !ParseState -> (Rhs, !ParseState) // FunctionAltDefRhs
+wantRhs separator pState
+ # (alts, pState) = want_LetsFunctionBody separator pState
+ (locals, pState) = optionalLocals WhereToken pState
+ = ({ rhs_alts = alts, rhs_locals = locals}, pState)
+where
+ want_LetsFunctionBody :: !(!Token -> Bool) !ParseState -> (!OptGuardedAlts, !ParseState)
+ want_LetsFunctionBody sep pState
+ # (token, pState) = nextToken FunctionContext pState
+ (nodeDefs, token, pState) = want_LetBefores token pState
+ = want_FunctionBody token nodeDefs [] sep pState
+
+ want_FunctionBody :: !Token ![NodeDefWithLocals] ![GuardedExpr] !(Token -> Bool) !ParseState -> (!OptGuardedAlts, !ParseState)
+ want_FunctionBody BarToken nodeDefs alts sep pState
+// # (lets, pState) = want_StrictLet pState // removed from 2.0
+ # (token, pState) = nextToken FunctionContext pState
+ | token == OtherwiseToken
+ # (token, pState) = nextToken FunctionContext pState
+ (nodeDefs2, token, pState) = want_LetBefores token pState
+ = case token of
+ BarToken
+ # pState = parseError "RHS: default alternative" No "root expression instead of guarded expression" pState
+ -> root_expression token (nodeDefs ++ nodeDefs2) (reverse alts) sep pState
+ _ -> root_expression token (nodeDefs ++ nodeDefs2) (reverse alts) sep pState
+ | token == LetToken True
+ # pState = parseError "RHS" No "No 'let!' in this version of Clean" pState
+ = root_expression token nodeDefs (reverse alts) sep pState
+ # (guard, pState) = wantRhsExpressionT token pState
+ (token, pState) = nextToken FunctionContext pState
+ (nodeDefs2, token, pState) = want_LetBefores token pState
+ | token == BarToken // nested guard
+ # (position, pState) = getPosition pState
+ offside = position.fp_col
+ (expr, pState) = want_FunctionBody token nodeDefs2 [] sep pState
+ pState = wantEndNestedGuard (default_found expr) offside pState
+ alt = { alt_nodes = nodeDefs, alt_guard = guard, alt_expr = expr }
+ (token, pState) = nextToken FunctionContext pState
+ (nodeDefs, token, pState) = want_LetBefores token pState
+ = want_FunctionBody token nodeDefs [alt:alts] sep pState
+ // otherwise
+ # (expr, pState) = root_expression token nodeDefs2 [] sep pState
+ alt = { alt_nodes = nodeDefs, alt_guard = guard, alt_expr = expr }
+ (token, pState) = nextToken FunctionContext pState
+ (nodeDefs, token, pState) = want_LetBefores token pState
+ = want_FunctionBody token nodeDefs [alt:alts] sep pState
+ want_FunctionBody token nodeDefs alts sep pState
+ = root_expression token nodeDefs (reverse alts) sep pState
+
+ root_expression :: !Token ![NodeDefWithLocals] ![GuardedExpr] !(Token -> Bool) !ParseState -> (!OptGuardedAlts, !ParseState)
+ root_expression token nodeDefs [] sep pState
+ # (expr,pState) = want_OptExprWithLocals token nodeDefs sep pState
+ = case expr of
+ Yes expr -> ( UnGuardedExpr expr, pState)
+ No -> ( UnGuardedExpr {ewl_nodes = [], ewl_expr = PE_Empty, ewl_locals = LocalParsedDefs []}
+ , parseError "RHS: root expression" (Yes token) "= <ExprWithLocals>" pState
+ )
+ root_expression token nodeDefs alts sep pState
+ # (expr,pState) = want_OptExprWithLocals token nodeDefs sep pState
+ = (GuardedAlts alts expr, pState)
+
+ default_found (GuardedAlts _ No) = False
+ default_found _ = True
+
+ want_OptExprWithLocals :: !Token ![NodeDefWithLocals] !(Token -> Bool) !ParseState -> (!Optional !ExprWithLocalDefs, !ParseState)
+ want_OptExprWithLocals DoubleArrowToken nodeDefs sep pState
+ = want_OptExprWithLocals EqualToken nodeDefs sep (replaceToken EqualToken pState)
+ want_OptExprWithLocals token nodeDefs sep pState
+ | sep token
+ # (expr, pState) = wantExpression cIsNotAPattern pState
+ pState = wantEndRootExpression pState
+ (locals,pState) = optionalLocals WithToken pState
+ = ( Yes { ewl_nodes = nodeDefs
+ , ewl_expr = expr
+ , ewl_locals = locals
+ }
+ , pState
+ )
+ = (No, tokenBack pState)
+
+/* want_StrictLet :: !ParseState -> ([NodeDefWithLocals] , !ParseState) // Removed from the language !?
+ want_StrictLet pState
+ # (token, pState) = nextToken FunctionContext pState
+ | token == LetToken True
+ # (let_defs, pState) = wantList "<sequential node defs>" (try_LetDef True) pState
+ pState = wantToken FunctionContext "strict let" InToken pState
+ = (let_defs, pState)
+ = ([], tokenBack pState)
+*/
+ want_LetBefores :: !Token !ParseState -> (![NodeDefWithLocals], !Token, !ParseState)
+ want_LetBefores (SeqLetToken strict) pState
+ # (let_defs, pState) = wantList "<sequential node defs>" (try_LetDef strict) pState
+ (token, pState) = nextToken FunctionContext pState
+ (token, pState) = opt_End_Group token pState
+ (more_let_defs, token, pState) = want_LetBefores token pState
+ = (let_defs ++ more_let_defs, token, pState)
+ where
+ opt_End_Group token pState
+ # (ss_useLayout, pState) = accScanState UseLayout pState
+ | ss_useLayout
+ | token == EndGroupToken
+ = nextToken FunctionContext pState
+ // otherwise // token <> EndGroupToken
+ = (ErrorToken "End group missing in let befores", parseError "RHS: Let befores" (Yes token) "Generated End Group (due to layout)" pState)
+ | otherwise // not ss_useLayout
+ = (token, pState)
+ want_LetBefores token pState
+ = ([], token, pState)
+
+ try_LetDef :: !Bool !ParseState -> (!Bool, NodeDefWithLocals, !ParseState)
+ try_LetDef strict pState
+ # (succ, lhs_exp, pState) = trySimpleLhsExpression pState
+ | succ
+ # pState = wantToken FunctionContext "let definition" EqualToken pState
+ (rhs_exp, pState) = wantExpression cIsNotAPattern pState
+ pState = wantEndRootExpression pState -->> ("#",lhs_exp,"=",rhs_exp)
+ (locals , pState) = optionalLocals WithToken pState
+ = ( True
+ , { ndwl_strict = strict
+ , ndwl_def = { bind_dst = lhs_exp
+ , bind_src = rhs_exp
+ }
+ , ndwl_locals = locals
+ }
+ , pState
+ )
+ // otherwise // ~ succ
+ = (False, abort "no definition", pState)
+
+optionalLocals :: !Token !ParseState -> (!LocalDefs, !ParseState)
+optionalLocals dem_token pState
+ # (off_token, pState) = nextToken FunctionContext pState
+ | dem_token == off_token
+ = wantLocals pState
+ # (ss_useLayout, pState) = accScanState UseLayout pState
+ | off_token == CurlyOpenToken && ~ ss_useLayout
+ = wantLocals (tokenBack pState)
+ // otherwise
+ = (LocalParsedDefs [], tokenBack pState)
+
+wantLocals :: !ParseState -> (LocalDefs, !ParseState)
+wantLocals pState
+ # pState = wantBeginGroup "local definitions" pState
+ (defs, pState) = wantDefinitions cLocalContext pState
+ = (LocalParsedDefs defs, wantEndLocals pState)
+
+/*
+ imports and exports
+*/
+
+wantImports :: !ParseState -> (![ParsedImport], !ParseState)
+wantImports pState
+ # (names, pState) = wantIdents FunctionContext IC_Module pState
+ (file_name, line_nr, pState) = getFileAndLineNr pState
+ pState = wantEndOfDefinition "imports" pState
+ = (map (\name -> { import_module = name, import_symbols = [], import_file_position = (file_name, line_nr)}) names, pState)
+
+wantFromImports :: !ParseState -> (!ParsedImport, !ParseState)
+wantFromImports pState
+ # (mod_name, pState) = want pState
+ (mod_ident, pState) = stringToIdent mod_name IC_Module pState
+ pState = wantToken GeneralContext "from imports" ImportToken pState
+ (file_name, line_nr, pState) = getFileAndLineNr pState
+ (import_symbols, pState) = wantSequence CommaToken GeneralContext pState
+ pState = wantEndOfDefinition "from imports" pState
+ = ( { import_module = mod_ident, import_symbols = import_symbols, import_file_position = (file_name, line_nr) }, pState)
+
+// RWS ...
+instance want ImportedObject where
+ want pState
+ # (token, pState) = nextToken GeneralContext pState
+ | token == IdentToken "library"
+ # (token, pState) = nextToken GeneralContext pState
+ = want_import_string token cIsImportedLibrary pState
+ = want_import_string token cIsImportedObject pState
+ where
+ want_import_string :: Token Bool ParseState -> (ImportedObject, ParseState)
+ want_import_string (StringToken string) isLibrary pState
+ = ({io_is_library = isLibrary, io_name = string}, pState)
+ want_import_string token isLibrary pState
+ = ({io_is_library = isLibrary, io_name = ""}, parseError "import code declaration" (Yes token) "imported item" pState)
+
+wantCodeImports :: !ParseState -> (![ImportedObject], !ParseState)
+wantCodeImports pState
+ # pState = wantToken GeneralContext "import code declaration" FromToken pState
+ (importObjects, pState) = wantSequence CommaToken GeneralContext pState
+ = (importObjects, wantEndOfDefinition "import code declaration" pState)
+// ... RWS
+
+instance want ImportDeclaration
+where
+ want pState
+ # (token, pState) = nextToken GeneralContext pState
+ = case token of
+ DoubleColonToken
+ # (name, pState) = wantUpperCaseName "import type" pState
+ (type_id, pState) = stringToIdent name IC_Type pState
+ (ii_extended, token, pState) = optional_extension_with_next_token pState
+ | token == OpenToken
+ # (conses, pState) = want_names (wantUpperCaseName "import type (..)") IC_Expression CloseToken pState
+ -> (ID_Type { ii_ident = type_id, ii_extended = ii_extended } (Yes conses), pState)
+ | token == CurlyOpenToken
+ # (fields, pState) = want_names (wantLowerCaseName "import record fields") (IC_Field type_id) CurlyCloseToken pState
+ -> (ID_Record { ii_ident = type_id, ii_extended = ii_extended } (Yes fields), pState)
+ -> (ID_Type { ii_ident = type_id, ii_extended = ii_extended } No, tokenBack pState)
+ ClassToken
+ # (name, pState) = want pState
+ (class_id, pState) = stringToIdent name IC_Class pState
+ (ii_extended, token, pState) = optional_extension_with_next_token pState
+ | token == OpenToken
+ # (members, pState) = want_names want IC_Expression CloseToken pState
+ -> (ID_Class { ii_ident = class_id, ii_extended = ii_extended } (Yes members), pState)
+ -> (ID_Class { ii_ident = class_id, ii_extended = ii_extended } No, pState)
+ InstanceToken
+ # (class_name, pState) = want pState
+ (ii_extended, pState) = optional_extension pState
+ (types, pState) = wantList "instance types" tryBrackType pState
+ (class_id, pState) = stringToIdent class_name IC_Class pState
+ (inst_id, pState) = stringToIdent class_name (IC_Instance types) pState
+ (context, pState) = optionalContext pState
+ -> (ID_Instance { ii_ident = class_id, ii_extended = ii_extended } inst_id (types,context), pState)
+ IdentToken fun_name
+ # (fun_id, pState) = stringToIdent fun_name IC_Expression pState
+ (ii_extended, pState) = optional_extension pState
+ -> (ID_Function { ii_ident = fun_id, ii_extended = ii_extended }, pState)
+ token
+ # (fun_id, pState) = stringToIdent "dummy" IC_Expression pState
+ -> ( ID_Function { ii_ident = fun_id, ii_extended = False }
+ , parseError "from import" (Yes token) "imported item" pState
+ )
+ where
+ want_names want_fun ident_kind close_token pState
+ # (token, pState) = nextToken FunctionContext pState
+ | token == DotDotToken
+ = ([], wantToken FunctionContext "import declaration" close_token pState)
+ = want_list_of_names want_fun ident_kind close_token (tokenBack pState)
+
+ want_list_of_names want_fun ident_kind close_token pState
+ # (name, pState) = want_fun pState
+ (name_id, pState) = stringToIdent name ident_kind pState
+ (ii_extended, token, pState) = optional_extension_with_next_token pState
+ | token == CommaToken
+ # (names, pState) = want_list_of_names want_fun ident_kind close_token pState
+ = ([{ ii_ident = name_id, ii_extended = ii_extended } : names], pState)
+ | token == close_token
+ = ([{ ii_ident = name_id, ii_extended = ii_extended }], pState)
+ = ([{ ii_ident = name_id, ii_extended = ii_extended }], parseError "ImportDeclaration" (Yes token) ")" pState)
+
+ optional_extension pState
+ # (token, pState) = nextToken FunctionContext pState
+ | token == DotDotToken
+ = (True, pState)
+ = (False, tokenBack pState)
+
+ optional_extension_with_next_token pState
+ # (token, pState) = nextToken FunctionContext pState
+ | token == DotDotToken
+ # (token, pState) = nextToken FunctionContext pState
+ = (True, token, pState)
+ = (False, token, pState)
+
+/*
+wantExportDef :: !ParseState -> (!Export, !ParseState)
+wantExportDef pState
+ # (name, pState) = want pState
+ (ident, pState) = stringToIdent name IC_Class pState
+ (types, pState) = wantList "instance types" trySimpleType pState
+ pState = wantEndOfDefinition "exports" pState
+ = ({ export_class = ident, export_types = types}, pState)
+*/
+/*
+ Classes and instances
+*/
+
+cIsAGlobalContext :== True
+cIsNotAGlobalContext :== False
+
+cMightBeAClass :== True
+cIsNotAClass :== False
+
+
+wantClassDefinition :: !ParseContext !Position !ParseState -> (!ParsedDefinition, !ParseState)
+wantClassDefinition context pos pState
+ # (might_be_a_class, class_or_member_name, prio, pState) = want_class_or_member_name pState
+ (class_variables, pState) = wantList "class variable(s)" try_class_variable pState
+ (class_arity, class_args, class_cons_vars) = convert_class_variables class_variables 0 0
+ (contexts, pState) = optionalContext pState
+ (token, pState) = nextToken TypeContext pState
+ | token == DoubleColonToken
+ = want_overloaded_function pos class_or_member_name prio class_arity class_args class_cons_vars contexts pState
+ | might_be_a_class
+ | token == WhereToken
+ # (class_id, pState) = stringToIdent class_or_member_name IC_Class pState
+ (members, pState) = wantDefinitions context pState
+ class_def = { class_name = class_id, class_arity = class_arity, class_args = class_args,
+ class_context = contexts, class_pos = pos, class_members = {}, class_cons_vars = class_cons_vars,
+ class_dictionary = { ds_ident = { class_id & id_info = nilPtr }, ds_arity = 0, ds_index = NoIndex }}
+ = (PD_Class class_def members, wantEndGroup "class" pState)
+ | isEmpty contexts
+ = (PD_Erroneous, parseError "Class Definition" (Yes token) "<class definition>: contexts" pState)
+ // otherwise
+ # pState = tokenBack pState
+ (class_id, pState) = stringToIdent class_or_member_name IC_Class pState
+ class_def = { class_name = class_id, class_arity = class_arity, class_args = class_args,
+ class_context = contexts, class_pos = pos, class_members = {}, class_cons_vars = class_cons_vars,
+ class_dictionary = { ds_ident = { class_id & id_info = nilPtr }, ds_arity = 0, ds_index = NoIndex }}
+ pState = wantEndOfDefinition "class definition" pState
+ = (PD_Class class_def [], pState)
+ = (PD_Erroneous, parseError "Class Definition" (Yes token) "<class definition>" pState)
+ where
+ want_class_or_member_name pState
+ # (token, pState) = nextToken TypeContext pState
+ | token == OpenToken
+ # (member_name, pState) = want pState
+ pState = wantToken GeneralContext "class definition" CloseToken pState
+ (token, pState) = nextToken FunctionContext pState
+ (prio, pState) = optionalPriority cIsInfix token pState
+ = (cIsNotAClass, member_name, prio, pState)
+ # (class_name, pState) = want_name token pState
+ = (cMightBeAClass, class_name, NoPrio, pState)
+ where
+ want_name (IdentToken name) pState
+ = (name, pState)
+ want_name token pState
+ = ("", parseError "Class Definition" (Yes token) "<identifier>" pState)
+
+ want_overloaded_function pos member_name prio class_arity class_args class_cons_vars contexts pState
+ # (tspec, pState) = want pState
+ (member_id, pState) = stringToIdent member_name IC_Expression pState
+ (class_id, pState) = stringToIdent member_name IC_Class pState
+ member = PD_TypeSpec pos member_id prio (Yes tspec) SP_None
+ class_def = { class_name = class_id, class_arity = class_arity, class_args = class_args,
+ class_context = contexts, class_pos = pos, class_members = {}, class_cons_vars = class_cons_vars,
+ class_dictionary = { ds_ident = { class_id & id_info = nilPtr }, ds_arity = 0, ds_index = NoIndex }}
+ pState = wantEndOfDefinition "overloaded function" pState
+ = (PD_Class class_def [member], pState)
+
+ try_class_variable pState
+ # (token, pState) = nextToken TypeContext pState
+ | token == DotToken
+ # (type_var, pState) = wantTypeVar pState
+ = (True, (True, type_var), pState)
+ # (succ, type_var, pState) = tryTypeVarT token pState
+ = (succ, (False, type_var), pState)
+
+ convert_class_variables [] arg_nr cons_vars
+ = (arg_nr, [], cons_vars)
+ convert_class_variables [(annot, var) : class_vars] arg_nr cons_vars
+ # (arity, class_vars, cons_vars) = convert_class_variables class_vars (inc arg_nr) cons_vars
+ | annot
+ = (arity, [var : class_vars], cons_vars bitor (1 << arg_nr))
+ = (arity, [var : class_vars], cons_vars)
+
+// Sjaak ...
+wantInstanceDeclaration :: !ParseContext !Position !ParseState -> (!ParsedDefinition, !ParseState)
+wantInstanceDeclaration context pi_pos pState
+ # (class_name, pState) = want pState
+ (pi_class, pState) = stringToIdent class_name IC_Class pState
+ ((pi_types, pi_context), pState) = want_instance_type pState
+ (pi_ident, pState) = stringToIdent class_name (IC_Instance pi_types) pState
+ | isIclContext context
+ # pState = wantToken FunctionContext "instance declaration" WhereToken pState
+ pState = wantBeginGroup "instance" pState
+ (pi_members, pState) = wantDefinitions context pState
+ pState = wantEndLocals pState
+
+ = (PD_Instance {pi_class = pi_class, pi_ident = pi_ident, pi_types = pi_types, pi_context = pi_context,
+ pi_members = pi_members, pi_specials = SP_None, pi_pos = pi_pos }, pState)
+ // otherwise // ~ (isIclContext context)
+ # (token, pState) = nextToken TypeContext pState
+ | token == CommaToken
+ # (pi_types_and_contexts, pState) = want_instance_types pState
+ (idents, pState) = seqList [stringToIdent class_name (IC_Instance type) \\ (type,context) <- pi_types_and_contexts] pState
+ = (PD_Instances
+// [ { pi_class = pi_class, pi_ident = pi_ident, pi_types = type, pi_context = context // voor martin
+ [ { pi_class = pi_class, pi_ident = ident, pi_types = type, pi_context = context
+ , pi_members = [], pi_specials = SP_None, pi_pos = pi_pos}
+ \\ (type,context) <- [ (pi_types, pi_context) : pi_types_and_contexts ]
+ & ident <- [ pi_ident : idents ]
+ ]
+ , pState
+ )
+ // otherwise // token <> CommaToken
+ # (specials, pState) = optionalSpecials (tokenBack pState)
+ pState = wantEndOfDefinition "instance declaration" pState
+ = (PD_Instance {pi_class = pi_class, pi_ident = pi_ident, pi_types = pi_types, pi_context = pi_context,
+ pi_members = [], pi_specials = specials, pi_pos = pi_pos}, pState)
+// ... Sjaak
+where
+ want_instance_type pState
+ # (pi_types, pState) = wantList "instance types" tryBrackType pState
+// # (pi_types, pState) = wantList "instance types" tryType pState // This accepts 1.3 syntax, but is wrong for multiparameter classes
+ (pi_context, pState) = optionalContext pState
+ = ((pi_types, pi_context), pState)
+ want_instance_types pState
+ # (type_and_context, pState) = want_instance_type pState
+ (token, pState) = nextToken TypeContext pState
+ | token == CommaToken
+ # (types, pState) = want_instance_types pState
+ = ([type_and_context:types], pState)
+ // otherwise // token <> CommaToken
+ = ([type_and_context], pState)
+
+optionalContext :: !ParseState -> ([TypeContext],ParseState)
+optionalContext pState
+ # (token, pState) = nextToken TypeContext pState
+ | token == BarToken
+ = want_contexts pState
+ = ([], tokenBack pState)
+where
+ want_contexts pState
+ # (contexts, pState) = want_context pState
+ (token, pState) = nextToken TypeContext pState
+ | token == AndToken
+ # (more_contexts, pState) = want_contexts pState
+ = (contexts ++ more_contexts, pState)
+ = (contexts, tokenBack pState)
+
+ want_context pState
+ # (class_names, pState) = wantSequence CommaToken TypeContext pState
+ (types, pState) = wantList "type arguments" tryBrackType pState
+ = build_contexts class_names types (length types) pState
+ where
+ build_contexts [] types arity pState
+ = ([], pState)
+ build_contexts [class_name : class_names] types arity pState
+ # (contexts, pState) = build_contexts class_names types arity pState
+ (class_ident, pState) = stringToIdent class_name IC_Class pState
+ tc_class = { glob_object = MakeDefinedSymbol class_ident NoIndex (length types), glob_module = NoIndex }
+ = ([{ tc_class = tc_class, tc_types = types, tc_var = nilPtr } : contexts], pState)
+
+optionalCoercions :: !ParseState -> ([AttrInequality], ParseState)
+optionalCoercions pState
+ # (token, pState) = nextToken TypeContext pState
+ | token == CommaToken
+ # (token, pState) = nextToken TypeContext pState
+ | token == SquareOpenToken
+ # (inequals, pState) = want_inequalities pState
+ = (inequals, wantToken FunctionContext "coercions" SquareCloseToken pState)
+ = ([], parseError "Function type: coersions" (Yes token) "[" pState)
+ = ([], tokenBack pState)
+ where
+ want_inequalities pState
+ # (token, pState) = nextToken TypeContext pState
+ (_, inequals, pState) = want_attr_inequality token pState
+ (token, pState) = nextToken TypeContext pState
+ | token == CommaToken
+ # (more_inequals, pState) = want_inequalities pState
+ = (inequals ++ more_inequals, pState)
+ = (inequals, tokenBack pState)
+ want_attr_inequality (IdentToken var_name) pState
+ | isLowerCaseName var_name
+ # (off_ident, pState) = stringToIdent var_name IC_TypeAttr pState
+ (token, pState) = nextToken TypeContext pState
+ | token == LessThanOrEqualToken
+ # (var_name, pState) = wantLowerCaseName "attribute inequality" pState
+ (dem_ident, pState) = stringToIdent var_name IC_TypeAttr pState
+ ai_demanded = makeAttributeVar dem_ident
+ = (ai_demanded, [{ ai_demanded = ai_demanded, ai_offered = makeAttributeVar off_ident }], pState)
+ # (ai_demanded, inequals, pState) = want_attr_inequality token pState
+ = (ai_demanded, [{ ai_demanded = ai_demanded, ai_offered = makeAttributeVar off_ident } : inequals], pState)
+ want_attr_inequality token pState
+ # erroneous_attr_var = makeAttributeVar erroneousIdent
+ = ( erroneous_attr_var
+ , [{ ai_demanded = erroneous_attr_var, ai_offered = erroneous_attr_var }]
+ , parseError "Function type: optional coercions" (Yes token) "<attribute variable>" pState
+ )
+
+/*
+ Type definitions
+*/
+
+wantTypeVar :: ! ParseState -> (!TypeVar, !ParseState)
+wantTypeVar pState
+ # (succ, type_var, pState) = tryTypeVar pState
+ | succ
+ = (type_var, pState)
+ # (token, pState) = nextToken TypeContext pState
+ = (MakeTypeVar erroneousIdent, parseError "Type Variable" (Yes token) "type variable" pState)
+
+tryAttributedTypeVar :: !ParseState -> (!Bool, ATypeVar, !ParseState)
+tryAttributedTypeVar pState
+ # (token, pState) = nextToken TypeContext pState
+ | is_type_arg_token token
+ # (aOrA, annot, attr, pState) = optionalAnnotAndAttr (tokenBack pState)
+ (succ, type_var, pState) = tryTypeVar pState
+ | succ
+ = (True, { atv_attribute = attr, atv_annotation = annot, atv_variable = type_var }, pState)
+ | aOrA // annot <> AN_None || attr <> TA_None
+ # (token, pState) = nextToken TypeContext pState
+ = (False, no_type_var, parseError "Attributed type var" (Yes token) "type variabele after annotation or attribute" pState)
+ // otherwise
+ = (False, no_type_var, tokenBack pState)
+ // otherwise
+ = (False, no_type_var, tokenBack pState)
+where
+ is_type_arg_token (IdentToken t) = isLowerCaseName t
+ is_type_arg_token DotToken = True
+ is_type_arg_token AsteriskToken = True
+ is_type_arg_token t = False
+
+ no_type_var = abort "tryAttributedTypeVar: No type var"
+
+wantTypeDef :: !ParseContext !Position !ParseState -> (ParsedDefinition, !ParseState)
+wantTypeDef context pos pState
+ # (type_lhs, annot, pState) = want_type_lhs pos pState
+ (token, pState) = nextToken TypeContext pState
+ (def, pState) = want_type_rhs context type_lhs token annot pState
+ pState = wantEndOfDefinition "type definition (6)" pState
+ = (def, pState)
+where
+ want_type_lhs :: !Position !ParseState -> (!ParsedTypeDef, !Annotation, !ParseState)
+ want_type_lhs pos pState
+ # (_, annot, attr, pState) = optionalAnnotAndAttr pState
+ (name, pState) = wantConstructorName "Type name" pState
+ (ident, pState) = stringToIdent name IC_Type pState // -->> ("Type name",name)
+ (args, pState) = parseList tryAttributedTypeVar pState
+ (contexts, pState) = optionalContext pState
+ = (MakeTypeDef ident args (ConsList []) attr contexts pos, annot, pState)
+
+ want_type_rhs :: !ParseContext !ParsedTypeDef !Token !Annotation !ParseState -> (ParsedDefinition, !ParseState)
+ want_type_rhs context td=:{td_name,td_attribute} EqualToken annot pState
+ # name = td_name.id_name
+ pState = verify_annot_attr annot td_attribute name pState
+ (exi_vars, pState) = optionalQuantifiedVariables ExistentialQuantifier pState
+ (token, pState) = nextToken TypeContext pState
+ (token, pState) = case token of // Make the ':' optional for now to handle 1.3 files
+ ColonToken -> nextToken TypeContext (parseWarning "type RHS" ":-symbol after extential quantified variable should be removed" pState)
+ _ -> (token, pState)
+ = case token of
+ CurlyOpenToken
+ # (fields, pState) = wantFields td_name pState
+ pState = wantToken TypeContext "record type def" CurlyCloseToken pState
+ (rec_cons_ident, pState) = stringToIdent ("_" + name) IC_Expression pState
+ -> (PD_Type { td & td_rhs = SelectorList rec_cons_ident exi_vars fields }, pState)
+ ColonToken
+ | isEmpty exi_vars
+ -> (PD_Erroneous, parseError "Algebraic type" No "no colon, :," pState)
+ -> (PD_Erroneous, parseError "Algebraic type" No "in this version of Clean no colon, :, after quantified variables" pState)
+ _
+ # (condefs, pState) = want_constructor_list exi_vars token pState
+ td = { td & td_rhs = ConsList condefs }
+ | annot == AN_None
+ -> (PD_Type td, pState)
+ -> (PD_Type td, parseError "Algebraic type" No ("No lhs strictness annotation for the algebraic type "+name) pState)
+ want_type_rhs context td=:{td_attribute} ColonDefinesToken annot pState // type Macro
+ # name = td.td_name.id_name
+ pState = verify_annot_attr annot td_attribute name pState
+ (atype, pState) = want pState // Atype
+ td = {td & td_rhs = TypeSpec atype}
+ | annot == AN_None
+ = (PD_Type td, pState)
+ = (PD_Type td, parseError "Type synonym" No ("No lhs strictness annotation for the type synonym "+name) pState)
+ want_type_rhs context td=:{td_attribute} token annot pState
+ | isIclContext context
+ = (PD_Erroneous, parseError "type RHS" (Yes token) "type definition" pState)
+ | td_attribute == TA_Anonymous || td_attribute == TA_Unique || td_attribute == TA_None
+ # (td_attribute, properties) = determine_properties annot td_attribute
+ # td = { td & td_attribute = td_attribute, td_rhs = EmptyRhs properties}
+ = (PD_Type td, tokenBack pState)
+ # name = td.td_name.id_name
+ = (PD_Type { td & td_rhs = EmptyRhs cAllBitsClear}, parseError "abstract type" No ("type attribute "+toString td_attribute+" for abstract type "+name+" is not") (tokenBack pState))
+
+ verify_annot_attr :: !Annotation !TypeAttribute !String !ParseState -> ParseState
+ verify_annot_attr annot attr name pState
+ | annot <> AN_None
+ = parseError "type definition" No ("No annotation, "+toString annot+", in the lhs of type "+name) pState
+ | attr == TA_None || attr == TA_Unique
+ = pState
+ = parseError "ty[e definition" No ("No attribute, "+toString attr+", in the lhs of type "+name) pState
+
+ determine_properties :: !Annotation !TypeAttribute -> (!TypeAttribute, !BITVECT)
+ determine_properties annot attr
+ | annot == AN_Strict
+ | attr == TA_Anonymous
+ = (TA_None, cIsHyperStrict)
+ = (attr, cIsHyperStrict bitor cIsNonCoercible)
+ | attr == TA_Anonymous
+ = (TA_None, cAllBitsClear)
+ = (attr, cIsNonCoercible)
+
+ want_constructor_list :: ![ATypeVar] !Token !ParseState -> (.[ParsedConstructor],ParseState)
+ want_constructor_list exi_vars token pState
+ # (pc_cons_name, pc_cons_prio, pc_cons_pos, pState) = want_cons_name_and_prio token pState
+ (pc_arg_types, pState) = parseList tryBrackAType pState
+ cons = { pc_cons_name = pc_cons_name, pc_arg_types = pc_arg_types, pc_cons_arity = length pc_arg_types,
+ pc_cons_prio = pc_cons_prio, pc_exi_vars = exi_vars, pc_cons_pos = pc_cons_pos}
+ (token, pState) = nextToken TypeContext pState
+ | token == BarToken
+ # (exi_vars, pState) = optionalQuantifiedVariables ExistentialQuantifier pState
+ (token, pState) = nextToken TypeContext pState
+ (cons_list, pState) = want_constructor_list exi_vars token pState
+ = ([cons : cons_list], pState)
+ // otherwise
+ = ([cons], tokenBack pState)
+ where
+ want_cons_name_and_prio :: !Token !ParseState -> (Ident, !Priority, !Position, !ParseState)
+ want_cons_name_and_prio tok=:(IdentToken name) pState
+ # (ident, pState) = stringToIdent name IC_Expression pState
+ (fname, linenr, pState) = getFileAndLineNr pState
+ (token, pState) = nextToken TypeContext pState
+ (prio, pState) = optionalPriority cIsNotInfix token pState
+ | isLowerCaseName name
+ = (ident, prio, LinePos fname linenr, parseError "Algebraic type: constructor definitions" (Yes tok) "constructor name" pState)
+ = (ident, prio, LinePos fname linenr, pState)
+ want_cons_name_and_prio OpenToken pState
+ # (name, pState) = wantConstructorName "infix constructor" pState
+ (fname, linenr, pState) = getFileAndLineNr pState
+ (ident, pState) = stringToIdent name IC_Expression pState
+ (token, pState) = nextToken TypeContext (wantToken TypeContext "type: constructor and prio" CloseToken pState)
+ (prio, pState) = optionalPriority cIsInfix token pState
+ = (ident, prio, LinePos fname linenr, pState)
+ want_cons_name_and_prio token pState
+ = (erroneousIdent, NoPrio, NoPos, parseError "Algebraic type: constructor list" (Yes token) "constructor name" pState)
+
+makeAttributeVar name :== { av_name = name, av_info_ptr = nilPtr }
+
+optionalAnnotAndAttr :: !ParseState -> (!Bool, !Annotation, !TypeAttribute, !ParseState)
+optionalAnnotAndAttr pState
+ # (token, pState) = nextToken TypeContext pState
+ | token == ExclamationToken
+ # (token, pState) = nextToken TypeContext pState
+ (_ , attr, pState) = optional_attribute token pState
+ = (True, AN_Strict, attr, pState)
+ | otherwise // token <> ExclamationToken
+ # (succ, attr, pState) = optional_attribute token pState
+ = (succ, AN_None, attr, pState)
+where
+ optional_attribute :: !Token !ParseState -> (!Bool, !TypeAttribute, !ParseState)
+ optional_attribute DotToken pState = (True, TA_Anonymous, pState)
+ optional_attribute AsteriskToken pState = (True, TA_Unique, pState)
+ optional_attribute (IdentToken id) pState
+ | isLowerCaseName id
+ # (token, pState) = nextToken TypeContext pState
+ | ColonToken == token
+ # (ident, pState) = stringToIdent id IC_TypeAttr pState
+ = (True, TA_Var (makeAttributeVar ident), pState)
+ = (False, TA_None, tokenBack (tokenBack pState))
+ optional_attribute _ pState = (False, TA_None, tokenBack pState)
+
+
+cIsInfix :== True
+cIsNotInfix :== False
+
+wantFields :: !Ident !*ParseState -> (![ParsedSelector], !*ParseState)
+wantFields record_type pState
+ # (field, pState) = want_field record_type pState
+ (token, pState) = nextToken TypeContext pState
+ | token == CommaToken
+ # (fields, pState) = wantFields record_type pState
+ = ([field : fields], pState)
+ = ([field], tokenBack pState)
+ where
+ want_field :: !Ident !*ParseState -> *(!ParsedSelector, !*ParseState)
+ want_field record_type pState
+ # (field_name, pState) = wantLowerCaseName "record field" pState
+ (fname, linenr, pState) = getFileAndLineNr pState
+ (ps_field_name, pState) = stringToIdent field_name (IC_Field record_type) pState
+ (ps_selector_name, pState) = stringToIdent field_name IC_Selector pState
+ (ps_field_var, pState) = stringToIdent field_name IC_Expression pState
+ pState = wantToken TypeContext "record field" DoubleColonToken pState
+ (ps_field_type, pState) = want pState
+ = ({ ps_field_name = ps_field_name, ps_selector_name = ps_selector_name, ps_field_type = ps_field_type, ps_field_var = ps_field_var,
+ ps_field_pos = LinePos fname linenr}, pState)
+
+makeSymbolType args result context attr_env :==
+ { st_vars = [], st_args = args, st_arity = length args, st_result = result,
+ st_context = context, st_attr_env = attr_env, st_attr_vars = [] }
+
+instance want SymbolType
+where
+ want pState
+ # (types, pState) = parseList tryBrackAType pState
+ (token, pState) = nextToken TypeContext pState //-->> ("arg types:",types)
+ (tspec, pState) = want_rest_of_symbol_type token types pState
+ = (tspec, pState)
+ where
+ want_rest_of_symbol_type :: !Token ![AType] !ParseState -> (SymbolType, !ParseState)
+ want_rest_of_symbol_type ArrowToken types pState
+ # (type, pState) = want pState
+ (context, pState) = optionalContext pState
+ (attr_env, pState) = optionalCoercions pState
+ = (makeSymbolType types type context attr_env, pState)
+ want_rest_of_symbol_type token [] pState
+ = (makeSymbolType [] (MakeAttributedType TE) [] [], parseError "symbol type" (Yes token) "type" pState)
+ want_rest_of_symbol_type token [type] pState
+ # (context, pState) = optionalContext (tokenBack pState)
+ (attr_env, pState) = optionalCoercions pState
+ = (makeSymbolType [] type context attr_env, pState)
+ want_rest_of_symbol_type token [type=:{at_type = TA type_symb []} : types] pState
+ # type = { type & at_type = TA { type_symb & type_arity = length types } types }
+ (context, pState) = optionalContext (tokenBack pState)
+ (attr_env, pState) = optionalCoercions pState
+ = (makeSymbolType [] type context attr_env, pState)
+ want_rest_of_symbol_type token [type=:{at_type = TV tv} : types] pState
+ # type = { type & at_type = CV tv :@: types }
+ (context, pState) = optionalContext (tokenBack pState)
+ (attr_env, pState) = optionalCoercions pState
+ = (makeSymbolType [] type context attr_env, pState)
+ want_rest_of_symbol_type token types pState
+ = (makeSymbolType [] (MakeAttributedType TE) [] [], parseError "symbol type" (Yes token) "->" pState) -->> types
+
+/*
+ Types
+*/
+
+nameToTypeVar name pState
+ # last_char_index = size name - 1
+ | name.[last_char_index] == '^'
+ # new_name = name % (0, last_char_index - 1)
+ # (ident, pState) = stringToIdent new_name IC_Type pState
+ = (GTV (MakeTypeVar ident), pState)
+ # (ident, pState) = stringToIdent name IC_Type pState
+ = (TV (MakeTypeVar ident), pState)
+
+instance want TypeVar
+where
+ want pState
+ # (token, pState) = nextToken TypeContext pState
+ = case token of
+ IdentToken name
+ | isLowerCaseName name
+ # (ident, pState) = stringToIdent name IC_Type pState
+ -> (MakeTypeVar ident, pState)
+ -> (MakeTypeVar erroneousIdent, parseError "Type variable" (Yes token) "<type variable>" pState)
+ _
+ -> (MakeTypeVar erroneousIdent, parseError "Type variable" (Yes token) "<type variable>" pState)
+
+adjustAttribute :: !TypeAttribute Type *ParseState -> (TypeAttribute,*ParseState)
+adjustAttribute TA_Anonymous (TV {tv_name={id_name}}) pState
+ # (ident, pState) = stringToIdent id_name IC_TypeAttr pState
+ = (TA_Var (makeAttributeVar ident), pState)
+adjustAttribute TA_Anonymous (GTV {tv_name={id_name}}) pState
+ # (ident, pState) = stringToIdent id_name IC_TypeAttr pState
+ = (TA_Var (makeAttributeVar ident), pState)
+adjustAttribute attr type pState
+ = (attr, pState)
+
+stringToType :: !String !ParseState -> (!Type, !ParseState)
+stringToType name pState
+ # (id, pState) = stringToIdent name IC_Type pState
+ | isLowerCaseName name
+ = nameToTypeVar name pState
+ = (TA (MakeNewTypeSymbIdent id 0) [], pState)
+/* | isUpperCaseName name
+ = (TA (MakeNewTypeSymbIdent id 0) [], pState)
+ = nameToTypeVar name pState
+*/
+/*
+stringToAType :: !String !Annotation !TypeAttribute !ParseState -> (!AType, !ParseState)
+stringToAType name annot attr pState
+ # (id, pState) = stringToIdent name IC_Type pState
+ | isUpperCaseName name
+ = ({ at_annotation = annot, at_attribute = attr, at_type = TA (MakeNewTypeSymbIdent id 0) []}, pState)
+ # (type_var, pState) = nameToTypeVar name pState
+ = build_attributed_type_var attr annot type_var name pState
+where
+ build_attributed_type_var TA_Anonymous annot type_var type_var_name pState
+ # (attr_id, pState) = stringToIdent type_var_name IC_TypeAttr pState
+ = ({ at_annotation = annot, at_attribute = TA_Var (makeAttributeVar attr_id), at_type = type_var }, pState)
+ build_attributed_type_var attr annot type_var _ pState
+ = ({ at_annotation = annot, at_attribute = attr, at_type = type_var }, pState)
+*/
+
+instance want AType
+where
+ want pState = wantAType pState
+
+instance want Type
+where
+ want pState = wantType pState
+
+wantType :: !ParseState -> (!Type,!ParseState)
+wantType pState
+ # (succ, atype, pState) = tryAType False AN_None TA_None pState
+ (succ2, type, pState) = tryATypeToType atype pState
+ | succ&&succ2
+ = (type, pState)
+ // otherwise //~ succ
+ # (token, pState) = nextToken TypeContext pState
+ = (type, parseError "type" (Yes token) "type" pState)
+
+wantAType :: !ParseState -> (!AType,!ParseState)
+wantAType pState
+ # (succ, atype, pState) = tryAType True AN_None TA_None pState
+ | succ
+ = (atype, pState)
+ // otherwise //~ succ
+ # (token, pState) = nextToken TypeContext pState
+ = (atype, parseError "atype" (Yes token) "attributed and annotated type" pState)
+
+tryType :: !ParseState -> (!Bool,!Type,!ParseState)
+tryType pState
+ # (succ, atype, pState) = tryAType False AN_None TA_None pState
+ (succ2, type, pState) = tryATypeToType atype pState
+ = (succ&&succ2, type, pState)
+
+tryAType :: !Bool !Annotation !TypeAttribute !ParseState -> (!Bool,!AType,!ParseState)
+tryAType tryAA annot attr pState
+ # (types, pState) = parseList tryBrackAType pState
+ | isEmpty types
+ = (False, {at_annotation = annot, at_attribute = attr, at_type = TE}, pState)
+ # (token, pState) = nextToken TypeContext pState
+ | token == ArrowToken
+ = tryFunctionType types annot attr pState
+ // otherwise
+ # pState = tokenBack pState
+ = tryApplicationType types annot attr pState
+
+tryFunctionType :: ![AType] !Annotation !TypeAttribute !ParseState -> (!Bool,!AType,!ParseState)
+tryFunctionType types annot attr pState
+ # (rtype, pState) = wantAType pState
+ = ( True
+ , make_curry_type annot attr types rtype
+ , pState
+ )
+where
+ make_curry_type annot attr [t1] res_type
+ = {at_annotation = annot, at_attribute = attr, at_type = t1 --> res_type}
+ make_curry_type annot attr [t1:tr] res_type
+ = {at_annotation = annot, at_attribute = attr, at_type = t1 --> make_curry_type AN_None TA_None tr res_type}
+ make_curry_type _ _ _ _ = abort "make_curry_type: wrong assumption"
+
+tryApplicationType :: ![AType] !Annotation !TypeAttribute !ParseState -> (!Bool,!AType,!ParseState)
+tryApplicationType [type1:types_rest] annot attr pState
+ # (annot, pState) = determAnnot annot type1.at_annotation pState
+ type = type1.at_type
+ (attr, pState) = determAttr attr type1.at_attribute type pState
+ | isEmpty types_rest
+ = ( True
+ , {at_annotation = annot, at_attribute = attr, at_type = type}
+ , pState
+ )
+ // otherwise // type application
+ # (type, pState) = convert_list_of_types type1.at_type types_rest pState
+ = ( True
+ , {at_annotation = annot, at_attribute = attr, at_type = type}
+ , pState
+ )
+where
+ convert_list_of_types (TA sym []) types pState
+ = (TA { sym & type_arity = length types } types, pState)
+ convert_list_of_types (TV tv) types pState
+ = (CV tv :@: types, pState)
+ convert_list_of_types _ types pState
+ = (TE, parseError "Type" No "ordinary type variable" pState)
+tryApplicationType _ annot attr pState
+ = (False, {at_annotation = annot, at_attribute = attr, at_type = TE}, pState)
+
+tryBrackType :: !ParseState -> (!Bool, Type, !ParseState)
+tryBrackType pState
+ # (succ, atype, pState) = trySimpleType AN_None TA_None pState
+ (succ2, type, pState) = tryATypeToType atype pState
+ = (succ&&succ2, type, pState)
+
+tryBrackAType :: !ParseState -> (!Bool, AType, !ParseState)
+tryBrackAType pState
+ # (_, annot, attr, pState) = optionalAnnotAndAttr pState
+ = trySimpleType annot attr pState
+
+trySimpleType :: !Annotation !TypeAttribute !ParseState -> (!Bool, !AType, !ParseState)
+trySimpleType annot attr pState
+ # (token, pState) = nextToken TypeContext pState
+ = trySimpleTypeT token annot attr pState
+
+trySimpleTypeT :: !Token !Annotation !TypeAttribute !ParseState -> (!Bool, !AType, !ParseState)
+trySimpleTypeT (IdentToken id) annot attr pState
+ | isLowerCaseName id
+ # (typevar, pState) = nameToTypeVar id pState
+ (attr, pState) = adjustAttribute attr typevar pState
+ = (True, {at_annotation = annot, at_attribute = attr, at_type = typevar}, pState)
+ | otherwise // | isUpperCaseName id || isFunnyIdName id
+ # (type, pState) = stringToType id pState
+ = (True, {at_annotation = annot, at_attribute = attr, at_type = type}, pState)
+trySimpleTypeT SquareOpenToken annot attr pState
+ # (token, pState) = nextToken TypeContext pState
+ | token == SquareCloseToken
+ # (list_symbol, pState) = makeListTypeSymbol 0 pState
+ = (True, {at_annotation = annot, at_attribute = attr, at_type = TA list_symbol []}, pState)
+ # (type, pState) = wantAType (tokenBack pState)
+ (token, pState) = nextToken TypeContext pState
+ | token == SquareCloseToken
+ # (list_symbol, pState) = makeListTypeSymbol 1 pState
+ = (True, {at_annotation = annot, at_attribute = attr, at_type = TA list_symbol [type]}, pState)
+ // otherwise // token <> SquareCloseToken
+ = (False, {at_annotation = annot, at_attribute = attr, at_type = TE}, parseError "List type" (Yes token) "]" pState)
+trySimpleTypeT OpenToken annot attr pState
+ # (token, pState) = nextToken TypeContext pState
+ | token == CommaToken
+ # (tup_arity, pState) = determine_arity_of_tuple 2 pState
+ (tuple_symbol, pState) = makeTupleTypeSymbol tup_arity 0 pState
+ = (True, {at_annotation = annot, at_attribute = attr, at_type = TA tuple_symbol []}, pState)
+ // otherwise // token <> CommaToken
+ # (atype, pState) = wantAType (tokenBack pState)
+ (token, pState) = nextToken TypeContext pState
+ | token == CloseToken
+ # (annot, pState) = determAnnot annot atype.at_annotation pState
+ type = atype.at_type
+ (attr, pState) = determAttr attr atype.at_attribute type pState
+ = (True, {at_annotation = annot, at_attribute = attr, at_type = type}, pState)
+ | token == CommaToken // TupleType
+ # (atypes, pState) = wantSequence CommaToken TypeContext pState
+ pState = wantToken TypeContext "tuple type" CloseToken pState
+ atypes = [atype:atypes]
+ arity = length atypes
+ (tuple_symbol, pState) = makeTupleTypeSymbol arity arity pState
+ = (True, {at_annotation = annot, at_attribute = attr, at_type = TA tuple_symbol atypes}, pState)
+ // otherwise // token <> CloseToken && token <> CommaToken
+ = (False, atype, parseError "Simple type" (Yes token) "')' or ','" pState)
+where
+ determine_arity_of_tuple :: !Int !ParseState -> (!Int, !ParseState)
+ determine_arity_of_tuple arity pState
+ # (token, pState) = nextToken TypeContext pState
+ | CommaToken == token
+ = determine_arity_of_tuple (inc arity) pState
+ | CloseToken == token
+ = (arity, pState)
+ = (arity, parseError "tuple type" (Yes token) ")" pState)
+trySimpleTypeT CurlyOpenToken annot attr pState
+ # (token, pState) = nextToken TypeContext pState
+ | token == CurlyCloseToken
+ # (array_symbol, pState) = makeLazyArraySymbol 0 pState
+ = (True, {at_annotation = annot, at_attribute = attr, at_type = TA array_symbol []}, pState)
+ | token == HashToken
+ # (token, pState) = nextToken TypeContext pState
+ | token == CurlyCloseToken
+ # (array_symbol, pState) = makeUnboxedArraySymbol 0 pState
+ = (True, {at_annotation = annot, at_attribute = attr, at_type = TA array_symbol []}, pState)
+ // otherwise // token <> CurlyCloseToken
+ # (atype, pState) = wantAType (tokenBack pState)
+ pState = wantToken TypeContext "unboxed array type" CurlyCloseToken pState
+ (array_symbol, pState) = makeUnboxedArraySymbol 1 pState
+ = (True, {at_annotation = annot, at_attribute = attr, at_type = TA array_symbol [atype]}, pState)
+ | token == ExclamationToken
+ # (token, pState) = nextToken TypeContext pState
+ | token == CurlyCloseToken
+ # (array_symbol, pState) = makeStrictArraySymbol 0 pState
+ = (True, {at_annotation = annot, at_attribute = attr, at_type = TA array_symbol []}, pState)
+ // otherwise // token <> CurlyCloseToken
+ # (atype,pState) = wantAType (tokenBack pState)
+ pState = wantToken TypeContext "strict array type" CurlyCloseToken pState
+ (array_symbol, pState) = makeStrictArraySymbol 1 pState
+ = (True, {at_annotation = annot, at_attribute = attr, at_type = TA array_symbol [atype]}, pState)
+ // otherwise
+ # (atype,pState) = wantAType (tokenBack pState)
+ pState = wantToken TypeContext "lazy array type" CurlyCloseToken pState
+ (array_symbol, pState) = makeLazyArraySymbol 1 pState
+ = (True, {at_annotation = annot, at_attribute = attr, at_type = TA array_symbol [atype]}, pState)
+trySimpleTypeT StringTypeToken annot attr pState
+ # (type, pState) = makeStringTypeSymbol pState
+ = (True, {at_annotation = annot, at_attribute = attr, at_type = TA type []}, pState)
+trySimpleTypeT token annot attr pState
+ # (bt, pState) = try token pState
+ = case bt of
+ Yes bt -> (True , {at_annotation = annot, at_attribute = attr, at_type = TB bt}, pState)
+ no -> (False, {at_annotation = annot, at_attribute = attr, at_type = TE} , pState)
+
+instance try BasicType
+where
+ try IntTypeToken pState = (Yes BT_Int , pState)
+ try CharTypeToken pState = (Yes BT_Char , pState)
+ try BoolTypeToken pState = (Yes BT_Bool , pState)
+ try RealTypeToken pState = (Yes BT_Real , pState)
+ try DynamicTypeToken pState = (Yes BT_Dynamic , pState)
+ try FileTypeToken pState = (Yes BT_File , pState)
+ try WorldTypeToken pState = (Yes BT_World , pState)
+ try _ pState = (No , tokenBack pState)
+
+determAnnot :: !Annotation !Annotation !ParseState -> (!Annotation, !ParseState)
+determAnnot AN_None annot2 pState = (annot2, pState)
+determAnnot annot1 AN_None pState = (annot1, pState)
+determAnnot annot1 annot2 pState
+ = (annot1, parseError "simple type" No ("More type annotations, "+toString annot1+" and "+toString annot2+", than") pState)
+
+determAttr :: !TypeAttribute !TypeAttribute !Type !ParseState -> (!TypeAttribute, !ParseState)
+determAttr TA_None attr2 type pState = adjustAttribute attr2 type pState
+determAttr attr1 TA_None type pState = adjustAttribute attr1 type pState
+determAttr attr1 attr2 type pState
+ = (attr1, parseError "simple type" No ("More type attributes, "+toString attr1+" and "+toString attr2+", than") pState)
+
+wantDynamicType :: !*ParseState -> *(!DynamicType,!*ParseState)
+wantDynamicType pState
+ # (type_vars, pState) = optionalQuantifiedVariables UniversalQuantifier pState
+ (type, pState) = want pState
+ = ({ dt_uni_vars = type_vars, dt_type = type, dt_global_vars = [] }, pState)
+
+:: QuantifierKind = UniversalQuantifier | ExistentialQuantifier
+
+instance == QuantifierKind
+where
+ (==) UniversalQuantifier UniversalQuantifier
+ = True
+ (==) ExistentialQuantifier ExistentialQuantifier
+ = True
+ (==) _ _
+ = False
+
+instance try QuantifierKind
+where
+ try (IdentToken name) pState
+ | name == "A"
+ # (token, pState) = nextToken TypeContext pState
+ | token == DotToken
+ = (Yes UniversalQuantifier, pState)
+ = (No, tokenBack (tokenBack pState))
+ | name == "E"
+ # (token, pState) = nextToken TypeContext pState
+ | token == DotToken
+ = (Yes ExistentialQuantifier, pState)
+ = (No, tokenBack (tokenBack pState))
+ try token pState
+ = (No, tokenBack pState)
+
+optionalQuantifiedVariables :: !QuantifierKind !*ParseState -> *(![ATypeVar],!*ParseState)
+optionalQuantifiedVariables req_quant pState
+ # (token, pState) = nextToken TypeContext pState
+ (optional_quantifier, pState) = try token pState
+ = case optional_quantifier of
+ Yes off_quant
+ # (vars, pState) = wantList "quantified variable(s)" try_Attributed_TypeVar pState
+ | req_quant == off_quant
+ -> (vars, pState)
+ -> (vars, parseError "optional quantified variables" No "illegal quantifier" pState)
+ No
+ -> ([], pState)
+where
+ try_Attributed_TypeVar :: !ParseState -> (Bool,ATypeVar,ParseState)
+ try_Attributed_TypeVar pState
+ # (token, pState) = nextToken TypeContext pState
+ = case token of
+ DotToken
+ # (succ,typevar, pState) = tryTypeVar pState
+ | succ
+ # atypevar = {atv_attribute = TA_Anonymous, atv_annotation = AN_None, atv_variable = typevar}
+ -> (True,atypevar,pState)
+ -> (False,abort "no ATypeVar",pState)
+ _
+ # (succ,typevar, pState) = tryTypeVar (tokenBack pState)
+ | succ
+ # atypevar = {atv_attribute = TA_None, atv_annotation = AN_None, atv_variable = typevar}
+ -> (True,atypevar,pState)
+ -> (False,abort "no ATypeVar",pState)
+
+tryATypeToType :: !AType !ParseState -> (!Bool, !Type, !ParseState)
+tryATypeToType atype pState
+ | atype.at_annotation <> AN_None
+ = ( False
+ , atype.at_type
+ , parseError "simple type" No ("type instead of type annotation "+toString atype.at_annotation) pState
+ )
+ | atype.at_attribute <> TA_None
+ = ( False
+ , atype.at_type
+ , parseError "simple type" No ("type instead of type attribute "+toString atype.at_attribute) pState
+ )
+ // otherwise
+ = (True, atype.at_type, pState)
+
+/*
+ Expressions
+*/
+/*
+wantMainExp :: !ParseState -> (ParsedExpr, !ParseState)
+wantMainExp pState
+ # (exp, pState) = wantExpression cIsNotAPattern pState
+ = (exp, wantEndOfFileToken pState)
+*/
+cIsAPattern :== True
+cIsNotAPattern :== False
+
+wantExpression :: !Bool !ParseState -> (!ParsedExpr, !ParseState)
+wantExpression is_pattern pState
+ # (token, pState) = nextToken FunctionContext pState
+ | is_pattern
+ = wantLhsExpressionT token pState
+ = wantRhsExpressionT token pState
+
+wantRhsExpressionT :: !Token !ParseState -> (!ParsedExpr, !ParseState)
+wantRhsExpressionT token pState
+ # (succ, expr, pState) = trySimpleRhsExpressionT token pState
+ | succ
+ # (exprs, pState) = parseList trySimpleRhsExpression pState
+ = (combineExpressions expr exprs, pState)
+ = (PE_Empty, parseError "RHS expression" (Yes token) "<expression>" pState)
+
+wantLhsExpressionT :: !Token !ParseState -> (!ParsedExpr, !ParseState)
+wantLhsExpressionT token pState
+ # (succ, expr, pState) = trySimpleLhsExpressionT token pState
+ | succ
+ # (exprs, pState) = parseList trySimpleLhsExpression pState
+ = (combineExpressions expr exprs, pState)
+ = (PE_Empty, parseError "LHS expression" (Yes token) "<expression>" pState)
+
+combineExpressions expr []
+ = expr
+combineExpressions expr exprs
+ = make_app_exp expr exprs
+where
+ make_app_exp exp []
+ = exp
+ make_app_exp (PE_Bound be=:{ bind_src}) exps
+ = PE_Bound { be & bind_src = make_app_exp bind_src exps }
+ make_app_exp exp exprs
+ = PE_List [exp : exprs]
+
+trySimpleLhsExpression :: !ParseState -> (!Bool, !ParsedExpr, !ParseState)
+trySimpleLhsExpression pState
+ # (token, pState) = nextToken FunctionContext pState
+ = trySimpleLhsExpressionT token pState
+
+trySimpleLhsExpressionT :: !Token !ParseState -> (!Bool, !ParsedExpr, !ParseState)
+trySimpleLhsExpressionT token pState
+ # (succ, expr, pState) = trySimpleExpressionT token cIsAPattern pState
+ | succ
+ # (token, pState) = nextToken FunctionContext pState
+ | token == DoubleColonToken
+ # (dyn_type, pState) = wantDynamicType pState
+ = (True, PE_DynamicPattern expr dyn_type, pState)
+ = (True, expr, tokenBack pState)
+ = (False, PE_Empty, pState)
+
+trySimpleRhsExpression :: !ParseState -> (!Bool, !ParsedExpr, !ParseState)
+trySimpleRhsExpression pState
+ # (token, pState) = nextToken FunctionContext pState
+ = trySimpleRhsExpressionT token pState
+
+trySimpleRhsExpressionT :: !Token !ParseState -> (!Bool, !ParsedExpr, !ParseState)
+trySimpleRhsExpressionT token pState
+ # (succ, expr, pState) = trySimpleExpressionT token cIsNotAPattern pState
+ | succ
+ # (expr, pState) = extend_expr_with_selectors expr pState
+ = (True, expr, pState)
+ = (False, PE_Empty, pState)
+where
+ extend_expr_with_selectors :: !ParsedExpr !ParseState -> (!ParsedExpr, !ParseState)
+ extend_expr_with_selectors exp pState
+ # (token, pState) = nextToken FunctionContext pState
+ | token == DotToken
+ # (token, pState) = nextToken FunctionContext pState
+ (selectors, pState) = wantSelectors token pState
+ = (PE_Selection cNonUniqueSelection exp selectors, pState)
+ | token == ExclamationToken
+ # (token, pState) = nextToken FunctionContext pState
+ (selectors, pState) = wantSelectors token pState
+ = (PE_Selection cUniqueSelection exp selectors, pState)
+ | otherwise
+ = (exp, tokenBack pState)
+
+wantSelectors :: Token *ParseState -> *(![ParsedSelection], !*ParseState)
+wantSelectors token pState
+ # (selector, pState) = want_selector token pState
+ (token, pState) = nextToken FunctionContext pState
+ | token == DotToken
+ # (token, pState) = nextToken FunctionContext pState
+ (selectors, pState) = wantSelectors token pState
+ = (selector ++ selectors, pState)
+ = (selector, tokenBack pState)
+where
+ want_selector :: !Token !*ParseState -> *(![ParsedSelection], !*ParseState)
+ want_selector SquareOpenToken pState
+ # (array_selectors, pState) = want_array_selectors pState
+ = (array_selectors, wantToken FunctionContext "array selector" SquareCloseToken pState)
+ where
+ want_array_selectors :: !*ParseState -> *(![ParsedSelection], !*ParseState)
+ want_array_selectors pState
+ # (index_expr, pState) = wantExpression cIsNotAPattern pState
+ selector = PS_Array index_expr
+ (token, pState) = nextToken FunctionContext pState
+ | token == CommaToken
+ # (selectors, pState) = want_array_selectors pState
+ = ([selector : selectors], pState)
+ = ([selector], tokenBack pState)
+
+ want_selector (IdentToken name) pState
+ | isUpperCaseName name
+ # (field, pState) = want (wantToken FunctionContext "array selector" DotToken pState)
+ (field_id, pState) = stringToIdent field IC_Selector pState
+ (type_id, pState) = stringToIdent name IC_Type pState
+ = ([PS_Record field_id (Yes type_id)], pState)
+ # (field_id, pState) = stringToIdent name IC_Selector pState
+ = ([PS_Record field_id No], pState)
+ want_selector token pState
+ = ([PS_Erroneous], parseError "simple RHS expression" (Yes token) "<selector>" pState)
+
+trySimpleExpression :: !Bool !ParseState -> (!Bool, !ParsedExpr, !ParseState)
+trySimpleExpression is_pattern pState
+ | is_pattern
+ = trySimpleLhsExpression pState
+ = trySimpleRhsExpression pState
+
+trySimpleExpressionT :: !Token !Bool !ParseState -> (!Bool, !ParsedExpr, !ParseState)
+trySimpleExpressionT (IdentToken name) is_pattern pState
+ | isLowerCaseName name
+ # (id, pState) = stringToIdent name IC_Expression pState
+ (token, pState) = nextToken FunctionContext pState
+ | token == DefinesColonToken
+ # (succ, expr, pState) = trySimpleExpression is_pattern pState
+ | succ
+ = (True, PE_Bound { bind_dst = id, bind_src = expr }, pState)
+ = (True, PE_Empty, parseError "simple expression" No "expression" pState)
+ = (True, PE_Ident id, tokenBack pState)
+trySimpleExpressionT (IdentToken name) is_pattern pState
+// | isUpperCaseName name || ~ is_pattern
+ # (id, pState) = stringToIdent name IC_Expression pState
+ = (True, PE_Ident id, pState)
+trySimpleExpressionT SquareOpenToken is_pattern pState
+ # (list_expr, pState) = wantListExp is_pattern pState
+ = (True, list_expr, pState)
+trySimpleExpressionT OpenToken is_pattern pState
+ # (args=:[exp:exps], pState) = want_expression_list is_pattern pState
+ pState = wantToken FunctionContext "expression list" CloseToken pState
+ | isEmpty exps
+ = case exp of
+ PE_Ident id
+ -> (True, PE_List [exp], pState)
+ _
+ -> (True, exp, pState)
+ // # (token,pState) = nextToken FunctionContext pState // for debugging
+ // pState = tokenBack pState -->> ("PE_tuple",args,token)
+ = (True, PE_Tuple args, pState)
+where
+ want_expression_list is_pattern pState
+ # (expr, pState) = wantExpression is_pattern pState
+ (token, pState) = nextToken FunctionContext pState
+ | token == CommaToken
+ # (exprs, pState) = want_expression_list is_pattern pState
+ = ([expr : exprs], pState)
+ = ([expr], tokenBack pState)
+trySimpleExpressionT CurlyOpenToken is_pattern pState
+ # (rec_or_aray_exp, pState) = wantRecordOrArrayExp is_pattern pState
+ = (True, rec_or_aray_exp, pState)
+trySimpleExpressionT (IntToken int) is_pattern pState
+ = (True, PE_Basic (BVI int), pState)
+trySimpleExpressionT (StringToken string) is_pattern pState
+ = (True, PE_Basic (BVS string), pState)
+trySimpleExpressionT (BoolToken bool) is_pattern pState
+ = (True, PE_Basic (BVB bool), pState)
+trySimpleExpressionT (CharToken char) is_pattern pState
+ = (True, PE_Basic (BVC char), pState)
+trySimpleExpressionT (RealToken real) is_pattern pState
+ = (True, PE_Basic (BVR real), pState)
+trySimpleExpressionT token is_pattern pState
+ | is_pattern
+ | token == WildCardToken
+ = (True, PE_WildCard, pState)
+ = (False, PE_Empty, tokenBack pState)
+ = trySimpleNonLhsExpressionT token pState
+
+trySimpleNonLhsExpressionT BackSlashToken pState
+ # (lam_ident, pState) = internalIdent "\\" pState
+ (lam_args, pState) = wantList "arguments" trySimpleLhsExpression pState
+ // pState = wantToken FunctionContext "lambda expression" ArrowToken pState
+ pState = want_lambda_sep pState
+ (exp, pState) = wantExpression cIsNotAPattern pState
+ = (True, PE_Lambda lam_ident lam_args exp, pState)
+ where
+ want_lambda_sep pState
+ # (token, pState) = nextToken FunctionContext pState
+ = case token of
+ ArrowToken -> pState
+ EqualToken -> pState
+ DotToken -> pState
+ _ -> parseError "lambda expression" (Yes token) "-> or =" (tokenBack pState)
+//trySimpleNonLhsExpressionT (LetToken strict) pState
+trySimpleNonLhsExpressionT (LetToken strict=:False) pState // let! is not supported in Clean 2.0
+ # (let_binds, pState) = wantLocals pState
+ pState = wantToken FunctionContext "let expression" InToken pState
+ (let_expr, pState) = wantExpression cIsNotAPattern pState
+ = (True, PE_Let strict let_binds let_expr, pState)
+trySimpleNonLhsExpressionT WildCardToken pState
+ = (True, PE_WildCard, pState)
+trySimpleNonLhsExpressionT CaseToken pState
+ # (case_exp, pState) = wantCaseExp pState
+ = (True, case_exp, pState)
+trySimpleNonLhsExpressionT IfToken pState
+ # (if_ident, pState) = internalIdent "_if" pState
+ (cond_exp, pState) = want_simple_expression "condition of if" pState
+ (then_exp, pState) = want_simple_expression "then-part of if" pState
+ (else_exp, pState) = want_simple_expression "else-part of if" pState
+ = (True, PE_If if_ident cond_exp then_exp else_exp, pState)
+where
+ want_simple_expression error pState
+ # (succ, expr, pState) = trySimpleRhsExpression pState
+ | succ
+ = (expr, pState)
+ = (PE_Empty, parseError error No "<expression>" pState)
+trySimpleNonLhsExpressionT DynamicToken pState
+ # (dyn_expr, pState) = wantExpression cIsNotAPattern pState
+ (token, pState) = nextToken FunctionContext pState
+ | token == DoubleColonToken
+ # (dyn_type, pState) = wantDynamicType pState
+ = (True, PE_Dynamic dyn_expr (Yes dyn_type), pState)
+ = (True, PE_Dynamic dyn_expr No, tokenBack pState)
+trySimpleNonLhsExpressionT token pState
+ = (False, PE_Empty, tokenBack pState)
+
+wantListExp :: !Bool !ParseState -> (ParsedExpr, !ParseState)
+wantListExp is_pattern pState
+ # (token, pState) = nextToken FunctionContext pState
+ = case token of
+ SquareCloseToken
+ -> makeNilExpression pState
+ _ -> want_LGraphExpr token [] pState
+where
+ want_list acc pState
+ # (token, pState) = nextToken FunctionContext pState
+ = case token of
+ SquareCloseToken
+ # (nil_expr, pState) = makeNilExpression pState
+ -> gen_cons_nodes acc nil_expr pState
+ CommaToken
+ # (token, pState) = nextToken FunctionContext pState
+ -> want_LGraphExpr token acc pState
+ ColonToken
+ # (token, pState) = nextToken FunctionContext pState
+ (exp, pState) = wantRhsExpressionT token pState
+ pState = wantToken FunctionContext "list" SquareCloseToken pState
+ -> gen_cons_nodes acc exp pState
+ DotDotToken
+ | length acc > 2 || isEmpty acc
+ # (nil_expr, pState) = makeNilExpression pState
+ pState = parseError "list expression" No "one or two expressions before .." pState
+ -> gen_cons_nodes acc nil_expr pState
+ # (token, pState) = nextToken FunctionContext pState
+ -> case token of
+ SquareCloseToken
+ -> case acc of
+ [e] -> (PE_Sequ (SQ_From e), pState)
+ [e2,e1]
+ -> (PE_Sequ (SQ_FromThen e1 e2), pState)
+ _ -> abort "Error 1 in WantListExp"
+ _ # (exp, pState) = wantRhsExpressionT token pState
+ pState = wantToken FunctionContext "dot dot expression" SquareCloseToken pState
+ -> case acc of
+ [e] -> (PE_Sequ (SQ_FromTo e exp), pState)
+ [e2,e1]
+ -> (PE_Sequ (SQ_FromThenTo e1 e2 exp), pState)
+ _ -> abort "Error 2 in WantListExp"
+ DoubleBackSlashToken
+ | length acc == 1
+ -> wantComprehension cIsListGenerator (acc!!0) pState
+ // otherwise // length acc <> 1
+ # (nil_expr, pState) = makeNilExpression pState
+ pState = parseError "list comprehension" No "one expressions before \\\\" pState
+ -> gen_cons_nodes acc nil_expr pState
+ _ # (nil_expr, pState) = makeNilExpression pState
+ pState = parseError "list" (Yes token) "list element separator" pState
+ -> gen_cons_nodes acc nil_expr pState
+
+ want_LGraphExpr token acc pState
+ = case token of
+ CharListToken chars
+ -> want_list (add_chars (fromString chars) acc) pState
+ with
+ add_chars [] acc = acc
+ add_chars [c:r] acc = add_chars r [PE_Basic (BVC (toString ['\'',c,'\''])): acc]
+ _ # (exp, pState) = (if is_pattern (wantLhsExpressionT token) (wantRhsExpressionT token)) pState
+ -> want_list [exp: acc] pState
+
+ gen_cons_nodes [] exp pState
+ = (exp, pState)
+ gen_cons_nodes [e:r] exp pState
+ # (exp, pState) = makeConsExpression e exp pState
+ = gen_cons_nodes r exp pState
+
+/**
+ (List and Array) Comprehensions
+**/
+
+wantComprehension :: !GeneratorKind !ParsedExpr !ParseState -> (!ParsedExpr, !ParseState)
+wantComprehension gen_kind exp pState
+ # (qualifiers, pState) = wantQualifiers 0 0 pState
+ | gen_kind == cIsListGenerator
+ = (PE_Compr cIsListGenerator exp qualifiers, wantToken FunctionContext "list comprehension" SquareCloseToken pState)
+ = (PE_Compr cIsArrayGenerator exp qualifiers, wantToken FunctionContext "array comprehension" CurlyCloseToken pState)
+
+wantQualifiers :: !Int !Int !ParseState -> (![Qualifier], !ParseState)
+wantQualifiers nr_of_quals nr_of_gens pState
+ # (qual, nr_of_gens, pState) = want_qualifier nr_of_quals nr_of_gens pState
+ (token, pState) = nextToken FunctionContext pState
+ | token == CommaToken
+ # (quals, pState) = wantQualifiers (inc nr_of_quals) nr_of_gens pState
+ = ([qual : quals], pState)
+ = ([qual], tokenBack pState)
+where
+
+ want_qualifier :: !Int !Int !ParseState -> (!Qualifier, !Int, !ParseState)
+ want_qualifier qual_nr gen_nr pState
+ # (lhs_expr, pState) = wantExpression cIsAPattern pState
+ (token, pState) = nextToken FunctionContext pState
+ | token == LeftArrowToken
+ = want_generators cIsListGenerator qual_nr gen_nr lhs_expr pState
+ | token == LeftArrowColonToken
+ = want_generators cIsArrayGenerator qual_nr gen_nr lhs_expr pState
+ = ({qual_generators = [], qual_filter = No, qual_fun_id = { id_name = "", id_info = nilPtr}}, gen_nr,
+ parseError "comprehension: qualifier" (Yes token) "qualifier(s)" pState)
+
+ want_generators :: !GeneratorKind !Int !Int !ParsedExpr !ParseState -> (!Qualifier, !Int, !ParseState)
+ want_generators gen_kind qual_nr gen_nr pattern_exp pState
+ # (gen_expr, pState) = wantExpression cIsNotAPattern pState
+ (token, pState) = nextToken FunctionContext pState
+ (gen_var, pState) = stringToIdent ("tl" +++ toString gen_nr) IC_Expression pState
+ generator = { gen_kind = gen_kind, gen_expr = gen_expr, gen_pattern = pattern_exp, gen_var = gen_var }
+ | token == BarToken
+ # (filter_expr, pState) = wantExpression cIsNotAPattern pState
+ (qual_fun_id, pState) = stringToIdent ("_compr" +++ toString qual_nr) IC_Expression pState
+ = ({qual_generators = [generator], qual_filter = Yes filter_expr, qual_fun_id = qual_fun_id }, inc gen_nr, pState)
+ | token == AndToken
+ # (qualifier, gen_nr, pState) = want_qualifier qual_nr (inc gen_nr) pState
+ = ({qualifier & qual_generators = [ generator : qualifier.qual_generators] }, gen_nr, pState)
+ # (qual_fun_id, pState) = stringToIdent ("_compr" +++ toString qual_nr) IC_Expression pState
+ = ({qual_generators = [generator], qual_filter = No, qual_fun_id = qual_fun_id}, inc gen_nr, tokenBack pState)
+
+/**
+ Case Expressions
+**/
+
+wantCaseExp :: !ParseState -> (ParsedExpr, !ParseState)
+wantCaseExp pState
+ # (case_ident, pState) = internalIdent "_c" pState
+ (case_exp, pState) = wantExpression cIsNotAPattern pState
+ pState = wantToken FunctionContext "case expression" OfToken pState
+ pState = wantBeginGroup "case" pState
+ (case_alts, pState) = parseList tryCaseAlt pState
+ (found, alt, pState) = tryLastCaseAlt pState
+ | found
+ = (PE_Case case_ident case_exp (case_alts++[alt]), wantEndCase pState)
+ = (PE_Case case_ident case_exp case_alts, wantEndCase pState)
+where
+ tryCaseAlt :: !ParseState -> (!Bool, CaseAlt, !ParseState)
+ tryCaseAlt pState
+ # (succ, pattern, pState) = try_pattern pState
+ | succ
+ # (rhs, pState) = wantRhs caseSeperator pState
+ = (True, { calt_pattern = pattern, calt_rhs = rhs }, pState) // -->> ("case alt", pattern)
+ // otherwise // ~ succ
+ = (False, abort "no case alt", pState)
+
+ tryLastCaseAlt :: !ParseState -> (!Bool, CaseAlt, !ParseState)
+ tryLastCaseAlt pState
+ # (token, pState) = nextToken FunctionContext pState
+ | caseSeperator token
+ # pState = tokenBack pState
+ (rhs, pState) = wantRhs caseSeperator pState
+ = (True, { calt_pattern = PE_WildCard, calt_rhs = rhs }, pState) // -->> ("default case alt")
+ | token == OtherwiseToken
+ # (token, pState) = nextToken FunctionContext pState
+ pState = tokenBack pState
+ | caseSeperator token
+ # (rhs, pState) = wantRhs caseSeperator pState
+ = (True, { calt_pattern = PE_WildCard, calt_rhs = rhs }, pState) // -->> ("default case alt")
+ = (False, abort "no case alt", pState)
+ = (False, abort "no case alt", tokenBack pState)
+
+ caseSeperator t = t == EqualToken || t == ArrowToken // to enable Clean 1.x case expressions
+
+ try_pattern :: !ParseState -> (!Bool, ParsedExpr, !ParseState)
+ try_pattern pState
+ # (succ, expr, pState) = trySimpleLhsExpression pState
+ | succ
+ # (succ, expr2, pState) = trySimpleLhsExpression pState
+ | succ
+ # (exprs, pState) = parseList trySimpleLhsExpression pState
+ = (True, PE_List [expr,expr2 : exprs], pState)
+ = (True, expr, pState)
+ = (False, abort "no expression", pState)
+
+:: NestedUpdate =
+ { nu_selectors :: ![ParsedSelection]
+ , nu_update_expr :: !ParsedExpr
+ }
+errorIdent :: Ident
+errorIdent
+ = {id_name = "<<error>>", id_info = nilPtr}
+
+buildNodeDef :: ParsedExpr ParsedExpr -> ParsedDefinition
+buildNodeDef lhsExpr rhsExpr
+ = PD_NodeDef NoPos lhsExpr rhs
+ where
+ rhs =
+ { rhs_alts
+ = UnGuardedExpr
+ { ewl_nodes = []
+ , ewl_locals = LocalParsedDefs []
+ , ewl_expr = rhsExpr
+ }
+ , rhs_locals
+ = LocalParsedDefs []
+ }
+
+/**
+ Record expressions
+**/
+
+wantRecordOrArrayExp :: !Bool !ParseState -> (ParsedExpr, !ParseState)
+wantRecordOrArrayExp is_pattern pState
+ # (token, pState) = nextToken FunctionContext pState
+ | token == CurlyCloseToken
+ = (PE_ArrayDenot [], pState)
+ | is_pattern
+ | token == SquareOpenToken
+ // # (elems, pState) = want_array_assignments cIsAPattern pState // currently no array selections in pattern PK
+ // = (PE_Array PE_Empty elems [], wantToken FunctionContext "array selections in pattern" CurlyCloseToken pState)
+ = (PE_Empty, parseError "array selection" No "No array selection in pattern" pState)
+ // otherwise // is_pattern && token <> SquareOpenToken
+ = want_record_pattern token pState
+ // otherwise // ~ is_pattern
+ # (opt_type, pState) = try_type_specification token pState
+ = case opt_type of
+ Yes _
+ -> want_record opt_type pState
+ _
+ # (succ, field, pState) = try_field_assignment token pState
+ | succ
+ # (token, pState) = nextToken FunctionContext pState
+ | token == CommaToken
+ # (token, pState) = nextToken FunctionContext pState
+ (fields, pState) = want_field_assignments cIsNotAPattern token pState
+ -> (PE_Record PE_Empty No [ field : fields ], wantToken FunctionContext "record or array" CurlyCloseToken pState)
+ | token == CurlyCloseToken
+ -> (PE_Record PE_Empty No [ field ], pState)
+ -> (PE_Record PE_Empty No [ field ], parseError "record or array" (Yes token) "}" pState)
+ # (expr, pState) = wantRhsExpressionT token pState
+ (token, pState) = nextToken FunctionContext pState
+ | token == AndToken
+ # (token, pState) = nextToken FunctionContext pState
+ -> want_record_or_array_update token expr pState
+ | token == DoubleBackSlashToken
+ -> wantComprehension cIsArrayGenerator expr pState
+ # (elems, pState) = want_array_elems token pState
+ -> (PE_ArrayDenot [expr : elems], pState)
+where
+ want_array_elems CurlyCloseToken pState
+ = ([], pState)
+ want_array_elems CommaToken pState
+ # (elem, pState) = wantExpression cIsNotAPattern pState
+ (token, pState) = nextToken FunctionContext pState
+ (elems, pState) = want_array_elems token pState
+ = ([elem : elems], pState)
+ want_array_elems token pState
+ = ([], parseError "array elements" (Yes token) "<array denotation>" pState)
+
+ want_record_pattern (IdentToken ident) pState
+ | isUpperCaseName ident
+ # pState = wantToken FunctionContext "record pattern" BarToken pState
+ (type_id, pState) = stringToIdent ident IC_Type pState
+ (token, pState) = nextToken FunctionContext pState
+ (fields, pState) = want_field_assignments cIsAPattern token pState
+ = (PE_Record PE_Empty (Yes type_id) fields, wantToken FunctionContext "record pattern" CurlyCloseToken pState)
+ want_record_pattern token pState
+ # (fields, pState) = want_field_assignments cIsAPattern token pState
+ = (PE_Record PE_Empty No fields, wantToken FunctionContext "record pattern" CurlyCloseToken pState)
+
+ try_type_specification (IdentToken ident) pState
+ | isUpperCaseName ident || isFunnyIdName ident
+ # (token, pState) = nextToken FunctionContext pState
+ | token == BarToken
+ # (type_id, pState) = stringToIdent ident IC_Type pState
+ = (Yes type_id, pState)
+ = (No, tokenBack pState)
+ = (No, pState)
+ try_type_specification _ pState
+ = (No, pState)
+
+ want_updates :: Token ParsedExpr ParseState -> (ParsedExpr, ParseState)
+ want_updates token update_expr pState
+ # (updates, pState)
+ = parse_updates token update_expr pState
+ = transform_record_or_array_update update_expr updates pState
+ where
+ parse_updates :: Token ParsedExpr ParseState -> ([NestedUpdate], ParseState)
+ parse_updates token update_expr pState
+ # (update, pState) = want_update token pState
+ (token, pState) = nextToken FunctionContext pState
+ | token == CommaToken
+ # (token, pState) = nextToken FunctionContext pState
+ (updates, pState) = parse_updates token update_expr pState
+ = ([update : updates], pState)
+ // otherwise
+ = ([update], tokenBack pState)
+
+ want_update :: Token ParseState -> (NestedUpdate, ParseState)
+ want_update token pState
+ # (selectors, pState) = wantSelectors token pState
+ (token, pState) = nextToken FunctionContext pState
+ | token == EqualToken
+ # (expr, pState) = wantExpression cIsNotAPattern pState
+ = ({nu_selectors = selectors, nu_update_expr = expr}, pState)
+ = ({nu_selectors = selectors, nu_update_expr = PE_Empty}, parseError "field assignment" (Yes token) "=" pState)
+
+ transform_record_or_array_update :: ParsedExpr [NestedUpdate] ParseState -> (ParsedExpr, ParseState)
+ transform_record_or_array_update expr updates pState
+ | is_record_update sortedUpdates
+ = transform_record_update expr groupedUpdates pState
+ // otherwise
+ = transform_array_update expr updates pState
+ where
+ sortedUpdates
+ // sort updates by first field name, array updates last
+ = sortBy smaller_update updates
+ where
+ smaller_update :: NestedUpdate NestedUpdate -> Bool
+ smaller_update a b
+ = smaller_selector (hd a.nu_selectors) (hd b.nu_selectors)
+ where
+ smaller_selector :: ParsedSelection ParsedSelection -> Bool
+ smaller_selector (PS_Record ident1 _) (PS_Record ident2 _)
+ = ident1.id_name < ident2.id_name
+ smaller_selector (PS_Record _ _) _
+ = True
+ smaller_selector _ _
+ = False
+
+ groupedUpdates
+ // group nested updates by first field name
+ = groupBy equal_update sortedUpdates
+ where
+ equal_update :: NestedUpdate NestedUpdate -> Bool
+ equal_update a b
+ = equal_selectors a.nu_selectors b.nu_selectors
+ where
+ equal_selectors :: [ParsedSelection] [ParsedSelection] -> Bool
+ equal_selectors [PS_Record ident1 _ : [_]] [PS_Record ident2 _ : [_]]
+ = ident1.id_name == ident2.id_name
+ equal_selectors _ _
+ = False
+
+ is_record_update [{nu_selectors=[select : _]} : _]
+ = is_record_select select
+ is_record_update updates
+ = False
+
+ is_record_select (PS_Record _ _)
+ = True
+ is_record_select _
+ = False
+
+ transform_record_update :: ParsedExpr ![[NestedUpdate]] ParseState -> (ParsedExpr, ParseState)
+ transform_record_update expr groupedUpdates pState
+ # (assignments, (optionalIdent, pState))
+ = mapSt transform_update groupedUpdates (No, pState)
+ updateExpr
+ = build_update optionalIdent expr assignments
+ = (updateExpr, pState)
+ where
+ // transform one group of nested updates with the same first field
+ // for example: f.g1 = e1, f.g2 = e2 -> f = {id.f & g1 = e1, g2 = e2},
+ // (id is ident to shared expression that's being updated)
+ transform_update :: [NestedUpdate] (Optional Ident, ParseState) -> (FieldAssignment, (Optional Ident, ParseState))
+ transform_update [{nu_selectors=[PS_Record fieldIdent _], nu_update_expr}] state
+ = ({bind_dst = fieldIdent, bind_src = nu_update_expr}, state)
+ transform_update updates=:[{nu_selectors=[PS_Record fieldIdent _ : _]} : _] (optionalIdent, pState)
+ # (shareIdent, pState)
+ = make_ident optionalIdent pState
+ select
+ = PE_Selection cNonUniqueSelection (PE_Ident shareIdent) [PS_Record fieldIdent No]
+ (update_expr, pState)
+ = transform_record_or_array_update select (map sub_update updates) pState
+ = ({bind_dst = fieldIdent, bind_src = update_expr}, (Yes shareIdent, pState))
+ where
+ make_ident :: (Optional Ident) ParseState -> (Ident, ParseState)
+ make_ident (Yes ident) pState
+ = (ident, pState)
+ make_ident No pState
+ = internalIdent "s;" pState
+
+ sub_update :: NestedUpdate -> NestedUpdate
+ sub_update update=:{nu_selectors}
+ = {update & nu_selectors = tl nu_selectors}
+ transform_update _ (_, pState)
+ # pState
+ = parseError "record or array" No "field assignments mixed with array assignments not" /* expected */ pState
+ = ({bind_dst = errorIdent, bind_src = PE_Empty}, (No, pState))
+
+ build_update :: (Optional Ident) ParsedExpr [FieldAssignment] -> ParsedExpr
+ build_update No expr assignments
+ = PE_Record expr No assignments
+ build_update (Yes ident) expr assignments
+ = PE_Let False (LocalParsedDefs [buildNodeDef (PE_Ident ident) expr])
+ (PE_Record (PE_Ident ident) No assignments)
+
+ transform_array_update :: ParsedExpr [NestedUpdate] ParseState -> (ParsedExpr, ParseState)
+ transform_array_update expr updates pState
+ // transform {<e> & [i].<...> = e1, ... } to {{<e> & [i1].<...> = e1} & ...}
+ = foldSt transform_update updates (expr, pState)
+ where
+ transform_update :: NestedUpdate (ParsedExpr, ParseState) -> (ParsedExpr, ParseState)
+ transform_update {nu_selectors, nu_update_expr} (expr1, pState)
+ = build_update expr1 (split_selectors nu_selectors) nu_update_expr pState
+ where
+ // split selectors into final record selectors and initial selectors
+ // (resulting selectors are reversed)
+ // for example: [i1].[i2].f.[i3].g.h -> (h.g, [i3].f.[i2].[i1])
+ split_selectors selectors
+ = span is_record_select (reverse selectors)
+
+ build_update :: ParsedExpr ([ParsedSelection], [ParsedSelection]) ParsedExpr ParseState -> (ParsedExpr, ParseState)
+ build_update expr ([], initial_selectors) update_expr pState
+ = (PE_Update expr (reverse initial_selectors) update_expr, pState)
+ // transform {<e> & <...>.[i].f.g. = e1} to
+ // let
+ // index_id = i
+ // (element_id, array_id) = <e>!<...>.[index_id]
+ // in {array_id & [index_id] = {element_id & f.g = e1}}
+ build_update expr (record_selectors, [PS_Array index : initial_selectors]) update_expr pState
+ # (index_id, pState)
+ = internalIdent "i;" pState
+ # (element_id, pState)
+ = internalIdent "e;" pState
+ # (array_id, pState)
+ = internalIdent "a;" pState
+ index_def
+ = buildNodeDef (PE_Ident index_id) index
+ select_def
+ = buildNodeDef
+ (PE_Tuple [PE_Ident element_id, PE_Ident array_id])
+ (PE_Selection cUniqueSelection expr (reverse [PS_Array (PE_Ident index_id) : initial_selectors]))
+ (updated_element, pState)
+ = transform_record_update
+ (PE_Ident element_id)
+ [[{nu_selectors=(reverse record_selectors), nu_update_expr=update_expr}]] pState
+ = (PE_Let False
+ (LocalParsedDefs [index_def, select_def])
+ (PE_Update (PE_Ident array_id) (reverse [PS_Array (PE_Ident index_id) : initial_selectors]) updated_element), pState)
+
+ want_field_assignments is_pattern token=:(IdentToken ident) pState
+ | isLowerCaseName ident
+ # (field, pState) = want_field_expression is_pattern ident pState
+ (token, pState) = nextToken FunctionContext pState
+ | token == CommaToken
+ # (token, pState) = nextToken FunctionContext pState
+ (fields, pState) = want_field_assignments is_pattern token pState
+ = ([ field : fields ], pState)
+ = ([ field ], tokenBack pState)
+ where
+ want_field_expression is_pattern ident pState
+ # (field_id, pState) = stringToIdent ident IC_Selector pState
+ (token, pState) = nextToken FunctionContext pState
+ | token == EqualToken
+ # (field_expr, pState) = wantExpression is_pattern pState
+ = ({ bind_src = field_expr, bind_dst = field_id}, pState)
+ = ({ bind_src = PE_Empty, bind_dst = field_id}, tokenBack pState)
+ want_field_assignments is_pattern token pState
+ = ([], parseError "record or array field assignments" (Yes token) "field name" pState)
+
+ try_field_assignment (IdentToken ident) pState
+ | isLowerCaseName ident
+ # (token, pState) = nextToken FunctionContext pState
+ | token == EqualToken
+ # (field_expr, pState) = wantExpression cIsNotAPattern pState
+ (field_id, pState) = stringToIdent ident IC_Selector pState
+ = (True, { bind_src = field_expr, bind_dst = field_id}, pState)
+ = (False, abort "no field", tokenBack pState)
+ = (False, abort "no field", pState)
+ try_field_assignment _ pState
+ = (False, abort "no field", pState)
+
+ want_record type pState
+ # (token1, pState) = nextToken FunctionContext pState
+ (token2, pState) = nextToken FunctionContext pState
+ | isDefinesFieldToken token2
+ # (fields, pState) = want_field_assignments cIsNotAPattern token1 (tokenBack pState)
+ = (PE_Record PE_Empty type fields, wantToken FunctionContext "record" CurlyCloseToken pState)
+ = want_record_update type token1 (tokenBack pState)
+ where
+ want_record_update :: !(Optional Ident) !Token !ParseState -> (!ParsedExpr, !ParseState)
+ want_record_update type token pState
+ # (expr, pState) = wantRhsExpressionT token pState
+ pState = wantToken FunctionContext "record update" AndToken pState
+ (token, pState) = nextToken FunctionContext pState
+ = want_update expr token pState
+
+ want_update :: !ParsedExpr !Token !ParseState -> (!ParsedExpr, !ParseState)
+ want_update exp token pState
+ # (update_expr, pState) = want_updates token exp pState
+ // (qualifiers, pState) = try_qualifiers pState // Bug: for RWS
+ = (update_expr, wantToken FunctionContext "record update" CurlyCloseToken pState)
+ where
+ try_qualifiers pState
+ # (token, pState) = nextToken FunctionContext pState
+ | token == DoubleBackSlashToken
+ = wantQualifiers 0 0 pState
+ = ([], tokenBack pState)
+
+ want_record_or_array_update token expr pState
+ = want_update expr token pState
+
+ want_array_assignments is_pattern pState
+ # (assign, pState) = want_array_assignment is_pattern pState
+ (token, pState) = nextToken FunctionContext pState
+ | token == CommaToken
+ # pState = wantToken FunctionContext "array assignments" SquareOpenToken pState
+ (assigns, pState) = want_array_assignments is_pattern pState
+ = ([ assign : assigns ], pState)
+ = ([ assign ], tokenBack pState)
+ where
+ want_array_assignment is_pattern pState
+ # (index_exp, pState) = wantExpression cIsNotAPattern pState
+ pState = wantToken FunctionContext "array assignment" SquareCloseToken pState
+ pState = wantToken FunctionContext "array assignment" EqualToken pState
+ (pattern_exp, pState) = wantExpression is_pattern pState
+ = ({bind_dst = index_exp, bind_src = pattern_exp}, pState)
+
+/**
+ End of definitions
+**/
+
+skipToEndOfDefinition :: !ParseState -> (!Token, !ParseState)
+skipToEndOfDefinition pState
+ # (token, pState) = nextToken FunctionContext pState
+ = case token of
+ NewDefinitionToken -> (token, pState)
+ EndGroupToken -> (token, pState)
+ EndOfFileToken -> (token, pState)
+// SemicolonToken -> (token, pState) // might be useful in non layout mode.
+ _ -> skipToEndOfDefinition pState -->> (token,"skipped")
+
+wantEndOfDefinition :: String !ParseState -> ParseState
+wantEndOfDefinition msg pState=:{ps_skipping}
+ | ps_skipping
+ # (token, pState) = skipToEndOfDefinition {pState & ps_skipping = False}
+ // (pos,pState) = getPosition pState // for debugging
+ = want_end_of_definition token msg pState //-->> ("restart parsing at ",token, pos)
+ # (token, pState) = nextToken FunctionContext pState
+ = want_end_of_definition token msg pState
+where
+ want_end_of_definition :: !Token String !ParseState -> ParseState
+ want_end_of_definition token msg pState
+ # (ss_useLayout, pState) = accScanState UseLayout pState
+ | ss_useLayout
+ = case token of
+ NewDefinitionToken -> pState // -->> "end of definition found due to NewDefinitionToken"
+ EndOfFileToken -> tokenBack pState // -->> "end of definition found due to EndOfFileToken"
+ EndGroupToken -> tokenBack pState // -->> "end of definition found due to EndGroupToken"
+ InToken -> tokenBack pState // -->> "end of definition found due to InToken"
+ WhereToken -> tokenBack pState // -->> "end of definition found due to WhereToken"
+ BarToken -> tokenBack pState // -->> "end of definition found due to BarToken"
+ EqualToken -> tokenBack pState // -->> "end of definition found due to EqualToken"
+ ArrowToken -> tokenBack pState // -->> "end of definition found due to ArrowToken"
+ SeqLetToken _ -> tokenBack pState // -->> "end of definition found due to SeqLetToken"
+ SemicolonToken # (token, pState) = nextToken FunctionContext pState
+ -> case token of
+ NewDefinitionToken -> pState // -->> "end of definition found due to SemicolonToken and NewDefinitionToken"
+ _ -> tokenBack pState// -->> "end of definition found due to SemicolonToken"
+ token -> wantEndOfDefinition "" (parseError msg (Yes token) "end of definition" pState)
+ // otherwise // ~ ss_useLayout
+ = case token of
+ CurlyCloseToken -> tokenBack pState
+ SemicolonToken -> pState
+ EndOfFileToken -> tokenBack pState // -->> "end of definition found due to EndOfFileToken"
+ token -> wantEndOfDefinition "" (parseError msg (Yes token) "end of definition" pState)
+
+wantEndRootExpression :: !ParseState -> ParseState
+wantEndRootExpression pState=:{ps_skipping}
+ | ps_skipping
+ = wantEndOfDefinition "root expression" pState
+ # (token, pState) = nextToken FunctionContext pState
+ (ss_useLayout, pState) = accScanState UseLayout pState
+ | ss_useLayout
+ = case token of
+ NewDefinitionToken -> pState
+ EndOfFileToken -> tokenBack pState
+ EndGroupToken -> tokenBack pState
+ EqualToken -> tokenBack pState
+ ArrowToken -> tokenBack pState
+ WhereToken -> tokenBack pState
+ WithToken -> tokenBack pState
+ BarToken -> tokenBack pState
+ InToken -> tokenBack pState
+ CloseToken -> tokenBack pState
+ (SeqLetToken _) -> tokenBack pState
+ SemicolonToken # (token, pState) = nextToken FunctionContext pState
+ -> case token of
+ NewDefinitionToken -> pState
+ _ -> tokenBack pState
+ token -> wantEndOfDefinition "root expression" (parseError "root expression" (Yes token) "end of root expression" pState)
+ // otherwise // ~ ss_useLayout
+ = case token of
+ SemicolonToken -> pState
+ CurlyCloseToken -> tokenBack pState
+ EqualToken -> tokenBack pState // Do we really want to allow all of these tokens
+ ArrowToken -> tokenBack pState
+ (SeqLetToken _) -> tokenBack pState
+ WhereToken -> tokenBack pState
+ WithToken -> tokenBack pState
+ BarToken -> tokenBack pState
+ EndOfFileToken -> tokenBack pState
+ token -> wantEndOfDefinition "root expression" (parseError "root expression" (Yes token) "end of root expression" pState)
+
+wantEndGroup :: String !ParseState -> ParseState
+wantEndGroup msg pState
+ # (token, pState) = nextToken FunctionContext pState
+ | token == EndOfFileToken
+ = tokenBack pState
+ # (ss_useLayout, pState) = accScanState UseLayout pState
+ | ss_useLayout
+ = case token of
+ EndGroupToken -> pState
+ _ -> parseError msg (Yes token) "end of group with layout" pState
+ // ~ ss_useLayout
+ | token == CurlyCloseToken
+ = pState
+ // otherwise // token <> CurlyCloseToken
+ = parseError msg (Yes token) "end of group without layout, }," pState
+
+wantEndModule :: !ParseState -> ParseState
+wantEndModule pState
+ # (token, pState) = nextToken FunctionContext pState
+ | token == EndOfFileToken
+ = tokenBack pState
+ # (ss_useLayout, pState) = accScanState UseLayout pState
+ | ss_useLayout && token == EndGroupToken
+ = pState
+ = parseError "Definition" (Yes token) "Unexpected token in input: definition" pState
+
+wantEndNestedGuard :: !Bool !Int !ParseState -> ParseState
+wantEndNestedGuard defaultFound offside pState
+ | ~ defaultFound
+ = parseError "nested guards" No "sorry, but for the time being there is a default alternative for nested guards" pState
+ # (token, pState) = nextToken FunctionContext pState
+ | token == EndOfFileToken
+ = tokenBack pState
+ # (ss_useLayout, pState) = accScanState UseLayout pState
+ | ss_useLayout
+ # ({fp_col}, pState) = getPosition pState
+ | fp_col < offside || (end_Nested_Guard token && fp_col == offside)
+ = tokenBack pState
+ // otherwise
+ = parseError "nested guards" (Yes token) "=, ->, | or # at offside position, or end of function definition" pState
+ // ~ ss_useLayout
+ | token == SemicolonToken
+ = pState
+ | defaultFound
+ = tokenBack pState
+ // otherwise
+ = parseError "nested guards" (Yes token) "End of nested guards, ;," pState
+where
+ end_Nested_Guard EqualToken = True
+ end_Nested_Guard BarToken = True
+ end_Nested_Guard ArrowToken = True
+ end_Nested_Guard (SeqLetToken _) = True
+ end_Nested_Guard _ = False
+
+wantEndLocals :: !ParseState -> ParseState
+wantEndLocals pState
+ # (ss_useLayout, pState) = accScanState UseLayout pState
+ (token, pState) = nextToken FunctionContext pState
+ | token == EndOfFileToken
+ = tokenBack pState
+ | ss_useLayout
+ = case token of
+ EndGroupToken -> pState
+ _ -> parseError "local definitions" (Yes token) "end of locals with layout" pState
+ // ~ ss_useLayout
+ | token == CurlyCloseToken
+ # (token, pState) = nextToken FunctionContext pState
+ | token == SemicolonToken
+ = pState
+ = tokenBack pState
+ // otherwise // token <> CurlyCloseToken
+ = parseError "local definitions" (Yes token) "end of locals without layout, }," pState
+
+wantEndCase :: !ParseState -> ParseState
+wantEndCase pState
+ # (ss_useLayout, pState) = accScanState UseLayout pState
+ (token, pState) = nextToken FunctionContext pState
+ | token == EndOfFileToken
+ = tokenBack pState
+ | ss_useLayout
+ = case token of
+ EndGroupToken -> pState
+ CloseToken -> tokenBack (appScanState dropOffsidePosition pState)
+ SquareCloseToken -> tokenBack (appScanState dropOffsidePosition pState)
+ SemicolonToken -> tokenBack (appScanState dropOffsidePosition pState)
+ _ -> parseError "case expression" (Yes token) "end of case with layout" pState
+ // ~ ss_useLayout
+ | token == CurlyCloseToken
+ = pState
+ // otherwise // token <> CurlyCloseToken
+ = parseError "case expression" (Yes token) "end of group without layout, }," pState
+
+wantBeginGroup :: String !ParseState -> ParseState
+wantBeginGroup msg pState
+ # (ss_useLayout, pState) = accScanState UseLayout pState
+ | ss_useLayout
+ = pState
+ // otherwise // ~ ss_uselayout
+ # (token, pState) = nextToken FunctionContext pState
+ = case token of
+ CurlyOpenToken
+ -> pState
+ _ -> parseError msg (Yes token) "begin group without layout, {," pState
+
+/*
+ Functions on the parse pState
+*/
+/*
+instance insertToken ParseState
+where
+ insertToken t c pState = appScanState (insertToken t c) pState
+
+instance currentToken ParseState
+where
+ currentToken pState = accScanState currentToken pState
+*/
+instance replaceToken ParseState
+where
+ replaceToken t pState = appScanState (replaceToken t) pState
+
+instance tokenBack ParseState
+where
+ tokenBack pState=:{ps_skipping}
+ | ps_skipping
+ = pState
+ = appScanState tokenBack pState
+
+instance nextToken ParseState
+where
+ nextToken :: !Context !ParseState -> (!Token, !ParseState)
+ nextToken context pState
+ | pState.ps_skipping // in error recovery from parse error
+ = (ErrorToken "Skipping", pState)
+ = accScanState (nextToken context) pState
+
+instance getPosition ParseState
+where
+ getPosition pState = accScanState getPosition pState
+
+parseWarning :: !{# Char} !{# Char} !ParseState -> ParseState
+parseWarning act msg pState
+ | pState.ps_skipping
+ = pState
+ | otherwise // not pState.ps_skipping
+ # (pos,pState) = getPosition pState
+ (filename,pState=:{ps_error={pea_file,pea_ok}}) = accScanState getFilename pState
+ pea_file = pea_file
+ <<< "Parse warning ["
+ <<< filename <<< ","
+ <<< pos
+ <<< (if (size act > 0) ("," + act) "") <<< "]: "
+ <<< msg
+ <<< "\n"
+ = { pState
+ & ps_error = { pea_file = pea_file, pea_ok = pea_ok }
+ }
+
+parseError :: !{# Char} !(Optional Token) !{# Char} !ParseState -> ParseState
+parseError act opt_token msg pState
+ | pState.ps_skipping
+ = pState
+ | otherwise // not pState.ps_skipping
+ # (pos,pState) = getPosition pState
+ (filename,pState=:{ps_error={pea_file}}) = accScanState getFilename pState
+ pea_file = pea_file
+ <<< "Parse error ["
+ <<< filename <<< ","
+ <<< pos
+ <<< (if (size act > 0) ("," + act) "") <<< "]: "
+ <<< msg
+ pea_file = case opt_token of
+ Yes token -> pea_file <<< " expected instead of " <<< token <<< "\n"
+ No -> pea_file <<< " expected\n"
+ pState = { pState
+ & ps_skipping = True
+ , ps_error = { pea_file = pea_file, pea_ok = False }
+ }
+ = case opt_token of
+ Yes _ -> tokenBack pState
+ No -> pState
+
+getFileAndLineNr :: !ParseState -> (!String, !Int, !ParseState)
+getFileAndLineNr pState =: {ps_scanState}
+ # (filename,scanState) = getFilename ps_scanState
+ ({fp_line},scanState) = getPosition scanState
+ = (filename, fp_line, {pState & ps_scanState = scanState} )
+
+/*
+ Simple parse functions
+*/
+
+wantToken :: !Context !{#Char} !Token !ParseState -> ParseState
+wantToken context act dem_token pState
+ # (token, pState) = nextToken context pState
+ | dem_token == token
+ = pState // -->> (token,"wanted and consumed")
+ = parseError act (Yes token) (toString dem_token) pState
+
+instance want Priority
+where
+ want pState
+ # (token, pState) = nextToken FunctionContext pState
+ = case token of
+ PriorityToken prio
+ -> (prio, pState)
+ _
+ -> (NoPrio, parseError "Priority" (Yes token) "with" pState)
+
+instance want {# Char}
+where
+ want pState
+ # (token, pState) = nextToken GeneralContext pState
+ = case token of
+ IdentToken name -> (name, pState)
+ _ -> ("", parseError "String" (Yes token) "identifier" pState)
+
+tryTypeVar :: !ParseState -> (!Bool, TypeVar, !ParseState)
+tryTypeVar pState
+ # (token, pState) = nextToken TypeContext pState
+ = tryTypeVarT token pState
+
+tryTypeVarT :: !Token !ParseState -> (!Bool, TypeVar, !ParseState)
+tryTypeVarT (IdentToken name) pState
+ | isUpperCaseName name
+ = (False, abort "no UC ident", pState)
+ # (id, pState) = stringToIdent name IC_Type pState
+ = (True, MakeTypeVar id, pState)
+tryTypeVarT token pState
+ = (False, abort "no type variable", tokenBack pState)
+
+wantUpperCaseName :: !String !ParseState -> (!String, !ParseState)
+wantUpperCaseName string pState
+ # (token, pState) = nextToken GeneralContext pState
+ = case token of
+ IdentToken name
+ | isUpperCaseName name
+ -> (name, pState)
+ _
+ -> ("dummy uppercase name", parseError string (Yes token) "upper case ident" pState)
+
+wantLowerCaseName :: !String !ParseState -> (!String, !ParseState)
+wantLowerCaseName string pState
+ # (token, pState) = nextToken GeneralContext pState
+ = case token of
+ IdentToken name
+ | isLowerCaseName name
+ -> (name, pState)
+ _
+ -> ("dummy lowercase name", parseError string (Yes token) "lower case ident" pState)
+
+wantConstructorName :: !String !ParseState -> (!String, !ParseState)
+wantConstructorName string pState
+ # (token, pState) = nextToken GeneralContext pState
+ = case token of
+ IdentToken name
+ | isUpperCaseName name || isFunnyIdName name
+ -> (name, pState)
+ _
+ -> ("", parseError string (Yes token) "upper case ident" pState)
+
+/*
+isTypeStartToken :: ! Token -> Bool
+isTypeStartToken (IdentToken id) = True
+isTypeStartToken SquareOpenToken = True
+isTypeStartToken CurlyOpenToken = True
+isTypeStartToken OpenToken = True
+isTypeStartToken IntTypeToken = True
+isTypeStartToken CharTypeToken = True
+isTypeStartToken BoolTypeToken = True
+isTypeStartToken VoidTypeToken = True
+isTypeStartToken StringTypeToken = True
+isTypeStartToken RealTypeToken = True
+isTypeStartToken DynamicTypeToken = True
+isTypeStartToken ExclamationToken = True
+isTypeStartToken DotToken = True
+isTypeStartToken AsteriskToken = True
+isTypeStartToken token = False
+
+isIdentToken :: ! Token -> Bool
+isIdentToken (IdentToken id) = True
+isIdentToken t = False
+
+isTypeDefToken :: ! Token -> Bool
+isTypeDefToken DoubleColonToken = True
+isTypeDefToken token = False
+
+isDefinesTypeToken :: !Token -> Bool
+isDefinesTypeToken EqualToken = True
+isDefinesTypeToken ColonDefinesToken = True
+isDefinesTypeToken token = False
+
+isUpperCaseIdent :: ! Token -> Bool
+isUpperCaseIdent (IdentToken name) = isUpperCaseName name
+isUpperCaseIdent token = False
+*/
+isDefinesFieldToken :: ! Token -> Bool
+isDefinesFieldToken EqualToken = True
+isDefinesFieldToken CurlyCloseToken = True
+isDefinesFieldToken CommaToken = True
+isDefinesFieldToken token = False
+
+ //---------------//
+ //--- Tracing ---//
+//---------------//
+
+(-->>) val _ :== val
+//(-->>) val message :== val ---> ("Parser",message)