Index: doc/proposals/exceptions-pab.md
===================================================================
--- doc/proposals/exceptions-pab.md	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
+++ doc/proposals/exceptions-pab.md	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
@@ -0,0 +1,346 @@
+# Exception Handling Changes
+
+This proposal changes the C&forall; exception handling mechanism from matching an object type to a function type.
+Using functions fits with function overloading in the C&forall; type system.
+
+The following shows a resumption example.
+
+```
+exception int resumpt( int, double );		// return result, no stack unwinding
+try {
+	i = resumpt( 3, 3.5 );					// exception raise
+} catch( int resumpt( int i, double d ) {	// i = 3, d = 3.5
+	... return 42;		 					// return value to raise point
+}
+```
+
+The following shows a termination example.
+
+```
+exception void termin( double );			// void return, stack unwinding
+try {
+	termin( 3.5 );							// exception raise
+} catch( void termin( int i, double d ) {	// i = 3, d = 3.5
+	...										// fall through to lexical block
+}
+```
+
+There is no explicit *raise* statement.
+(See Mesa Language Manual page 135, footnote)
+The compiler knows a function is an exception, so it does a search call (propagation) instead of a branch call.
+
+An exception function is denoted by the `exception` keyword to differentiate it from a regular function.
+An exception function is defined in a `catch` clause, which is a local, inline implementation of the exception function.
+The catch clause must specify the exception-function name and type for matching, and arbitrary parameter names to access the raise arguments.
+Data is carried from the raise call to the `catch` body via the argument/parameter mechanism, and data can be returned to the raise call via function return.
+An exception function cannot be passed as a function pointer nor can a raise use a pointer to an exception function.
+
+Overloading of the exception raise occurs among existing exception functions.
+
+```
+exception int fix( int, double );
+exception double fix( int, double );
+exception double fix( double );
+try {
+	int i = fix ( 3, 3.5 );					// choose best overloading
+} catch( int fix( int i, double d ) ) {		// match with exact catch body
+} catch( double fix( int i, double d ) ) {
+} catch( double fix( double d ) ) {
+}
+```
+
+Normal overload resolution occur at the raise point, where the best fit *exception* function is chosen based on arguments and left-hand side.
+Matching between raise and catch is exact, as for function pointers, with the selected overload chosen at the raise point (compare mangled names dynamically)
+
+An exception function has a *kind*: return, noreturn, or dual, denoting resumption, termination, or both.
+An exception function cannot be overloaded on the exception kind.
+A return exception function must return a type, a noreturn exception function must return `void`, a dual exception function must return a type.
+A dual exception function is specified using the quasi-keyword `dual`.
+
+```
+exception int dual( int, double ) dual;		// Dual, return result or exit handler block,
+											// no initial stack unwinding
+```
+
+Within the handler for kind return (stack not unwound), the handler *must* return a value as for any value returning function;
+any other control-flow statement or fallthrough is an error, like `break` or fallthrough on a value returning function.
+
+```
+	} catch( int fix( int i, float j ) ) {	// stack not unwound, i/j accessible, => must return
+		return 42;							// => return to fix call, not return of lexical function
+		break;								// syntax error => must return
+		// fallthrough => must return
+	}
+```
+
+Within the handler for kind noreturn (stack unwound), `break` or fallthrough &rArr; exit handler, like in the `case` clause of a switch statement;
+any other control-flow statement works on the lexical context outside the handler.
+
+```
+	} catch( void recover( int i ) ) {		// stack unwound, cannot return
+		break;								// => exit catch routine
+		return;								// => return from lexical function
+		// fallthrough => => break
+	}
+```
+
+Within the handler for kind dual (stack not unwound), `break` or fallthrough &rArr; exit handler and unwind stack, or return a value to the raise at top of the stack.
+
+```
+	} catch( int dual( int i, float j ) ) {	// stack not unwound, can return
+		return 42;							// => return to fix call, not return of nested function
+		break;								// => exit catch body
+		// fallthrough => break
+	}
+```
+
+In all cases, a handler can raise another exception.
+
+Resumption example:
+
+```
+exception int fix( int, float );
+void foo() {
+	try {
+		for () {
+			... if ( ... ) x = fix( 3, 5.4 ); ...
+		}
+	} catch( int fix( int i, float f ) ) {
+		... return 42;						// fix up problem and return to raise
+	}
+}
+```
+
+Termination example:
+
+```
+exception void end_of_file( ifstream is );
+void foo() {
+	int i;
+	try {
+		for () {
+			sin | i;			// internally, calls end_of_file( is ) to raise exception
+			sout | i;
+		}
+	} catch( end_of_file( ifstream is ) && is == sin ) { // "is" used in predicate selection
+		// close file
+	}
+}
+```
+
+Dual example:
+
+```
+exception int dual( int i, float ) dual;
+void baz() {
+	try {
+		for () {
+			if ( ... ) x = dual( 3, 5.4 );
+		}
+	} catch( int dual( int i, float f ) ) {	// stack not unwound
+		if ( ... ) return 42;				// return to raise calls
+		if ( ... ) break;					// exit catch body
+		// fallthrough => break
+	}
+}
+```
+
+
+## Default Handler
+
+An exception function can have a static body, which defines the action if the exception is not caught.
+If no body is specified, there are default actions added.
+This matches with `defaultResume` and `defaultTerminate` in current C&forall;/&mu;C++.
+Here a parameter name is necessary to access the raise argument(s).
+
+Resumption default:
+
+```
+exception int resumpt( int i ) {			// called if no handler found
+	// return default correction or abort or raise another exception
+	// default if not specified is to call UnhandledException at resumer or joiner.
+}
+```
+
+Termination default:
+
+```
+exception void termin( double d ) {			// called if no handler found
+	// abort or raise another exception
+	// default if not specified is to call UnhandledException at resumer or joiner.
+}
+```
+
+Dual default is the same as termination default, as having a default correction action is unlikely.
+
+
+## Polymorphism
+
+A catch clause can be polymorphic using the RTTI information in a mangled name.
+
+```
+forall( T | { T ?+?( T, T ); } )
+exception T foo( T t ) { return t + t; }
+
+	try (
+		i = foo( 3 );						// raise
+	} catch( int foo( int t ) ) {			// monomorphic handler
+		return t + 3 / t;					// can do something
+	} catch( forall( T | { T ?+?( T, T ) } ) T foo( T t ) ) { // polymorphic handler
+		return t + t;						// cannot do much
+	}
+
+```
+
+Matching is a pattern match on the mangled name (assuming there is enough information):
+
+```
+_X3fooQ1_0_0_5__X16_operator_assignFBD0_BD0BD0__X12_constructorFv_BD0__X12_constructorFv_BD0BD0
+	__X11_destructorFv_BD0__X13_operator_addFBD0_BD0BD0__FBD0_BD0__1
+```
+
+
+## Separate Compilation
+
+**test.hfa**
+
+```
+typedef struct S {
+	void (*f)( int );						// general function pointer
+} S;
+
+void foo( int ) throws( E );				// external
+void bar( int ) throws( F );
+
+void mary( S & s );							// external
+void jane( S s );
+```
+
+**test2.cfa**
+
+```
+#include "test1.hfa"
+#include "stdlib.h"
+
+void foo( int ) { printf( "foo\n" ); }
+void bar( int ) { printf( "bar\n" ); }
+
+void mary( S & s ) {
+	s.f = random() % 2 ? foo : bar;			// randomly insert a function
+}
+
+void jane( S s ) {
+	s.f( 3 );								// call field f
+}
+```
+
+**test1.cfa**
+
+```
+#include "test1.hfa"
+
+int main() {
+	S sfoo;
+
+	mary( sfoo );							// initialize field f
+
+	try {
+		jane( sfoo );						// calls sfoo.f in jane
+	} catch( ... ) {}						// cannot statically check correct handler is present
+}
+```
+
+
+## `throws` Clause
+
+A `throws` clause can be added to a regular function to indicate alternate outcomes.
+
+```
+int foo(...) throws( int ex( int ), float ex( int ), char ex( double, double ) );
+```
+
+The `throws` clause is *not* part of the function type, and hence, is *not* used for overloading.
+Functions with a `throws` clause are handled by a separate type-checking pass, which examines the static call-structure to determine if calls are nested directly or indirectly within guarded blocks with matching catch clauses, e.g.:
+
+```
+int bar( int i ) throws( int fixup( int ) ); // might call fixup directly or indirectly
+
+void foo(...) {
+	... i = bar( 3 ); ...			// call statically nested within handler for fixup in baz
+}
+void baz() {
+	try {
+		foo(...);
+	} catch( int fixup( int ) ) {			// handler for bar
+		... return 42;
+	}
+}
+```
+
+If this type check fails because of separate compilation, e.g., `baz` is in a different translation unit, a warning is given, and a dynamic check is wrapped around the call to `bar` to verify only the specified exception functions are raised.
+This dual approach allows all forms of reuse to exist, and is similar to checked/unchecked exceptions in Java.
+
+
+## Polymorphism Extension
+
+A new kind of polymorphic parameter is introduced, `throws`, listing the possible empty set of exceptions (alternate outcomes) that can be raised exception, but a possibly empty set of exceptions.
+A set of exceptions can be used in an exception signature in the same way a single exception can be and are traced from callee to caller in the same way a single exception is.
+They do not interact with throws or catches as those work on concrete types.
+At the top and bottom of the polymorphic call stack concrete functions throw and catch the exception, passing through the polymorphic section. 
+
+```
+forall( T, [N], throws E )
+	void apply( void op(T &) throws(E), array(T, N) & data ) throws(E) {
+		for ( i; N ) op( data[i] );
+}
+```
+Given the concrete usage:
+
+```
+void op( int ) throws( void WWW( int ), Y, Z ) { ... }
+array( int, 10 ) arr;
+try {
+	 apply( op, arr ); // op(... ) => if (... ) WWW(...)
+} catch( void WWW( int ) ) { ... // apply can raise from op
+} catch( exception Y ) { ... // apply can raise from op
+} catch( exception Z ) { ... // apply can raise from op
+}
+```
+
+The call to `apply` composes a list of all potential exceptions thrown by arguments.
+
+Imagine we passed around a set description (a list of type identities for each exception in the set) and at the edges of the polymorphic space we check for an unknown exception type against these sets.
+The static checks should ensure that every exception falls into one set;
+in fact if there is only one knows set we know it must belong to it.
+Then we wrap it up with a little marker saying which set it is part of and which one in the set it is.
+That gets passed through as an opaque exception until we return to monomorphic code, then it is unpacked and passed normally.
+
+
+## More Examples
+
+```
+enum FloatExceptions ! { Invalid, ZeroDiv, Overflow, Underflow, Inexact };
+exception double arithmetic( double op1, double op2, int retcode ) {
+	// default abort
+}
+enum IntExceptions ! { ZeroDiv, Overflow, Underflow };
+exception double arithmetic( int op1, int op2, int retcode ) {
+	// default abort
+}
+
+void foo() {
+	double x = 3.5;
+	try {
+		x = x / 0.0;
+	} catch( double arithmetic( double op1, double op2, int retcode ) ) {
+		if ( retcode == FloatExceptions.ZeroDiv ) ...	// analyze retcode
+	}
+
+	int i = 3;
+	try {
+		i = i / 0;
+	} catch( double arithmetic( int op1, int op2, int retcode ) ) {
+		if ( retcode == IntExceptions.ZeroDiv ) ...		// analyze retcode
+	}
+}
+```
Index: doc/proposals/modules-alvin/3_implementation_details/meta.md
===================================================================
--- doc/proposals/modules-alvin/3_implementation_details/meta.md	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
+++ doc/proposals/modules-alvin/3_implementation_details/meta.md	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
@@ -0,0 +1,5 @@
+At this point in development, there are enough ideas from my previous writeups that the questions "can it be done?" and "what are the tradeoffs?" are clear enough to start implementing.
+
+Now, the focus is on explaining the ideas succinctly and considering the order in which to implement features (some features require adding capabilities that are much harder to implement). As such, I'll be using this space to organize all these ideas into a suitable narrative, with accompanying code and examples.
+
+The prototype code described in today's meeting is in `prototype/`.
Index: doc/proposals/modules-alvin/3_implementation_details/prototype/Driver.py
===================================================================
--- doc/proposals/modules-alvin/3_implementation_details/prototype/Driver.py	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
+++ doc/proposals/modules-alvin/3_implementation_details/prototype/Driver.py	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
@@ -0,0 +1,266 @@
+import argparse
+import os
+from pprint import pprint
+from antlr4 import *
+from parser.CMODLexer import CMODLexer
+from parser.CMODParser import CMODParser
+
+def parse_args():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("input_file", help="file to parse")
+    parser.add_argument("-r", "--project_root", help="the root folder of the project, used to find imported modules. All modules, including imports, should be within this folder")
+    args = parser.parse_args()
+    return args
+
+def main():
+    args = parse_args()
+    generate_code(args)
+
+def generate_code(args):
+    # args.input_file
+    # args.project_root
+
+    # This changes the OS directory to be project_root, and removes the suffix from input_file
+    # (output: input_module)
+    input_file = os.path.relpath(args.input_file, args.project_root)
+    os.chdir(args.project_root)
+    dot_index = input_file.rfind('.')
+    if dot_index < 0 or input_file[dot_index:] != '.cmod':
+        raise RuntimeError("input_file must use .cmod suffix")
+    input_module = input_file[:dot_index]
+
+    # Parses AST of a given module
+    # (output: get_module_info())
+    module_asts = {}  # dict[module_name: str, (text: str, tokens, tree)]
+    def get_module_info(module_name: str):
+        def insert_module_info(module_name):
+            input_stream = FileStream(module_name + ".cmod")
+            text = str(input_stream)
+            lexer = CMODLexer(input_stream)
+            tokens = lexer.getAllTokens()  # list[token: {text, start, stop, line, column}]
+                                           # stop is inclusive, just like getSourceInterval
+            lexer.reset()
+            stream = CommonTokenStream(lexer)
+            parser = CMODParser(stream)
+            tree = parser.compilationUnit()  # {getSourceInterval, getChildren, getChildCount, getChild, getText}
+            if parser.getNumberOfSyntaxErrors() > 0:
+                # Let it keep going with errors
+                print(f"// ERROR: syntax errors for file {module_name}")
+            module_asts[module_name] = text, tokens, tree
+
+        if module_name not in module_asts:
+            insert_module_info(module_name)
+        return module_asts[module_name]
+
+    # Gets imports of module
+    # (output: get_imports())
+    module_imports = {}  # dict[module_name: str, list[module_name: str]]
+    def get_imports(module_name: str):
+        def insert_imports(module_name):
+            _, _, tree = get_module_info(module_name)
+            import_names = []  # list[module_name: str]
+            for importDeclaration in tree.translationUnit().importDeclaration():
+                import_names.append(importDeclaration.Identifier().getText())
+            module_imports[module_name] = import_names
+
+        if module_name not in module_imports:
+            insert_imports(module_name)
+        return module_imports[module_name]
+
+    # Gets info for symbols of module
+    # (output: get_symbol_list())
+    module_symbols = {}  # dict[module_name: str, list[(symbol_name: str, idx: int, exported: bool)]]
+    def get_symbol_list(module_name: str):
+        def insert_symbol_list(module_name):
+            _, _, tree = get_module_info(module_name)
+            symbol_list = []  # list[(symbol_name: str, idx: int, exported: bool)]
+            for idx, externalDeclaration in enumerate(tree.translationUnit().externalDeclaration()):
+                exported = externalDeclaration.getChild(0).getText() == 'export'
+                structDefinition = externalDeclaration.structDefinition()
+                globalDefinition = externalDeclaration.globalDefinition()
+                functionDefinition = externalDeclaration.functionDefinition()
+                if structDefinition:
+                    symbol_name = structDefinition.Identifier().getText()
+                elif globalDefinition:
+                    symbol_name = globalDefinition.declarator().Identifier().getText()
+                elif functionDefinition:
+                    symbol_name = functionDefinition.declarator().Identifier().getText()
+                symbol_list.append((symbol_name, idx, exported))
+            module_symbols[module_name] = symbol_list
+
+        if module_name not in module_symbols:
+            insert_symbol_list(module_name)
+        return module_symbols[module_name]
+
+    # Gets info for symbols via lookup
+    # (output: lookup_symbol())
+    module_lookup = {}  # dict[parent_module_name: str, dict[symbol_name: str, (module_name: str, idx: int)]]
+    def lookup_symbol(parent_module_name: str, symbol_name: str) -> tuple[str, int] | None:
+        def generate_symbol_table(parent_module_name):
+            symbol_table = {}  # dict[symbol_name: str, (module_name: str, idx: int)]
+            def add_to_symbol_table(symbol_name, module_name, idx):
+                if symbol_name in symbol_table:
+                    # Let it keep going with errors
+                    print(f"// ERROR: symbol name clash for {symbol_name}")
+                else:
+                    symbol_table[symbol_name] = module_name, idx
+            for symbol_name, idx, _ in get_symbol_list(parent_module_name):
+                add_to_symbol_table(symbol_name, parent_module_name, idx)
+            for module_name in get_imports(parent_module_name):
+                for symbol_name, idx, exported in get_symbol_list(module_name):
+                    if exported:
+                        add_to_symbol_table(symbol_name, module_name, idx)
+            module_lookup[parent_module_name] = symbol_table
+
+        if parent_module_name not in module_lookup:
+            generate_symbol_table(parent_module_name)
+        if symbol_name in module_lookup[parent_module_name]:
+            return module_lookup[parent_module_name][symbol_name]
+        else:
+            # if symbol not found, hopefully it's fine
+            return None
+
+    # Generate the supporting code for a given symbol definition
+    # (output: codegen())
+    visited = {}  # dict[(module_name: str, idx: int), is_defn: bool]
+    visiting = set()  # set[(module_name: str, idx: int)]
+    def codegen(parent_module_name: str, idx: int, needs_defn: bool):
+        def codegen_type_info(typeSpecifier, uses_defn):
+            struct_identifier = typeSpecifier.Identifier()
+            if not struct_identifier:
+                return
+            res = lookup_symbol(parent_module_name, struct_identifier.getText())
+            if not res:
+                return
+            module_name, idx = res
+            codegen(module_name, idx, uses_defn)
+        def codegen_expression_info(expression):
+            for expr in expression.expression():
+                codegen_expression_info(expr)
+            typeSpecifier = expression.typeSpecifier()
+            if typeSpecifier:
+                codegen_type_info(typeSpecifier, expression.getChildCount() == 1)
+            identifier = expression.Identifier()
+            if identifier:
+                res = lookup_symbol(parent_module_name, identifier.getText())
+                if res:
+                    module_name, idx = res
+                    codegen(module_name, idx, False)
+
+        if (parent_module_name, idx) in visited:
+            # Unless we now need the definition, we can skip
+            if visited[(parent_module_name, idx)] == True or not needs_defn:
+                return
+        if (parent_module_name, idx) in visiting:
+            text, tokens, tree = get_module_info(parent_module_name)
+            structDefinition = tree.translationUnit().externalDeclaration(idx).structDefinition()
+            if not needs_defn and structDefinition:
+                # Special case: can revisit struct as a declaration
+                token_start = structDefinition.getSourceInterval()[0]
+                token_end = structDefinition.Identifier().getSourceInterval()[1]
+                text_start, text_end = tokens[token_start].start, tokens[token_end].stop
+                code = text[text_start:text_end+1]
+                code += ';'
+                print(code)
+                return
+            else:
+                # Let it keep going with errors
+                print(f"// ERROR: circular reference!")
+                return
+        visiting.add((parent_module_name, idx))
+
+        # get symbol definition
+        text, tokens, tree = get_module_info(parent_module_name)
+        externalDeclaration = tree.translationUnit().externalDeclaration(idx)
+        structDefinition = externalDeclaration.structDefinition()
+        globalDefinition = externalDeclaration.globalDefinition()
+        functionDefinition = externalDeclaration.functionDefinition()
+        if structDefinition:
+            # call codegen on children
+            if needs_defn:
+                for structField in structDefinition.structField():
+                    codegen_type_info(structField.typeSpecifier(),
+                                      structField.declarator().getChildCount() == 1)
+            # print out declaration / definition
+            token_start, token_end = structDefinition.getSourceInterval()
+            if not needs_defn:
+                token_end = structDefinition.Identifier().getSourceInterval()[1]
+            text_start, text_end = tokens[token_start].start, tokens[token_end].stop
+            code = text[text_start:text_end+1]
+            if not needs_defn:
+                code += ';'
+            print(code)
+        elif globalDefinition:
+            # call codegen on children
+            codegen_type_info(globalDefinition.typeSpecifier(),
+                              globalDefinition.declarator().getChildCount() == 1)
+            if needs_defn and globalDefinition.expression():
+                codegen_expression_info(globalDefinition.expression())
+            # print out declaration / definition
+            token_start, token_end = globalDefinition.getSourceInterval()
+            if not needs_defn:
+                token_end = globalDefinition.declarator().getSourceInterval()[1]
+            text_start, text_end = tokens[token_start].start, tokens[token_end].stop
+            code = text[text_start:text_end+1]
+            if not needs_defn:
+                code = 'extern ' + code + ';'
+            print(code)
+        elif functionDefinition:
+            # call codegen on children
+            codegen_type_info(functionDefinition.typeSpecifier(),
+                              functionDefinition.declarator().getChildCount() == 1)
+            parameterList = functionDefinition.parameterList()
+            if parameterList:
+                for typeSpecifier, declarator in zip(parameterList.typeSpecifier(),
+                                                     parameterList.declarator()):
+                    codegen_type_info(typeSpecifier, declarator.getChildCount() == 1)
+            if needs_defn:
+                for statement in functionDefinition.compoundStatement().statement():
+                    codegen_expression_info(statement.expression())
+            # print out declaration / definition
+            token_start, token_end = functionDefinition.getSourceInterval()
+            if not needs_defn:
+                token_end = functionDefinition.compoundStatement().getSourceInterval()[0] - 1
+            text_start, text_end = tokens[token_start].start, tokens[token_end].stop
+            code = text[text_start:text_end+1]
+            if not needs_defn:
+                code += ';'
+            print(code)
+
+        visiting.remove((parent_module_name, idx))
+        visited[(parent_module_name, idx)] = needs_defn
+    
+    # Now drive codegen through the input module
+    _, _, tree = get_module_info(input_module)
+    for _, idx, _ in get_symbol_list(input_module):
+        codegen(input_module, idx, True)
+
+def simple_parse(input_file):
+    # Used in debugging
+    input_stream = FileStream(input_file)
+    lexer = CMODLexer(input_stream)
+    stream = CommonTokenStream(lexer)
+    parser = CMODParser(stream)
+    tree = parser.compilationUnit()
+    print(tree.getText())
+
+def details(ast):
+    # Used in debugging
+    print(f"Details for {repr(ast)}")
+    num_auto_expand = 0
+    while ast.getChildCount() == 1:
+        ast = ast.getChild(0)
+        num_auto_expand += 1
+        print(repr(ast))
+    if num_auto_expand:
+        print(f"auto expanded {num_auto_expand} times")
+    n = ast.getChildCount()
+    print(n)
+    for i in range(n):
+        print()
+        print(i)
+        print(repr(ast.getChild(i)))
+        print(ast.getChild(i).getText())
+
+if __name__ == '__main__':
+    main()
Index: doc/proposals/modules-alvin/3_implementation_details/prototype/README.md
===================================================================
--- doc/proposals/modules-alvin/3_implementation_details/prototype/README.md	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
+++ doc/proposals/modules-alvin/3_implementation_details/prototype/README.md	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
@@ -0,0 +1,13 @@
+## Generating the parser code
+
+*The PLG environment is a shared system so you can't do `pip install antlr4-tools` . Instead, run `pipx install antlr4-tools` , then `pipx ensurepath` , exit and relogin to refresh PATH, then `antlr4 -v 4.13.2` (I had to run `~/.local/share/pipx/venvs/antlr4-tools/bin/antlr4 -v 4.13.2` because the path wasn't getting picked up initially). Once this is done, you can run `antlr4` and `antlr4-parse` normally.*
+
+Using ANTLR4 (v4.13.2) to parse grammars. See https://github.com/antlr/antlr4/blob/master/doc/getting-started.md for details. Run `pip install antlr4-tools` to get `antlr4` and `anltr4-parse` executables. Example command: `antlr4-parse -v 4.13.2 parser/CMOD.g4 compilationUnit -tree testing/basic.cmod`
+
+CMOD.g4 grammar inspired by https://github.com/antlr/grammars-v4/blob/master/c/C.g4 (though heavily edited afterwards). Ran `antlr4 -v 4.13.2 -Dlanguage=Python3 parser/CMOD.g4` to generate parser code (you can add `-visitor -listener` flags for extra capabilities).
+
+## Running the code
+
+*The PLG environment is a shared system so you can't do `pip install -r requirements.txt` . Instead, create a venv with `python3 -m venv ./.venv` , then install dependencies with `./.venv/bin/pip install -r requirements.txt` . After that, you can run on example code using `./.venv/bin/python3 Driver.py -r testing testing/basic.cmod`*
+
+Adapted the steps from https://github.com/antlr/antlr4/blob/master/doc/python-target.md to generate output. Run `pip install -r requirements.txt` to get needed libraries, then `python3 Driver.py -r testing testing/basic.cmod` to run on example code.
Index: doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMOD.g4
===================================================================
--- doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMOD.g4	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
+++ doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMOD.g4	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
@@ -0,0 +1,124 @@
+// C-like language with expressions removed, used to showcase module capabilities
+
+grammar CMOD;
+
+compilationUnit
+    : translationUnit EOF
+    ;
+
+translationUnit
+    : moduleDeclaration importDeclaration* externalDeclaration*
+    ;
+
+moduleDeclaration
+    : 'module' Identifier ';'
+    ;
+
+importDeclaration
+    : 'import' Identifier ';'
+    ;
+
+externalDeclaration
+    : 'export'? structDefinition
+    | 'export'? globalDefinition
+    | 'export'? functionDefinition
+    | ';' // stray ;
+    ;
+
+structDefinition
+    : 'struct' Identifier '{' structField* '}' ';'
+    ;
+
+structField
+    : typeSpecifier declarator ';'
+    ;
+
+globalDefinition
+    : typeSpecifier declarator ('=' expression)? ';'
+    ;
+
+functionDefinition
+    : typeSpecifier declarator '(' parameterList? ')' compoundStatement
+    ;
+
+parameterList
+    : typeSpecifier declarator (',' typeSpecifier declarator)*
+    ;
+
+compoundStatement
+    : '{' statement* '}'
+    ;
+
+statement
+    : expression ';'
+    ;
+
+expression
+    // Modules doesn't need to parse expressions correctly
+    // We just need to know which symbols are used
+    // Note this is a conservative overestimate
+    : expression expression
+    | ',' | '.' | '->' | '*' | '/' | '+' | '-' | '&' | '|' | '?' | ':' | '=' | '<' | '>'
+    | '(' expression ')'
+    | '[' expression ']'
+    | '{' expression '}'
+    | StringLiteral
+    | Number
+    | typeSpecifier '*'*
+    | Identifier
+    ;
+
+typeSpecifier
+    : 'void'
+    | 'char'
+    | 'short'
+    | 'int'
+    | 'long'
+    | 'float'
+    | 'double'
+    | 'struct' Identifier
+    ;
+
+declarator
+    : '*'? Identifier
+    ;
+
+Identifier
+    : Nondigit (Nondigit | Digit)*
+    ;
+
+Number
+    : Digit+ ('.' Digit*)?
+    ;
+
+fragment Nondigit
+    : [a-zA-Z_$]
+    ;
+
+fragment Digit
+    : [0-9]
+    ;
+
+StringLiteral
+    : '"' SChar* '"'
+    ;
+
+fragment SChar
+    : ~["\r\n]
+    ;
+
+Whitespace
+    : [ \t]+ -> channel(HIDDEN)
+    ;
+
+Newline
+    : ('\r' '\n'? | '\n') -> channel(HIDDEN)
+    ;
+
+BlockComment
+    : '/*' .*? '*/' -> channel(HIDDEN)
+    ;
+
+LineComment
+    : '//' ~[\r\n]* -> channel(HIDDEN)
+    ;
Index: doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMOD.interp
===================================================================
--- doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMOD.interp	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
+++ doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMOD.interp	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
@@ -0,0 +1,104 @@
+token literal names:
+null
+'module'
+';'
+'import'
+'export'
+'struct'
+'{'
+'}'
+'='
+'('
+')'
+','
+'.'
+'->'
+'*'
+'/'
+'+'
+'-'
+'&'
+'|'
+'?'
+':'
+'<'
+'>'
+'['
+']'
+'void'
+'char'
+'short'
+'int'
+'long'
+'float'
+'double'
+null
+null
+null
+null
+null
+null
+null
+
+token symbolic names:
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+Identifier
+Number
+StringLiteral
+Whitespace
+Newline
+BlockComment
+LineComment
+
+rule names:
+compilationUnit
+translationUnit
+moduleDeclaration
+importDeclaration
+externalDeclaration
+structDefinition
+structField
+globalDefinition
+functionDefinition
+parameterList
+compoundStatement
+statement
+expression
+typeSpecifier
+declarator
+
+
+atn:
+[4, 1, 39, 188, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 5, 1, 36, 8, 1, 10, 1, 12, 1, 39, 9, 1, 1, 1, 5, 1, 42, 8, 1, 10, 1, 12, 1, 45, 9, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 3, 4, 56, 8, 4, 1, 4, 1, 4, 3, 4, 60, 8, 4, 1, 4, 1, 4, 3, 4, 64, 8, 4, 1, 4, 1, 4, 3, 4, 68, 8, 4, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 74, 8, 5, 10, 5, 12, 5, 77, 9, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 90, 8, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 98, 8, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 5, 9, 109, 8, 9, 10, 9, 12, 9, 112, 9, 9, 1, 10, 1, 10, 5, 10, 116, 8, 10, 10, 10, 12, 10, 119, 9, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 5, 12, 157, 8, 12, 10, 12, 12, 12, 160, 9, 12, 1, 12, 3, 12, 163, 8, 12, 1, 12, 1, 12, 5, 12, 167, 8, 12, 10, 12, 12, 12, 170, 9, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 3, 13, 181, 8, 13, 1, 14, 3, 14, 184, 8, 14, 1, 14, 1, 14, 1, 14, 0, 1, 24, 15, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 0, 0, 215, 0, 30, 1, 0, 0, 0, 2, 33, 1, 0, 0, 0, 4, 46, 1, 0, 0, 0, 6, 50, 1, 0, 0, 0, 8, 67, 1, 0, 0, 0, 10, 69, 1, 0, 0, 0, 12, 81, 1, 0, 0, 0, 14, 85, 1, 0, 0, 0, 16, 93, 1, 0, 0, 0, 18, 102, 1, 0, 0, 0, 20, 113, 1, 0, 0, 0, 22, 122, 1, 0, 0, 0, 24, 162, 1, 0, 0, 0, 26, 180, 1, 0, 0, 0, 28, 183, 1, 0, 0, 0, 30, 31, 3, 2, 1, 0, 31, 32, 5, 0, 0, 1, 32, 1, 1, 0, 0, 0, 33, 37, 3, 4, 2, 0, 34, 36, 3, 6, 3, 0, 35, 34, 1, 0, 0, 0, 36, 39, 1, 0, 0, 0, 37, 35, 1, 0, 0, 0, 37, 38, 1, 0, 0, 0, 38, 43, 1, 0, 0, 0, 39, 37, 1, 0, 0, 0, 40, 42, 3, 8, 4, 0, 41, 40, 1, 0, 0, 0, 42, 45, 1, 0, 0, 0, 43, 41, 1, 0, 0, 0, 43, 44, 1, 0, 0, 0, 44, 3, 1, 0, 0, 0, 45, 43, 1, 0, 0, 0, 46, 47, 5, 1, 0, 0, 47, 48, 5, 33, 0, 0, 48, 49, 5, 2, 0, 0, 49, 5, 1, 0, 0, 0, 50, 51, 5, 3, 0, 0, 51, 52, 5, 33, 0, 0, 52, 53, 5, 2, 0, 0, 53, 7, 1, 0, 0, 0, 54, 56, 5, 4, 0, 0, 55, 54, 1, 0, 0, 0, 55, 56, 1, 0, 0, 0, 56, 57, 1, 0, 0, 0, 57, 68, 3, 10, 5, 0, 58, 60, 5, 4, 0, 0, 59, 58, 1, 0, 0, 0, 59, 60, 1, 0, 0, 0, 60, 61, 1, 0, 0, 0, 61, 68, 3, 14, 7, 0, 62, 64, 5, 4, 0, 0, 63, 62, 1, 0, 0, 0, 63, 64, 1, 0, 0, 0, 64, 65, 1, 0, 0, 0, 65, 68, 3, 16, 8, 0, 66, 68, 5, 2, 0, 0, 67, 55, 1, 0, 0, 0, 67, 59, 1, 0, 0, 0, 67, 63, 1, 0, 0, 0, 67, 66, 1, 0, 0, 0, 68, 9, 1, 0, 0, 0, 69, 70, 5, 5, 0, 0, 70, 71, 5, 33, 0, 0, 71, 75, 5, 6, 0, 0, 72, 74, 3, 12, 6, 0, 73, 72, 1, 0, 0, 0, 74, 77, 1, 0, 0, 0, 75, 73, 1, 0, 0, 0, 75, 76, 1, 0, 0, 0, 76, 78, 1, 0, 0, 0, 77, 75, 1, 0, 0, 0, 78, 79, 5, 7, 0, 0, 79, 80, 5, 2, 0, 0, 80, 11, 1, 0, 0, 0, 81, 82, 3, 26, 13, 0, 82, 83, 3, 28, 14, 0, 83, 84, 5, 2, 0, 0, 84, 13, 1, 0, 0, 0, 85, 86, 3, 26, 13, 0, 86, 89, 3, 28, 14, 0, 87, 88, 5, 8, 0, 0, 88, 90, 3, 24, 12, 0, 89, 87, 1, 0, 0, 0, 89, 90, 1, 0, 0, 0, 90, 91, 1, 0, 0, 0, 91, 92, 5, 2, 0, 0, 92, 15, 1, 0, 0, 0, 93, 94, 3, 26, 13, 0, 94, 95, 3, 28, 14, 0, 95, 97, 5, 9, 0, 0, 96, 98, 3, 18, 9, 0, 97, 96, 1, 0, 0, 0, 97, 98, 1, 0, 0, 0, 98, 99, 1, 0, 0, 0, 99, 100, 5, 10, 0, 0, 100, 101, 3, 20, 10, 0, 101, 17, 1, 0, 0, 0, 102, 103, 3, 26, 13, 0, 103, 110, 3, 28, 14, 0, 104, 105, 5, 11, 0, 0, 105, 106, 3, 26, 13, 0, 106, 107, 3, 28, 14, 0, 107, 109, 1, 0, 0, 0, 108, 104, 1, 0, 0, 0, 109, 112, 1, 0, 0, 0, 110, 108, 1, 0, 0, 0, 110, 111, 1, 0, 0, 0, 111, 19, 1, 0, 0, 0, 112, 110, 1, 0, 0, 0, 113, 117, 5, 6, 0, 0, 114, 116, 3, 22, 11, 0, 115, 114, 1, 0, 0, 0, 116, 119, 1, 0, 0, 0, 117, 115, 1, 0, 0, 0, 117, 118, 1, 0, 0, 0, 118, 120, 1, 0, 0, 0, 119, 117, 1, 0, 0, 0, 120, 121, 5, 7, 0, 0, 121, 21, 1, 0, 0, 0, 122, 123, 3, 24, 12, 0, 123, 124, 5, 2, 0, 0, 124, 23, 1, 0, 0, 0, 125, 126, 6, 12, -1, 0, 126, 163, 5, 11, 0, 0, 127, 163, 5, 12, 0, 0, 128, 163, 5, 13, 0, 0, 129, 163, 5, 14, 0, 0, 130, 163, 5, 15, 0, 0, 131, 163, 5, 16, 0, 0, 132, 163, 5, 17, 0, 0, 133, 163, 5, 18, 0, 0, 134, 163, 5, 19, 0, 0, 135, 163, 5, 20, 0, 0, 136, 163, 5, 21, 0, 0, 137, 163, 5, 8, 0, 0, 138, 163, 5, 22, 0, 0, 139, 163, 5, 23, 0, 0, 140, 141, 5, 9, 0, 0, 141, 142, 3, 24, 12, 0, 142, 143, 5, 10, 0, 0, 143, 163, 1, 0, 0, 0, 144, 145, 5, 24, 0, 0, 145, 146, 3, 24, 12, 0, 146, 147, 5, 25, 0, 0, 147, 163, 1, 0, 0, 0, 148, 149, 5, 6, 0, 0, 149, 150, 3, 24, 12, 0, 150, 151, 5, 7, 0, 0, 151, 163, 1, 0, 0, 0, 152, 163, 5, 35, 0, 0, 153, 163, 5, 34, 0, 0, 154, 158, 3, 26, 13, 0, 155, 157, 5, 14, 0, 0, 156, 155, 1, 0, 0, 0, 157, 160, 1, 0, 0, 0, 158, 156, 1, 0, 0, 0, 158, 159, 1, 0, 0, 0, 159, 163, 1, 0, 0, 0, 160, 158, 1, 0, 0, 0, 161, 163, 5, 33, 0, 0, 162, 125, 1, 0, 0, 0, 162, 127, 1, 0, 0, 0, 162, 128, 1, 0, 0, 0, 162, 129, 1, 0, 0, 0, 162, 130, 1, 0, 0, 0, 162, 131, 1, 0, 0, 0, 162, 132, 1, 0, 0, 0, 162, 133, 1, 0, 0, 0, 162, 134, 1, 0, 0, 0, 162, 135, 1, 0, 0, 0, 162, 136, 1, 0, 0, 0, 162, 137, 1, 0, 0, 0, 162, 138, 1, 0, 0, 0, 162, 139, 1, 0, 0, 0, 162, 140, 1, 0, 0, 0, 162, 144, 1, 0, 0, 0, 162, 148, 1, 0, 0, 0, 162, 152, 1, 0, 0, 0, 162, 153, 1, 0, 0, 0, 162, 154, 1, 0, 0, 0, 162, 161, 1, 0, 0, 0, 163, 168, 1, 0, 0, 0, 164, 165, 10, 22, 0, 0, 165, 167, 3, 24, 12, 23, 166, 164, 1, 0, 0, 0, 167, 170, 1, 0, 0, 0, 168, 166, 1, 0, 0, 0, 168, 169, 1, 0, 0, 0, 169, 25, 1, 0, 0, 0, 170, 168, 1, 0, 0, 0, 171, 181, 5, 26, 0, 0, 172, 181, 5, 27, 0, 0, 173, 181, 5, 28, 0, 0, 174, 181, 5, 29, 0, 0, 175, 181, 5, 30, 0, 0, 176, 181, 5, 31, 0, 0, 177, 181, 5, 32, 0, 0, 178, 179, 5, 5, 0, 0, 179, 181, 5, 33, 0, 0, 180, 171, 1, 0, 0, 0, 180, 172, 1, 0, 0, 0, 180, 173, 1, 0, 0, 0, 180, 174, 1, 0, 0, 0, 180, 175, 1, 0, 0, 0, 180, 176, 1, 0, 0, 0, 180, 177, 1, 0, 0, 0, 180, 178, 1, 0, 0, 0, 181, 27, 1, 0, 0, 0, 182, 184, 5, 14, 0, 0, 183, 182, 1, 0, 0, 0, 183, 184, 1, 0, 0, 0, 184, 185, 1, 0, 0, 0, 185, 186, 5, 33, 0, 0, 186, 29, 1, 0, 0, 0, 16, 37, 43, 55, 59, 63, 67, 75, 89, 97, 110, 117, 158, 162, 168, 180, 183]
Index: doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMOD.tokens
===================================================================
--- doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMOD.tokens	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
+++ doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMOD.tokens	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
@@ -0,0 +1,71 @@
+T__0=1
+T__1=2
+T__2=3
+T__3=4
+T__4=5
+T__5=6
+T__6=7
+T__7=8
+T__8=9
+T__9=10
+T__10=11
+T__11=12
+T__12=13
+T__13=14
+T__14=15
+T__15=16
+T__16=17
+T__17=18
+T__18=19
+T__19=20
+T__20=21
+T__21=22
+T__22=23
+T__23=24
+T__24=25
+T__25=26
+T__26=27
+T__27=28
+T__28=29
+T__29=30
+T__30=31
+T__31=32
+Identifier=33
+Number=34
+StringLiteral=35
+Whitespace=36
+Newline=37
+BlockComment=38
+LineComment=39
+'module'=1
+';'=2
+'import'=3
+'export'=4
+'struct'=5
+'{'=6
+'}'=7
+'='=8
+'('=9
+')'=10
+','=11
+'.'=12
+'->'=13
+'*'=14
+'/'=15
+'+'=16
+'-'=17
+'&'=18
+'|'=19
+'?'=20
+':'=21
+'<'=22
+'>'=23
+'['=24
+']'=25
+'void'=26
+'char'=27
+'short'=28
+'int'=29
+'long'=30
+'float'=31
+'double'=32
Index: doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMODLexer.interp
===================================================================
--- doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMODLexer.interp	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
+++ doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMODLexer.interp	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
@@ -0,0 +1,137 @@
+token literal names:
+null
+'module'
+';'
+'import'
+'export'
+'struct'
+'{'
+'}'
+'='
+'('
+')'
+','
+'.'
+'->'
+'*'
+'/'
+'+'
+'-'
+'&'
+'|'
+'?'
+':'
+'<'
+'>'
+'['
+']'
+'void'
+'char'
+'short'
+'int'
+'long'
+'float'
+'double'
+null
+null
+null
+null
+null
+null
+null
+
+token symbolic names:
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+Identifier
+Number
+StringLiteral
+Whitespace
+Newline
+BlockComment
+LineComment
+
+rule names:
+T__0
+T__1
+T__2
+T__3
+T__4
+T__5
+T__6
+T__7
+T__8
+T__9
+T__10
+T__11
+T__12
+T__13
+T__14
+T__15
+T__16
+T__17
+T__18
+T__19
+T__20
+T__21
+T__22
+T__23
+T__24
+T__25
+T__26
+T__27
+T__28
+T__29
+T__30
+T__31
+Identifier
+Number
+Nondigit
+Digit
+StringLiteral
+SChar
+Whitespace
+Newline
+BlockComment
+LineComment
+
+channel names:
+DEFAULT_TOKEN_CHANNEL
+HIDDEN
+
+mode names:
+DEFAULT_MODE
+
+atn:
+[4, 0, 39, 272, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 5, 32, 198, 8, 32, 10, 32, 12, 32, 201, 9, 32, 1, 33, 4, 33, 204, 8, 33, 11, 33, 12, 33, 205, 1, 33, 1, 33, 5, 33, 210, 8, 33, 10, 33, 12, 33, 213, 9, 33, 3, 33, 215, 8, 33, 1, 34, 1, 34, 1, 35, 1, 35, 1, 36, 1, 36, 5, 36, 223, 8, 36, 10, 36, 12, 36, 226, 9, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 38, 4, 38, 233, 8, 38, 11, 38, 12, 38, 234, 1, 38, 1, 38, 1, 39, 1, 39, 3, 39, 241, 8, 39, 1, 39, 3, 39, 244, 8, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 5, 40, 252, 8, 40, 10, 40, 12, 40, 255, 9, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 5, 41, 266, 8, 41, 10, 41, 12, 41, 269, 9, 41, 1, 41, 1, 41, 1, 253, 0, 42, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 34, 69, 0, 71, 0, 73, 35, 75, 0, 77, 36, 79, 37, 81, 38, 83, 39, 1, 0, 5, 4, 0, 36, 36, 65, 90, 95, 95, 97, 122, 1, 0, 48, 57, 3, 0, 10, 10, 13, 13, 34, 34, 2, 0, 9, 9, 32, 32, 2, 0, 10, 10, 13, 13, 279, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 1, 85, 1, 0, 0, 0, 3, 92, 1, 0, 0, 0, 5, 94, 1, 0, 0, 0, 7, 101, 1, 0, 0, 0, 9, 108, 1, 0, 0, 0, 11, 115, 1, 0, 0, 0, 13, 117, 1, 0, 0, 0, 15, 119, 1, 0, 0, 0, 17, 121, 1, 0, 0, 0, 19, 123, 1, 0, 0, 0, 21, 125, 1, 0, 0, 0, 23, 127, 1, 0, 0, 0, 25, 129, 1, 0, 0, 0, 27, 132, 1, 0, 0, 0, 29, 134, 1, 0, 0, 0, 31, 136, 1, 0, 0, 0, 33, 138, 1, 0, 0, 0, 35, 140, 1, 0, 0, 0, 37, 142, 1, 0, 0, 0, 39, 144, 1, 0, 0, 0, 41, 146, 1, 0, 0, 0, 43, 148, 1, 0, 0, 0, 45, 150, 1, 0, 0, 0, 47, 152, 1, 0, 0, 0, 49, 154, 1, 0, 0, 0, 51, 156, 1, 0, 0, 0, 53, 161, 1, 0, 0, 0, 55, 166, 1, 0, 0, 0, 57, 172, 1, 0, 0, 0, 59, 176, 1, 0, 0, 0, 61, 181, 1, 0, 0, 0, 63, 187, 1, 0, 0, 0, 65, 194, 1, 0, 0, 0, 67, 203, 1, 0, 0, 0, 69, 216, 1, 0, 0, 0, 71, 218, 1, 0, 0, 0, 73, 220, 1, 0, 0, 0, 75, 229, 1, 0, 0, 0, 77, 232, 1, 0, 0, 0, 79, 243, 1, 0, 0, 0, 81, 247, 1, 0, 0, 0, 83, 261, 1, 0, 0, 0, 85, 86, 5, 109, 0, 0, 86, 87, 5, 111, 0, 0, 87, 88, 5, 100, 0, 0, 88, 89, 5, 117, 0, 0, 89, 90, 5, 108, 0, 0, 90, 91, 5, 101, 0, 0, 91, 2, 1, 0, 0, 0, 92, 93, 5, 59, 0, 0, 93, 4, 1, 0, 0, 0, 94, 95, 5, 105, 0, 0, 95, 96, 5, 109, 0, 0, 96, 97, 5, 112, 0, 0, 97, 98, 5, 111, 0, 0, 98, 99, 5, 114, 0, 0, 99, 100, 5, 116, 0, 0, 100, 6, 1, 0, 0, 0, 101, 102, 5, 101, 0, 0, 102, 103, 5, 120, 0, 0, 103, 104, 5, 112, 0, 0, 104, 105, 5, 111, 0, 0, 105, 106, 5, 114, 0, 0, 106, 107, 5, 116, 0, 0, 107, 8, 1, 0, 0, 0, 108, 109, 5, 115, 0, 0, 109, 110, 5, 116, 0, 0, 110, 111, 5, 114, 0, 0, 111, 112, 5, 117, 0, 0, 112, 113, 5, 99, 0, 0, 113, 114, 5, 116, 0, 0, 114, 10, 1, 0, 0, 0, 115, 116, 5, 123, 0, 0, 116, 12, 1, 0, 0, 0, 117, 118, 5, 125, 0, 0, 118, 14, 1, 0, 0, 0, 119, 120, 5, 61, 0, 0, 120, 16, 1, 0, 0, 0, 121, 122, 5, 40, 0, 0, 122, 18, 1, 0, 0, 0, 123, 124, 5, 41, 0, 0, 124, 20, 1, 0, 0, 0, 125, 126, 5, 44, 0, 0, 126, 22, 1, 0, 0, 0, 127, 128, 5, 46, 0, 0, 128, 24, 1, 0, 0, 0, 129, 130, 5, 45, 0, 0, 130, 131, 5, 62, 0, 0, 131, 26, 1, 0, 0, 0, 132, 133, 5, 42, 0, 0, 133, 28, 1, 0, 0, 0, 134, 135, 5, 47, 0, 0, 135, 30, 1, 0, 0, 0, 136, 137, 5, 43, 0, 0, 137, 32, 1, 0, 0, 0, 138, 139, 5, 45, 0, 0, 139, 34, 1, 0, 0, 0, 140, 141, 5, 38, 0, 0, 141, 36, 1, 0, 0, 0, 142, 143, 5, 124, 0, 0, 143, 38, 1, 0, 0, 0, 144, 145, 5, 63, 0, 0, 145, 40, 1, 0, 0, 0, 146, 147, 5, 58, 0, 0, 147, 42, 1, 0, 0, 0, 148, 149, 5, 60, 0, 0, 149, 44, 1, 0, 0, 0, 150, 151, 5, 62, 0, 0, 151, 46, 1, 0, 0, 0, 152, 153, 5, 91, 0, 0, 153, 48, 1, 0, 0, 0, 154, 155, 5, 93, 0, 0, 155, 50, 1, 0, 0, 0, 156, 157, 5, 118, 0, 0, 157, 158, 5, 111, 0, 0, 158, 159, 5, 105, 0, 0, 159, 160, 5, 100, 0, 0, 160, 52, 1, 0, 0, 0, 161, 162, 5, 99, 0, 0, 162, 163, 5, 104, 0, 0, 163, 164, 5, 97, 0, 0, 164, 165, 5, 114, 0, 0, 165, 54, 1, 0, 0, 0, 166, 167, 5, 115, 0, 0, 167, 168, 5, 104, 0, 0, 168, 169, 5, 111, 0, 0, 169, 170, 5, 114, 0, 0, 170, 171, 5, 116, 0, 0, 171, 56, 1, 0, 0, 0, 172, 173, 5, 105, 0, 0, 173, 174, 5, 110, 0, 0, 174, 175, 5, 116, 0, 0, 175, 58, 1, 0, 0, 0, 176, 177, 5, 108, 0, 0, 177, 178, 5, 111, 0, 0, 178, 179, 5, 110, 0, 0, 179, 180, 5, 103, 0, 0, 180, 60, 1, 0, 0, 0, 181, 182, 5, 102, 0, 0, 182, 183, 5, 108, 0, 0, 183, 184, 5, 111, 0, 0, 184, 185, 5, 97, 0, 0, 185, 186, 5, 116, 0, 0, 186, 62, 1, 0, 0, 0, 187, 188, 5, 100, 0, 0, 188, 189, 5, 111, 0, 0, 189, 190, 5, 117, 0, 0, 190, 191, 5, 98, 0, 0, 191, 192, 5, 108, 0, 0, 192, 193, 5, 101, 0, 0, 193, 64, 1, 0, 0, 0, 194, 199, 3, 69, 34, 0, 195, 198, 3, 69, 34, 0, 196, 198, 3, 71, 35, 0, 197, 195, 1, 0, 0, 0, 197, 196, 1, 0, 0, 0, 198, 201, 1, 0, 0, 0, 199, 197, 1, 0, 0, 0, 199, 200, 1, 0, 0, 0, 200, 66, 1, 0, 0, 0, 201, 199, 1, 0, 0, 0, 202, 204, 3, 71, 35, 0, 203, 202, 1, 0, 0, 0, 204, 205, 1, 0, 0, 0, 205, 203, 1, 0, 0, 0, 205, 206, 1, 0, 0, 0, 206, 214, 1, 0, 0, 0, 207, 211, 5, 46, 0, 0, 208, 210, 3, 71, 35, 0, 209, 208, 1, 0, 0, 0, 210, 213, 1, 0, 0, 0, 211, 209, 1, 0, 0, 0, 211, 212, 1, 0, 0, 0, 212, 215, 1, 0, 0, 0, 213, 211, 1, 0, 0, 0, 214, 207, 1, 0, 0, 0, 214, 215, 1, 0, 0, 0, 215, 68, 1, 0, 0, 0, 216, 217, 7, 0, 0, 0, 217, 70, 1, 0, 0, 0, 218, 219, 7, 1, 0, 0, 219, 72, 1, 0, 0, 0, 220, 224, 5, 34, 0, 0, 221, 223, 3, 75, 37, 0, 222, 221, 1, 0, 0, 0, 223, 226, 1, 0, 0, 0, 224, 222, 1, 0, 0, 0, 224, 225, 1, 0, 0, 0, 225, 227, 1, 0, 0, 0, 226, 224, 1, 0, 0, 0, 227, 228, 5, 34, 0, 0, 228, 74, 1, 0, 0, 0, 229, 230, 8, 2, 0, 0, 230, 76, 1, 0, 0, 0, 231, 233, 7, 3, 0, 0, 232, 231, 1, 0, 0, 0, 233, 234, 1, 0, 0, 0, 234, 232, 1, 0, 0, 0, 234, 235, 1, 0, 0, 0, 235, 236, 1, 0, 0, 0, 236, 237, 6, 38, 0, 0, 237, 78, 1, 0, 0, 0, 238, 240, 5, 13, 0, 0, 239, 241, 5, 10, 0, 0, 240, 239, 1, 0, 0, 0, 240, 241, 1, 0, 0, 0, 241, 244, 1, 0, 0, 0, 242, 244, 5, 10, 0, 0, 243, 238, 1, 0, 0, 0, 243, 242, 1, 0, 0, 0, 244, 245, 1, 0, 0, 0, 245, 246, 6, 39, 0, 0, 246, 80, 1, 0, 0, 0, 247, 248, 5, 47, 0, 0, 248, 249, 5, 42, 0, 0, 249, 253, 1, 0, 0, 0, 250, 252, 9, 0, 0, 0, 251, 250, 1, 0, 0, 0, 252, 255, 1, 0, 0, 0, 253, 254, 1, 0, 0, 0, 253, 251, 1, 0, 0, 0, 254, 256, 1, 0, 0, 0, 255, 253, 1, 0, 0, 0, 256, 257, 5, 42, 0, 0, 257, 258, 5, 47, 0, 0, 258, 259, 1, 0, 0, 0, 259, 260, 6, 40, 0, 0, 260, 82, 1, 0, 0, 0, 261, 262, 5, 47, 0, 0, 262, 263, 5, 47, 0, 0, 263, 267, 1, 0, 0, 0, 264, 266, 8, 4, 0, 0, 265, 264, 1, 0, 0, 0, 266, 269, 1, 0, 0, 0, 267, 265, 1, 0, 0, 0, 267, 268, 1, 0, 0, 0, 268, 270, 1, 0, 0, 0, 269, 267, 1, 0, 0, 0, 270, 271, 6, 41, 0, 0, 271, 84, 1, 0, 0, 0, 12, 0, 197, 199, 205, 211, 214, 224, 234, 240, 243, 253, 267, 1, 0, 1, 0]
Index: doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMODLexer.py
===================================================================
--- doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMODLexer.py	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
+++ doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMODLexer.py	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
@@ -0,0 +1,189 @@
+# Generated from parser/CMOD.g4 by ANTLR 4.13.2
+from antlr4 import *
+from io import StringIO
+import sys
+if sys.version_info[1] > 5:
+    from typing import TextIO
+else:
+    from typing.io import TextIO
+
+
+def serializedATN():
+    return [
+        4,0,39,272,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,
+        2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,
+        13,7,13,2,14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7,
+        19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2,
+        26,7,26,2,27,7,27,2,28,7,28,2,29,7,29,2,30,7,30,2,31,7,31,2,32,7,
+        32,2,33,7,33,2,34,7,34,2,35,7,35,2,36,7,36,2,37,7,37,2,38,7,38,2,
+        39,7,39,2,40,7,40,2,41,7,41,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,
+        1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,4,1,4,
+        1,4,1,4,1,4,1,4,1,4,1,5,1,5,1,6,1,6,1,7,1,7,1,8,1,8,1,9,1,9,1,10,
+        1,10,1,11,1,11,1,12,1,12,1,12,1,13,1,13,1,14,1,14,1,15,1,15,1,16,
+        1,16,1,17,1,17,1,18,1,18,1,19,1,19,1,20,1,20,1,21,1,21,1,22,1,22,
+        1,23,1,23,1,24,1,24,1,25,1,25,1,25,1,25,1,25,1,26,1,26,1,26,1,26,
+        1,26,1,27,1,27,1,27,1,27,1,27,1,27,1,28,1,28,1,28,1,28,1,29,1,29,
+        1,29,1,29,1,29,1,30,1,30,1,30,1,30,1,30,1,30,1,31,1,31,1,31,1,31,
+        1,31,1,31,1,31,1,32,1,32,1,32,5,32,198,8,32,10,32,12,32,201,9,32,
+        1,33,4,33,204,8,33,11,33,12,33,205,1,33,1,33,5,33,210,8,33,10,33,
+        12,33,213,9,33,3,33,215,8,33,1,34,1,34,1,35,1,35,1,36,1,36,5,36,
+        223,8,36,10,36,12,36,226,9,36,1,36,1,36,1,37,1,37,1,38,4,38,233,
+        8,38,11,38,12,38,234,1,38,1,38,1,39,1,39,3,39,241,8,39,1,39,3,39,
+        244,8,39,1,39,1,39,1,40,1,40,1,40,1,40,5,40,252,8,40,10,40,12,40,
+        255,9,40,1,40,1,40,1,40,1,40,1,40,1,41,1,41,1,41,1,41,5,41,266,8,
+        41,10,41,12,41,269,9,41,1,41,1,41,1,253,0,42,1,1,3,2,5,3,7,4,9,5,
+        11,6,13,7,15,8,17,9,19,10,21,11,23,12,25,13,27,14,29,15,31,16,33,
+        17,35,18,37,19,39,20,41,21,43,22,45,23,47,24,49,25,51,26,53,27,55,
+        28,57,29,59,30,61,31,63,32,65,33,67,34,69,0,71,0,73,35,75,0,77,36,
+        79,37,81,38,83,39,1,0,5,4,0,36,36,65,90,95,95,97,122,1,0,48,57,3,
+        0,10,10,13,13,34,34,2,0,9,9,32,32,2,0,10,10,13,13,279,0,1,1,0,0,
+        0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0,0,0,0,11,1,0,0,0,0,
+        13,1,0,0,0,0,15,1,0,0,0,0,17,1,0,0,0,0,19,1,0,0,0,0,21,1,0,0,0,0,
+        23,1,0,0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,29,1,0,0,0,0,31,1,0,0,0,0,
+        33,1,0,0,0,0,35,1,0,0,0,0,37,1,0,0,0,0,39,1,0,0,0,0,41,1,0,0,0,0,
+        43,1,0,0,0,0,45,1,0,0,0,0,47,1,0,0,0,0,49,1,0,0,0,0,51,1,0,0,0,0,
+        53,1,0,0,0,0,55,1,0,0,0,0,57,1,0,0,0,0,59,1,0,0,0,0,61,1,0,0,0,0,
+        63,1,0,0,0,0,65,1,0,0,0,0,67,1,0,0,0,0,73,1,0,0,0,0,77,1,0,0,0,0,
+        79,1,0,0,0,0,81,1,0,0,0,0,83,1,0,0,0,1,85,1,0,0,0,3,92,1,0,0,0,5,
+        94,1,0,0,0,7,101,1,0,0,0,9,108,1,0,0,0,11,115,1,0,0,0,13,117,1,0,
+        0,0,15,119,1,0,0,0,17,121,1,0,0,0,19,123,1,0,0,0,21,125,1,0,0,0,
+        23,127,1,0,0,0,25,129,1,0,0,0,27,132,1,0,0,0,29,134,1,0,0,0,31,136,
+        1,0,0,0,33,138,1,0,0,0,35,140,1,0,0,0,37,142,1,0,0,0,39,144,1,0,
+        0,0,41,146,1,0,0,0,43,148,1,0,0,0,45,150,1,0,0,0,47,152,1,0,0,0,
+        49,154,1,0,0,0,51,156,1,0,0,0,53,161,1,0,0,0,55,166,1,0,0,0,57,172,
+        1,0,0,0,59,176,1,0,0,0,61,181,1,0,0,0,63,187,1,0,0,0,65,194,1,0,
+        0,0,67,203,1,0,0,0,69,216,1,0,0,0,71,218,1,0,0,0,73,220,1,0,0,0,
+        75,229,1,0,0,0,77,232,1,0,0,0,79,243,1,0,0,0,81,247,1,0,0,0,83,261,
+        1,0,0,0,85,86,5,109,0,0,86,87,5,111,0,0,87,88,5,100,0,0,88,89,5,
+        117,0,0,89,90,5,108,0,0,90,91,5,101,0,0,91,2,1,0,0,0,92,93,5,59,
+        0,0,93,4,1,0,0,0,94,95,5,105,0,0,95,96,5,109,0,0,96,97,5,112,0,0,
+        97,98,5,111,0,0,98,99,5,114,0,0,99,100,5,116,0,0,100,6,1,0,0,0,101,
+        102,5,101,0,0,102,103,5,120,0,0,103,104,5,112,0,0,104,105,5,111,
+        0,0,105,106,5,114,0,0,106,107,5,116,0,0,107,8,1,0,0,0,108,109,5,
+        115,0,0,109,110,5,116,0,0,110,111,5,114,0,0,111,112,5,117,0,0,112,
+        113,5,99,0,0,113,114,5,116,0,0,114,10,1,0,0,0,115,116,5,123,0,0,
+        116,12,1,0,0,0,117,118,5,125,0,0,118,14,1,0,0,0,119,120,5,61,0,0,
+        120,16,1,0,0,0,121,122,5,40,0,0,122,18,1,0,0,0,123,124,5,41,0,0,
+        124,20,1,0,0,0,125,126,5,44,0,0,126,22,1,0,0,0,127,128,5,46,0,0,
+        128,24,1,0,0,0,129,130,5,45,0,0,130,131,5,62,0,0,131,26,1,0,0,0,
+        132,133,5,42,0,0,133,28,1,0,0,0,134,135,5,47,0,0,135,30,1,0,0,0,
+        136,137,5,43,0,0,137,32,1,0,0,0,138,139,5,45,0,0,139,34,1,0,0,0,
+        140,141,5,38,0,0,141,36,1,0,0,0,142,143,5,124,0,0,143,38,1,0,0,0,
+        144,145,5,63,0,0,145,40,1,0,0,0,146,147,5,58,0,0,147,42,1,0,0,0,
+        148,149,5,60,0,0,149,44,1,0,0,0,150,151,5,62,0,0,151,46,1,0,0,0,
+        152,153,5,91,0,0,153,48,1,0,0,0,154,155,5,93,0,0,155,50,1,0,0,0,
+        156,157,5,118,0,0,157,158,5,111,0,0,158,159,5,105,0,0,159,160,5,
+        100,0,0,160,52,1,0,0,0,161,162,5,99,0,0,162,163,5,104,0,0,163,164,
+        5,97,0,0,164,165,5,114,0,0,165,54,1,0,0,0,166,167,5,115,0,0,167,
+        168,5,104,0,0,168,169,5,111,0,0,169,170,5,114,0,0,170,171,5,116,
+        0,0,171,56,1,0,0,0,172,173,5,105,0,0,173,174,5,110,0,0,174,175,5,
+        116,0,0,175,58,1,0,0,0,176,177,5,108,0,0,177,178,5,111,0,0,178,179,
+        5,110,0,0,179,180,5,103,0,0,180,60,1,0,0,0,181,182,5,102,0,0,182,
+        183,5,108,0,0,183,184,5,111,0,0,184,185,5,97,0,0,185,186,5,116,0,
+        0,186,62,1,0,0,0,187,188,5,100,0,0,188,189,5,111,0,0,189,190,5,117,
+        0,0,190,191,5,98,0,0,191,192,5,108,0,0,192,193,5,101,0,0,193,64,
+        1,0,0,0,194,199,3,69,34,0,195,198,3,69,34,0,196,198,3,71,35,0,197,
+        195,1,0,0,0,197,196,1,0,0,0,198,201,1,0,0,0,199,197,1,0,0,0,199,
+        200,1,0,0,0,200,66,1,0,0,0,201,199,1,0,0,0,202,204,3,71,35,0,203,
+        202,1,0,0,0,204,205,1,0,0,0,205,203,1,0,0,0,205,206,1,0,0,0,206,
+        214,1,0,0,0,207,211,5,46,0,0,208,210,3,71,35,0,209,208,1,0,0,0,210,
+        213,1,0,0,0,211,209,1,0,0,0,211,212,1,0,0,0,212,215,1,0,0,0,213,
+        211,1,0,0,0,214,207,1,0,0,0,214,215,1,0,0,0,215,68,1,0,0,0,216,217,
+        7,0,0,0,217,70,1,0,0,0,218,219,7,1,0,0,219,72,1,0,0,0,220,224,5,
+        34,0,0,221,223,3,75,37,0,222,221,1,0,0,0,223,226,1,0,0,0,224,222,
+        1,0,0,0,224,225,1,0,0,0,225,227,1,0,0,0,226,224,1,0,0,0,227,228,
+        5,34,0,0,228,74,1,0,0,0,229,230,8,2,0,0,230,76,1,0,0,0,231,233,7,
+        3,0,0,232,231,1,0,0,0,233,234,1,0,0,0,234,232,1,0,0,0,234,235,1,
+        0,0,0,235,236,1,0,0,0,236,237,6,38,0,0,237,78,1,0,0,0,238,240,5,
+        13,0,0,239,241,5,10,0,0,240,239,1,0,0,0,240,241,1,0,0,0,241,244,
+        1,0,0,0,242,244,5,10,0,0,243,238,1,0,0,0,243,242,1,0,0,0,244,245,
+        1,0,0,0,245,246,6,39,0,0,246,80,1,0,0,0,247,248,5,47,0,0,248,249,
+        5,42,0,0,249,253,1,0,0,0,250,252,9,0,0,0,251,250,1,0,0,0,252,255,
+        1,0,0,0,253,254,1,0,0,0,253,251,1,0,0,0,254,256,1,0,0,0,255,253,
+        1,0,0,0,256,257,5,42,0,0,257,258,5,47,0,0,258,259,1,0,0,0,259,260,
+        6,40,0,0,260,82,1,0,0,0,261,262,5,47,0,0,262,263,5,47,0,0,263,267,
+        1,0,0,0,264,266,8,4,0,0,265,264,1,0,0,0,266,269,1,0,0,0,267,265,
+        1,0,0,0,267,268,1,0,0,0,268,270,1,0,0,0,269,267,1,0,0,0,270,271,
+        6,41,0,0,271,84,1,0,0,0,12,0,197,199,205,211,214,224,234,240,243,
+        253,267,1,0,1,0
+    ]
+
+class CMODLexer(Lexer):
+
+    atn = ATNDeserializer().deserialize(serializedATN())
+
+    decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ]
+
+    T__0 = 1
+    T__1 = 2
+    T__2 = 3
+    T__3 = 4
+    T__4 = 5
+    T__5 = 6
+    T__6 = 7
+    T__7 = 8
+    T__8 = 9
+    T__9 = 10
+    T__10 = 11
+    T__11 = 12
+    T__12 = 13
+    T__13 = 14
+    T__14 = 15
+    T__15 = 16
+    T__16 = 17
+    T__17 = 18
+    T__18 = 19
+    T__19 = 20
+    T__20 = 21
+    T__21 = 22
+    T__22 = 23
+    T__23 = 24
+    T__24 = 25
+    T__25 = 26
+    T__26 = 27
+    T__27 = 28
+    T__28 = 29
+    T__29 = 30
+    T__30 = 31
+    T__31 = 32
+    Identifier = 33
+    Number = 34
+    StringLiteral = 35
+    Whitespace = 36
+    Newline = 37
+    BlockComment = 38
+    LineComment = 39
+
+    channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ]
+
+    modeNames = [ "DEFAULT_MODE" ]
+
+    literalNames = [ "<INVALID>",
+            "'module'", "';'", "'import'", "'export'", "'struct'", "'{'", 
+            "'}'", "'='", "'('", "')'", "','", "'.'", "'->'", "'*'", "'/'", 
+            "'+'", "'-'", "'&'", "'|'", "'?'", "':'", "'<'", "'>'", "'['", 
+            "']'", "'void'", "'char'", "'short'", "'int'", "'long'", "'float'", 
+            "'double'" ]
+
+    symbolicNames = [ "<INVALID>",
+            "Identifier", "Number", "StringLiteral", "Whitespace", "Newline", 
+            "BlockComment", "LineComment" ]
+
+    ruleNames = [ "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", 
+                  "T__7", "T__8", "T__9", "T__10", "T__11", "T__12", "T__13", 
+                  "T__14", "T__15", "T__16", "T__17", "T__18", "T__19", 
+                  "T__20", "T__21", "T__22", "T__23", "T__24", "T__25", 
+                  "T__26", "T__27", "T__28", "T__29", "T__30", "T__31", 
+                  "Identifier", "Number", "Nondigit", "Digit", "StringLiteral", 
+                  "SChar", "Whitespace", "Newline", "BlockComment", "LineComment" ]
+
+    grammarFileName = "CMOD.g4"
+
+    def __init__(self, input=None, output:TextIO = sys.stdout):
+        super().__init__(input, output)
+        self.checkVersion("4.13.2")
+        self._interp = LexerATNSimulator(self, self.atn, self.decisionsToDFA, PredictionContextCache())
+        self._actions = None
+        self._predicates = None
+
+
Index: doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMODLexer.tokens
===================================================================
--- doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMODLexer.tokens	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
+++ doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMODLexer.tokens	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
@@ -0,0 +1,71 @@
+T__0=1
+T__1=2
+T__2=3
+T__3=4
+T__4=5
+T__5=6
+T__6=7
+T__7=8
+T__8=9
+T__9=10
+T__10=11
+T__11=12
+T__12=13
+T__13=14
+T__14=15
+T__15=16
+T__16=17
+T__17=18
+T__18=19
+T__19=20
+T__20=21
+T__21=22
+T__22=23
+T__23=24
+T__24=25
+T__25=26
+T__26=27
+T__27=28
+T__28=29
+T__29=30
+T__30=31
+T__31=32
+Identifier=33
+Number=34
+StringLiteral=35
+Whitespace=36
+Newline=37
+BlockComment=38
+LineComment=39
+'module'=1
+';'=2
+'import'=3
+'export'=4
+'struct'=5
+'{'=6
+'}'=7
+'='=8
+'('=9
+')'=10
+','=11
+'.'=12
+'->'=13
+'*'=14
+'/'=15
+'+'=16
+'-'=17
+'&'=18
+'|'=19
+'?'=20
+':'=21
+'<'=22
+'>'=23
+'['=24
+']'=25
+'void'=26
+'char'=27
+'short'=28
+'int'=29
+'long'=30
+'float'=31
+'double'=32
Index: doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMODListener.py
===================================================================
--- doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMODListener.py	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
+++ doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMODListener.py	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
@@ -0,0 +1,147 @@
+# Generated from parser/CMOD.g4 by ANTLR 4.13.2
+from antlr4 import *
+if "." in __name__:
+    from .CMODParser import CMODParser
+else:
+    from CMODParser import CMODParser
+
+# This class defines a complete listener for a parse tree produced by CMODParser.
+class CMODListener(ParseTreeListener):
+
+    # Enter a parse tree produced by CMODParser#compilationUnit.
+    def enterCompilationUnit(self, ctx:CMODParser.CompilationUnitContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#compilationUnit.
+    def exitCompilationUnit(self, ctx:CMODParser.CompilationUnitContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#translationUnit.
+    def enterTranslationUnit(self, ctx:CMODParser.TranslationUnitContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#translationUnit.
+    def exitTranslationUnit(self, ctx:CMODParser.TranslationUnitContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#moduleDeclaration.
+    def enterModuleDeclaration(self, ctx:CMODParser.ModuleDeclarationContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#moduleDeclaration.
+    def exitModuleDeclaration(self, ctx:CMODParser.ModuleDeclarationContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#importDeclaration.
+    def enterImportDeclaration(self, ctx:CMODParser.ImportDeclarationContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#importDeclaration.
+    def exitImportDeclaration(self, ctx:CMODParser.ImportDeclarationContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#externalDeclaration.
+    def enterExternalDeclaration(self, ctx:CMODParser.ExternalDeclarationContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#externalDeclaration.
+    def exitExternalDeclaration(self, ctx:CMODParser.ExternalDeclarationContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#structDefinition.
+    def enterStructDefinition(self, ctx:CMODParser.StructDefinitionContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#structDefinition.
+    def exitStructDefinition(self, ctx:CMODParser.StructDefinitionContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#structField.
+    def enterStructField(self, ctx:CMODParser.StructFieldContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#structField.
+    def exitStructField(self, ctx:CMODParser.StructFieldContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#globalDefinition.
+    def enterGlobalDefinition(self, ctx:CMODParser.GlobalDefinitionContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#globalDefinition.
+    def exitGlobalDefinition(self, ctx:CMODParser.GlobalDefinitionContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#functionDefinition.
+    def enterFunctionDefinition(self, ctx:CMODParser.FunctionDefinitionContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#functionDefinition.
+    def exitFunctionDefinition(self, ctx:CMODParser.FunctionDefinitionContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#parameterList.
+    def enterParameterList(self, ctx:CMODParser.ParameterListContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#parameterList.
+    def exitParameterList(self, ctx:CMODParser.ParameterListContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#compoundStatement.
+    def enterCompoundStatement(self, ctx:CMODParser.CompoundStatementContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#compoundStatement.
+    def exitCompoundStatement(self, ctx:CMODParser.CompoundStatementContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#statement.
+    def enterStatement(self, ctx:CMODParser.StatementContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#statement.
+    def exitStatement(self, ctx:CMODParser.StatementContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#expression.
+    def enterExpression(self, ctx:CMODParser.ExpressionContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#expression.
+    def exitExpression(self, ctx:CMODParser.ExpressionContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#typeSpecifier.
+    def enterTypeSpecifier(self, ctx:CMODParser.TypeSpecifierContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#typeSpecifier.
+    def exitTypeSpecifier(self, ctx:CMODParser.TypeSpecifierContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#declarator.
+    def enterDeclarator(self, ctx:CMODParser.DeclaratorContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#declarator.
+    def exitDeclarator(self, ctx:CMODParser.DeclaratorContext):
+        pass
+
+
+
+del CMODParser
Index: doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMODParser.py
===================================================================
--- doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMODParser.py	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
+++ doc/proposals/modules-alvin/3_implementation_details/prototype/parser/CMODParser.py	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
@@ -0,0 +1,1267 @@
+# Generated from parser/CMOD.g4 by ANTLR 4.13.2
+# encoding: utf-8
+from antlr4 import *
+from io import StringIO
+import sys
+if sys.version_info[1] > 5:
+	from typing import TextIO
+else:
+	from typing.io import TextIO
+
+def serializedATN():
+    return [
+        4,1,39,188,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,
+        6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,
+        2,14,7,14,1,0,1,0,1,0,1,1,1,1,5,1,36,8,1,10,1,12,1,39,9,1,1,1,5,
+        1,42,8,1,10,1,12,1,45,9,1,1,2,1,2,1,2,1,2,1,3,1,3,1,3,1,3,1,4,3,
+        4,56,8,4,1,4,1,4,3,4,60,8,4,1,4,1,4,3,4,64,8,4,1,4,1,4,3,4,68,8,
+        4,1,5,1,5,1,5,1,5,5,5,74,8,5,10,5,12,5,77,9,5,1,5,1,5,1,5,1,6,1,
+        6,1,6,1,6,1,7,1,7,1,7,1,7,3,7,90,8,7,1,7,1,7,1,8,1,8,1,8,1,8,3,8,
+        98,8,8,1,8,1,8,1,8,1,9,1,9,1,9,1,9,1,9,1,9,5,9,109,8,9,10,9,12,9,
+        112,9,9,1,10,1,10,5,10,116,8,10,10,10,12,10,119,9,10,1,10,1,10,1,
+        11,1,11,1,11,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,
+        12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,
+        12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,5,12,157,8,12,10,12,12,12,
+        160,9,12,1,12,3,12,163,8,12,1,12,1,12,5,12,167,8,12,10,12,12,12,
+        170,9,12,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,3,13,181,8,
+        13,1,14,3,14,184,8,14,1,14,1,14,1,14,0,1,24,15,0,2,4,6,8,10,12,14,
+        16,18,20,22,24,26,28,0,0,215,0,30,1,0,0,0,2,33,1,0,0,0,4,46,1,0,
+        0,0,6,50,1,0,0,0,8,67,1,0,0,0,10,69,1,0,0,0,12,81,1,0,0,0,14,85,
+        1,0,0,0,16,93,1,0,0,0,18,102,1,0,0,0,20,113,1,0,0,0,22,122,1,0,0,
+        0,24,162,1,0,0,0,26,180,1,0,0,0,28,183,1,0,0,0,30,31,3,2,1,0,31,
+        32,5,0,0,1,32,1,1,0,0,0,33,37,3,4,2,0,34,36,3,6,3,0,35,34,1,0,0,
+        0,36,39,1,0,0,0,37,35,1,0,0,0,37,38,1,0,0,0,38,43,1,0,0,0,39,37,
+        1,0,0,0,40,42,3,8,4,0,41,40,1,0,0,0,42,45,1,0,0,0,43,41,1,0,0,0,
+        43,44,1,0,0,0,44,3,1,0,0,0,45,43,1,0,0,0,46,47,5,1,0,0,47,48,5,33,
+        0,0,48,49,5,2,0,0,49,5,1,0,0,0,50,51,5,3,0,0,51,52,5,33,0,0,52,53,
+        5,2,0,0,53,7,1,0,0,0,54,56,5,4,0,0,55,54,1,0,0,0,55,56,1,0,0,0,56,
+        57,1,0,0,0,57,68,3,10,5,0,58,60,5,4,0,0,59,58,1,0,0,0,59,60,1,0,
+        0,0,60,61,1,0,0,0,61,68,3,14,7,0,62,64,5,4,0,0,63,62,1,0,0,0,63,
+        64,1,0,0,0,64,65,1,0,0,0,65,68,3,16,8,0,66,68,5,2,0,0,67,55,1,0,
+        0,0,67,59,1,0,0,0,67,63,1,0,0,0,67,66,1,0,0,0,68,9,1,0,0,0,69,70,
+        5,5,0,0,70,71,5,33,0,0,71,75,5,6,0,0,72,74,3,12,6,0,73,72,1,0,0,
+        0,74,77,1,0,0,0,75,73,1,0,0,0,75,76,1,0,0,0,76,78,1,0,0,0,77,75,
+        1,0,0,0,78,79,5,7,0,0,79,80,5,2,0,0,80,11,1,0,0,0,81,82,3,26,13,
+        0,82,83,3,28,14,0,83,84,5,2,0,0,84,13,1,0,0,0,85,86,3,26,13,0,86,
+        89,3,28,14,0,87,88,5,8,0,0,88,90,3,24,12,0,89,87,1,0,0,0,89,90,1,
+        0,0,0,90,91,1,0,0,0,91,92,5,2,0,0,92,15,1,0,0,0,93,94,3,26,13,0,
+        94,95,3,28,14,0,95,97,5,9,0,0,96,98,3,18,9,0,97,96,1,0,0,0,97,98,
+        1,0,0,0,98,99,1,0,0,0,99,100,5,10,0,0,100,101,3,20,10,0,101,17,1,
+        0,0,0,102,103,3,26,13,0,103,110,3,28,14,0,104,105,5,11,0,0,105,106,
+        3,26,13,0,106,107,3,28,14,0,107,109,1,0,0,0,108,104,1,0,0,0,109,
+        112,1,0,0,0,110,108,1,0,0,0,110,111,1,0,0,0,111,19,1,0,0,0,112,110,
+        1,0,0,0,113,117,5,6,0,0,114,116,3,22,11,0,115,114,1,0,0,0,116,119,
+        1,0,0,0,117,115,1,0,0,0,117,118,1,0,0,0,118,120,1,0,0,0,119,117,
+        1,0,0,0,120,121,5,7,0,0,121,21,1,0,0,0,122,123,3,24,12,0,123,124,
+        5,2,0,0,124,23,1,0,0,0,125,126,6,12,-1,0,126,163,5,11,0,0,127,163,
+        5,12,0,0,128,163,5,13,0,0,129,163,5,14,0,0,130,163,5,15,0,0,131,
+        163,5,16,0,0,132,163,5,17,0,0,133,163,5,18,0,0,134,163,5,19,0,0,
+        135,163,5,20,0,0,136,163,5,21,0,0,137,163,5,8,0,0,138,163,5,22,0,
+        0,139,163,5,23,0,0,140,141,5,9,0,0,141,142,3,24,12,0,142,143,5,10,
+        0,0,143,163,1,0,0,0,144,145,5,24,0,0,145,146,3,24,12,0,146,147,5,
+        25,0,0,147,163,1,0,0,0,148,149,5,6,0,0,149,150,3,24,12,0,150,151,
+        5,7,0,0,151,163,1,0,0,0,152,163,5,35,0,0,153,163,5,34,0,0,154,158,
+        3,26,13,0,155,157,5,14,0,0,156,155,1,0,0,0,157,160,1,0,0,0,158,156,
+        1,0,0,0,158,159,1,0,0,0,159,163,1,0,0,0,160,158,1,0,0,0,161,163,
+        5,33,0,0,162,125,1,0,0,0,162,127,1,0,0,0,162,128,1,0,0,0,162,129,
+        1,0,0,0,162,130,1,0,0,0,162,131,1,0,0,0,162,132,1,0,0,0,162,133,
+        1,0,0,0,162,134,1,0,0,0,162,135,1,0,0,0,162,136,1,0,0,0,162,137,
+        1,0,0,0,162,138,1,0,0,0,162,139,1,0,0,0,162,140,1,0,0,0,162,144,
+        1,0,0,0,162,148,1,0,0,0,162,152,1,0,0,0,162,153,1,0,0,0,162,154,
+        1,0,0,0,162,161,1,0,0,0,163,168,1,0,0,0,164,165,10,22,0,0,165,167,
+        3,24,12,23,166,164,1,0,0,0,167,170,1,0,0,0,168,166,1,0,0,0,168,169,
+        1,0,0,0,169,25,1,0,0,0,170,168,1,0,0,0,171,181,5,26,0,0,172,181,
+        5,27,0,0,173,181,5,28,0,0,174,181,5,29,0,0,175,181,5,30,0,0,176,
+        181,5,31,0,0,177,181,5,32,0,0,178,179,5,5,0,0,179,181,5,33,0,0,180,
+        171,1,0,0,0,180,172,1,0,0,0,180,173,1,0,0,0,180,174,1,0,0,0,180,
+        175,1,0,0,0,180,176,1,0,0,0,180,177,1,0,0,0,180,178,1,0,0,0,181,
+        27,1,0,0,0,182,184,5,14,0,0,183,182,1,0,0,0,183,184,1,0,0,0,184,
+        185,1,0,0,0,185,186,5,33,0,0,186,29,1,0,0,0,16,37,43,55,59,63,67,
+        75,89,97,110,117,158,162,168,180,183
+    ]
+
+class CMODParser ( Parser ):
+
+    grammarFileName = "CMOD.g4"
+
+    atn = ATNDeserializer().deserialize(serializedATN())
+
+    decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ]
+
+    sharedContextCache = PredictionContextCache()
+
+    literalNames = [ "<INVALID>", "'module'", "';'", "'import'", "'export'", 
+                     "'struct'", "'{'", "'}'", "'='", "'('", "')'", "','", 
+                     "'.'", "'->'", "'*'", "'/'", "'+'", "'-'", "'&'", "'|'", 
+                     "'?'", "':'", "'<'", "'>'", "'['", "']'", "'void'", 
+                     "'char'", "'short'", "'int'", "'long'", "'float'", 
+                     "'double'" ]
+
+    symbolicNames = [ "<INVALID>", "<INVALID>", "<INVALID>", "<INVALID>", 
+                      "<INVALID>", "<INVALID>", "<INVALID>", "<INVALID>", 
+                      "<INVALID>", "<INVALID>", "<INVALID>", "<INVALID>", 
+                      "<INVALID>", "<INVALID>", "<INVALID>", "<INVALID>", 
+                      "<INVALID>", "<INVALID>", "<INVALID>", "<INVALID>", 
+                      "<INVALID>", "<INVALID>", "<INVALID>", "<INVALID>", 
+                      "<INVALID>", "<INVALID>", "<INVALID>", "<INVALID>", 
+                      "<INVALID>", "<INVALID>", "<INVALID>", "<INVALID>", 
+                      "<INVALID>", "Identifier", "Number", "StringLiteral", 
+                      "Whitespace", "Newline", "BlockComment", "LineComment" ]
+
+    RULE_compilationUnit = 0
+    RULE_translationUnit = 1
+    RULE_moduleDeclaration = 2
+    RULE_importDeclaration = 3
+    RULE_externalDeclaration = 4
+    RULE_structDefinition = 5
+    RULE_structField = 6
+    RULE_globalDefinition = 7
+    RULE_functionDefinition = 8
+    RULE_parameterList = 9
+    RULE_compoundStatement = 10
+    RULE_statement = 11
+    RULE_expression = 12
+    RULE_typeSpecifier = 13
+    RULE_declarator = 14
+
+    ruleNames =  [ "compilationUnit", "translationUnit", "moduleDeclaration", 
+                   "importDeclaration", "externalDeclaration", "structDefinition", 
+                   "structField", "globalDefinition", "functionDefinition", 
+                   "parameterList", "compoundStatement", "statement", "expression", 
+                   "typeSpecifier", "declarator" ]
+
+    EOF = Token.EOF
+    T__0=1
+    T__1=2
+    T__2=3
+    T__3=4
+    T__4=5
+    T__5=6
+    T__6=7
+    T__7=8
+    T__8=9
+    T__9=10
+    T__10=11
+    T__11=12
+    T__12=13
+    T__13=14
+    T__14=15
+    T__15=16
+    T__16=17
+    T__17=18
+    T__18=19
+    T__19=20
+    T__20=21
+    T__21=22
+    T__22=23
+    T__23=24
+    T__24=25
+    T__25=26
+    T__26=27
+    T__27=28
+    T__28=29
+    T__29=30
+    T__30=31
+    T__31=32
+    Identifier=33
+    Number=34
+    StringLiteral=35
+    Whitespace=36
+    Newline=37
+    BlockComment=38
+    LineComment=39
+
+    def __init__(self, input:TokenStream, output:TextIO = sys.stdout):
+        super().__init__(input, output)
+        self.checkVersion("4.13.2")
+        self._interp = ParserATNSimulator(self, self.atn, self.decisionsToDFA, self.sharedContextCache)
+        self._predicates = None
+
+
+
+
+    class CompilationUnitContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def translationUnit(self):
+            return self.getTypedRuleContext(CMODParser.TranslationUnitContext,0)
+
+
+        def EOF(self):
+            return self.getToken(CMODParser.EOF, 0)
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_compilationUnit
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterCompilationUnit" ):
+                listener.enterCompilationUnit(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitCompilationUnit" ):
+                listener.exitCompilationUnit(self)
+
+
+
+
+    def compilationUnit(self):
+
+        localctx = CMODParser.CompilationUnitContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 0, self.RULE_compilationUnit)
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 30
+            self.translationUnit()
+            self.state = 31
+            self.match(CMODParser.EOF)
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class TranslationUnitContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def moduleDeclaration(self):
+            return self.getTypedRuleContext(CMODParser.ModuleDeclarationContext,0)
+
+
+        def importDeclaration(self, i:int=None):
+            if i is None:
+                return self.getTypedRuleContexts(CMODParser.ImportDeclarationContext)
+            else:
+                return self.getTypedRuleContext(CMODParser.ImportDeclarationContext,i)
+
+
+        def externalDeclaration(self, i:int=None):
+            if i is None:
+                return self.getTypedRuleContexts(CMODParser.ExternalDeclarationContext)
+            else:
+                return self.getTypedRuleContext(CMODParser.ExternalDeclarationContext,i)
+
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_translationUnit
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterTranslationUnit" ):
+                listener.enterTranslationUnit(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitTranslationUnit" ):
+                listener.exitTranslationUnit(self)
+
+
+
+
+    def translationUnit(self):
+
+        localctx = CMODParser.TranslationUnitContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 2, self.RULE_translationUnit)
+        self._la = 0 # Token type
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 33
+            self.moduleDeclaration()
+            self.state = 37
+            self._errHandler.sync(self)
+            _la = self._input.LA(1)
+            while _la==3:
+                self.state = 34
+                self.importDeclaration()
+                self.state = 39
+                self._errHandler.sync(self)
+                _la = self._input.LA(1)
+
+            self.state = 43
+            self._errHandler.sync(self)
+            _la = self._input.LA(1)
+            while (((_la) & ~0x3f) == 0 and ((1 << _la) & 8522825780) != 0):
+                self.state = 40
+                self.externalDeclaration()
+                self.state = 45
+                self._errHandler.sync(self)
+                _la = self._input.LA(1)
+
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class ModuleDeclarationContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def Identifier(self):
+            return self.getToken(CMODParser.Identifier, 0)
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_moduleDeclaration
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterModuleDeclaration" ):
+                listener.enterModuleDeclaration(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitModuleDeclaration" ):
+                listener.exitModuleDeclaration(self)
+
+
+
+
+    def moduleDeclaration(self):
+
+        localctx = CMODParser.ModuleDeclarationContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 4, self.RULE_moduleDeclaration)
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 46
+            self.match(CMODParser.T__0)
+            self.state = 47
+            self.match(CMODParser.Identifier)
+            self.state = 48
+            self.match(CMODParser.T__1)
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class ImportDeclarationContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def Identifier(self):
+            return self.getToken(CMODParser.Identifier, 0)
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_importDeclaration
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterImportDeclaration" ):
+                listener.enterImportDeclaration(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitImportDeclaration" ):
+                listener.exitImportDeclaration(self)
+
+
+
+
+    def importDeclaration(self):
+
+        localctx = CMODParser.ImportDeclarationContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 6, self.RULE_importDeclaration)
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 50
+            self.match(CMODParser.T__2)
+            self.state = 51
+            self.match(CMODParser.Identifier)
+            self.state = 52
+            self.match(CMODParser.T__1)
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class ExternalDeclarationContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def structDefinition(self):
+            return self.getTypedRuleContext(CMODParser.StructDefinitionContext,0)
+
+
+        def globalDefinition(self):
+            return self.getTypedRuleContext(CMODParser.GlobalDefinitionContext,0)
+
+
+        def functionDefinition(self):
+            return self.getTypedRuleContext(CMODParser.FunctionDefinitionContext,0)
+
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_externalDeclaration
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterExternalDeclaration" ):
+                listener.enterExternalDeclaration(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitExternalDeclaration" ):
+                listener.exitExternalDeclaration(self)
+
+
+
+
+    def externalDeclaration(self):
+
+        localctx = CMODParser.ExternalDeclarationContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 8, self.RULE_externalDeclaration)
+        self._la = 0 # Token type
+        try:
+            self.state = 67
+            self._errHandler.sync(self)
+            la_ = self._interp.adaptivePredict(self._input,5,self._ctx)
+            if la_ == 1:
+                self.enterOuterAlt(localctx, 1)
+                self.state = 55
+                self._errHandler.sync(self)
+                _la = self._input.LA(1)
+                if _la==4:
+                    self.state = 54
+                    self.match(CMODParser.T__3)
+
+
+                self.state = 57
+                self.structDefinition()
+                pass
+
+            elif la_ == 2:
+                self.enterOuterAlt(localctx, 2)
+                self.state = 59
+                self._errHandler.sync(self)
+                _la = self._input.LA(1)
+                if _la==4:
+                    self.state = 58
+                    self.match(CMODParser.T__3)
+
+
+                self.state = 61
+                self.globalDefinition()
+                pass
+
+            elif la_ == 3:
+                self.enterOuterAlt(localctx, 3)
+                self.state = 63
+                self._errHandler.sync(self)
+                _la = self._input.LA(1)
+                if _la==4:
+                    self.state = 62
+                    self.match(CMODParser.T__3)
+
+
+                self.state = 65
+                self.functionDefinition()
+                pass
+
+            elif la_ == 4:
+                self.enterOuterAlt(localctx, 4)
+                self.state = 66
+                self.match(CMODParser.T__1)
+                pass
+
+
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class StructDefinitionContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def Identifier(self):
+            return self.getToken(CMODParser.Identifier, 0)
+
+        def structField(self, i:int=None):
+            if i is None:
+                return self.getTypedRuleContexts(CMODParser.StructFieldContext)
+            else:
+                return self.getTypedRuleContext(CMODParser.StructFieldContext,i)
+
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_structDefinition
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterStructDefinition" ):
+                listener.enterStructDefinition(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitStructDefinition" ):
+                listener.exitStructDefinition(self)
+
+
+
+
+    def structDefinition(self):
+
+        localctx = CMODParser.StructDefinitionContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 10, self.RULE_structDefinition)
+        self._la = 0 # Token type
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 69
+            self.match(CMODParser.T__4)
+            self.state = 70
+            self.match(CMODParser.Identifier)
+            self.state = 71
+            self.match(CMODParser.T__5)
+            self.state = 75
+            self._errHandler.sync(self)
+            _la = self._input.LA(1)
+            while (((_la) & ~0x3f) == 0 and ((1 << _la) & 8522825760) != 0):
+                self.state = 72
+                self.structField()
+                self.state = 77
+                self._errHandler.sync(self)
+                _la = self._input.LA(1)
+
+            self.state = 78
+            self.match(CMODParser.T__6)
+            self.state = 79
+            self.match(CMODParser.T__1)
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class StructFieldContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def typeSpecifier(self):
+            return self.getTypedRuleContext(CMODParser.TypeSpecifierContext,0)
+
+
+        def declarator(self):
+            return self.getTypedRuleContext(CMODParser.DeclaratorContext,0)
+
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_structField
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterStructField" ):
+                listener.enterStructField(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitStructField" ):
+                listener.exitStructField(self)
+
+
+
+
+    def structField(self):
+
+        localctx = CMODParser.StructFieldContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 12, self.RULE_structField)
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 81
+            self.typeSpecifier()
+            self.state = 82
+            self.declarator()
+            self.state = 83
+            self.match(CMODParser.T__1)
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class GlobalDefinitionContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def typeSpecifier(self):
+            return self.getTypedRuleContext(CMODParser.TypeSpecifierContext,0)
+
+
+        def declarator(self):
+            return self.getTypedRuleContext(CMODParser.DeclaratorContext,0)
+
+
+        def expression(self):
+            return self.getTypedRuleContext(CMODParser.ExpressionContext,0)
+
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_globalDefinition
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterGlobalDefinition" ):
+                listener.enterGlobalDefinition(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitGlobalDefinition" ):
+                listener.exitGlobalDefinition(self)
+
+
+
+
+    def globalDefinition(self):
+
+        localctx = CMODParser.GlobalDefinitionContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 14, self.RULE_globalDefinition)
+        self._la = 0 # Token type
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 85
+            self.typeSpecifier()
+            self.state = 86
+            self.declarator()
+            self.state = 89
+            self._errHandler.sync(self)
+            _la = self._input.LA(1)
+            if _la==8:
+                self.state = 87
+                self.match(CMODParser.T__7)
+                self.state = 88
+                self.expression(0)
+
+
+            self.state = 91
+            self.match(CMODParser.T__1)
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class FunctionDefinitionContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def typeSpecifier(self):
+            return self.getTypedRuleContext(CMODParser.TypeSpecifierContext,0)
+
+
+        def declarator(self):
+            return self.getTypedRuleContext(CMODParser.DeclaratorContext,0)
+
+
+        def compoundStatement(self):
+            return self.getTypedRuleContext(CMODParser.CompoundStatementContext,0)
+
+
+        def parameterList(self):
+            return self.getTypedRuleContext(CMODParser.ParameterListContext,0)
+
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_functionDefinition
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterFunctionDefinition" ):
+                listener.enterFunctionDefinition(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitFunctionDefinition" ):
+                listener.exitFunctionDefinition(self)
+
+
+
+
+    def functionDefinition(self):
+
+        localctx = CMODParser.FunctionDefinitionContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 16, self.RULE_functionDefinition)
+        self._la = 0 # Token type
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 93
+            self.typeSpecifier()
+            self.state = 94
+            self.declarator()
+            self.state = 95
+            self.match(CMODParser.T__8)
+            self.state = 97
+            self._errHandler.sync(self)
+            _la = self._input.LA(1)
+            if (((_la) & ~0x3f) == 0 and ((1 << _la) & 8522825760) != 0):
+                self.state = 96
+                self.parameterList()
+
+
+            self.state = 99
+            self.match(CMODParser.T__9)
+            self.state = 100
+            self.compoundStatement()
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class ParameterListContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def typeSpecifier(self, i:int=None):
+            if i is None:
+                return self.getTypedRuleContexts(CMODParser.TypeSpecifierContext)
+            else:
+                return self.getTypedRuleContext(CMODParser.TypeSpecifierContext,i)
+
+
+        def declarator(self, i:int=None):
+            if i is None:
+                return self.getTypedRuleContexts(CMODParser.DeclaratorContext)
+            else:
+                return self.getTypedRuleContext(CMODParser.DeclaratorContext,i)
+
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_parameterList
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterParameterList" ):
+                listener.enterParameterList(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitParameterList" ):
+                listener.exitParameterList(self)
+
+
+
+
+    def parameterList(self):
+
+        localctx = CMODParser.ParameterListContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 18, self.RULE_parameterList)
+        self._la = 0 # Token type
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 102
+            self.typeSpecifier()
+            self.state = 103
+            self.declarator()
+            self.state = 110
+            self._errHandler.sync(self)
+            _la = self._input.LA(1)
+            while _la==11:
+                self.state = 104
+                self.match(CMODParser.T__10)
+                self.state = 105
+                self.typeSpecifier()
+                self.state = 106
+                self.declarator()
+                self.state = 112
+                self._errHandler.sync(self)
+                _la = self._input.LA(1)
+
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class CompoundStatementContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def statement(self, i:int=None):
+            if i is None:
+                return self.getTypedRuleContexts(CMODParser.StatementContext)
+            else:
+                return self.getTypedRuleContext(CMODParser.StatementContext,i)
+
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_compoundStatement
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterCompoundStatement" ):
+                listener.enterCompoundStatement(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitCompoundStatement" ):
+                listener.exitCompoundStatement(self)
+
+
+
+
+    def compoundStatement(self):
+
+        localctx = CMODParser.CompoundStatementContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 20, self.RULE_compoundStatement)
+        self._la = 0 # Token type
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 113
+            self.match(CMODParser.T__5)
+            self.state = 117
+            self._errHandler.sync(self)
+            _la = self._input.LA(1)
+            while (((_la) & ~0x3f) == 0 and ((1 << _la) & 68685921120) != 0):
+                self.state = 114
+                self.statement()
+                self.state = 119
+                self._errHandler.sync(self)
+                _la = self._input.LA(1)
+
+            self.state = 120
+            self.match(CMODParser.T__6)
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class StatementContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def expression(self):
+            return self.getTypedRuleContext(CMODParser.ExpressionContext,0)
+
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_statement
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterStatement" ):
+                listener.enterStatement(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitStatement" ):
+                listener.exitStatement(self)
+
+
+
+
+    def statement(self):
+
+        localctx = CMODParser.StatementContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 22, self.RULE_statement)
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 122
+            self.expression(0)
+            self.state = 123
+            self.match(CMODParser.T__1)
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class ExpressionContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def expression(self, i:int=None):
+            if i is None:
+                return self.getTypedRuleContexts(CMODParser.ExpressionContext)
+            else:
+                return self.getTypedRuleContext(CMODParser.ExpressionContext,i)
+
+
+        def StringLiteral(self):
+            return self.getToken(CMODParser.StringLiteral, 0)
+
+        def Number(self):
+            return self.getToken(CMODParser.Number, 0)
+
+        def typeSpecifier(self):
+            return self.getTypedRuleContext(CMODParser.TypeSpecifierContext,0)
+
+
+        def Identifier(self):
+            return self.getToken(CMODParser.Identifier, 0)
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_expression
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterExpression" ):
+                listener.enterExpression(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitExpression" ):
+                listener.exitExpression(self)
+
+
+
+    def expression(self, _p:int=0):
+        _parentctx = self._ctx
+        _parentState = self.state
+        localctx = CMODParser.ExpressionContext(self, self._ctx, _parentState)
+        _prevctx = localctx
+        _startState = 24
+        self.enterRecursionRule(localctx, 24, self.RULE_expression, _p)
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 162
+            self._errHandler.sync(self)
+            token = self._input.LA(1)
+            if token in [11]:
+                self.state = 126
+                self.match(CMODParser.T__10)
+                pass
+            elif token in [12]:
+                self.state = 127
+                self.match(CMODParser.T__11)
+                pass
+            elif token in [13]:
+                self.state = 128
+                self.match(CMODParser.T__12)
+                pass
+            elif token in [14]:
+                self.state = 129
+                self.match(CMODParser.T__13)
+                pass
+            elif token in [15]:
+                self.state = 130
+                self.match(CMODParser.T__14)
+                pass
+            elif token in [16]:
+                self.state = 131
+                self.match(CMODParser.T__15)
+                pass
+            elif token in [17]:
+                self.state = 132
+                self.match(CMODParser.T__16)
+                pass
+            elif token in [18]:
+                self.state = 133
+                self.match(CMODParser.T__17)
+                pass
+            elif token in [19]:
+                self.state = 134
+                self.match(CMODParser.T__18)
+                pass
+            elif token in [20]:
+                self.state = 135
+                self.match(CMODParser.T__19)
+                pass
+            elif token in [21]:
+                self.state = 136
+                self.match(CMODParser.T__20)
+                pass
+            elif token in [8]:
+                self.state = 137
+                self.match(CMODParser.T__7)
+                pass
+            elif token in [22]:
+                self.state = 138
+                self.match(CMODParser.T__21)
+                pass
+            elif token in [23]:
+                self.state = 139
+                self.match(CMODParser.T__22)
+                pass
+            elif token in [9]:
+                self.state = 140
+                self.match(CMODParser.T__8)
+                self.state = 141
+                self.expression(0)
+                self.state = 142
+                self.match(CMODParser.T__9)
+                pass
+            elif token in [24]:
+                self.state = 144
+                self.match(CMODParser.T__23)
+                self.state = 145
+                self.expression(0)
+                self.state = 146
+                self.match(CMODParser.T__24)
+                pass
+            elif token in [6]:
+                self.state = 148
+                self.match(CMODParser.T__5)
+                self.state = 149
+                self.expression(0)
+                self.state = 150
+                self.match(CMODParser.T__6)
+                pass
+            elif token in [35]:
+                self.state = 152
+                self.match(CMODParser.StringLiteral)
+                pass
+            elif token in [34]:
+                self.state = 153
+                self.match(CMODParser.Number)
+                pass
+            elif token in [5, 26, 27, 28, 29, 30, 31, 32]:
+                self.state = 154
+                self.typeSpecifier()
+                self.state = 158
+                self._errHandler.sync(self)
+                _alt = self._interp.adaptivePredict(self._input,11,self._ctx)
+                while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER:
+                    if _alt==1:
+                        self.state = 155
+                        self.match(CMODParser.T__13) 
+                    self.state = 160
+                    self._errHandler.sync(self)
+                    _alt = self._interp.adaptivePredict(self._input,11,self._ctx)
+
+                pass
+            elif token in [33]:
+                self.state = 161
+                self.match(CMODParser.Identifier)
+                pass
+            else:
+                raise NoViableAltException(self)
+
+            self._ctx.stop = self._input.LT(-1)
+            self.state = 168
+            self._errHandler.sync(self)
+            _alt = self._interp.adaptivePredict(self._input,13,self._ctx)
+            while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER:
+                if _alt==1:
+                    if self._parseListeners is not None:
+                        self.triggerExitRuleEvent()
+                    _prevctx = localctx
+                    localctx = CMODParser.ExpressionContext(self, _parentctx, _parentState)
+                    self.pushNewRecursionContext(localctx, _startState, self.RULE_expression)
+                    self.state = 164
+                    if not self.precpred(self._ctx, 22):
+                        from antlr4.error.Errors import FailedPredicateException
+                        raise FailedPredicateException(self, "self.precpred(self._ctx, 22)")
+                    self.state = 165
+                    self.expression(23) 
+                self.state = 170
+                self._errHandler.sync(self)
+                _alt = self._interp.adaptivePredict(self._input,13,self._ctx)
+
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.unrollRecursionContexts(_parentctx)
+        return localctx
+
+
+    class TypeSpecifierContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def Identifier(self):
+            return self.getToken(CMODParser.Identifier, 0)
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_typeSpecifier
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterTypeSpecifier" ):
+                listener.enterTypeSpecifier(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitTypeSpecifier" ):
+                listener.exitTypeSpecifier(self)
+
+
+
+
+    def typeSpecifier(self):
+
+        localctx = CMODParser.TypeSpecifierContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 26, self.RULE_typeSpecifier)
+        try:
+            self.state = 180
+            self._errHandler.sync(self)
+            token = self._input.LA(1)
+            if token in [26]:
+                self.enterOuterAlt(localctx, 1)
+                self.state = 171
+                self.match(CMODParser.T__25)
+                pass
+            elif token in [27]:
+                self.enterOuterAlt(localctx, 2)
+                self.state = 172
+                self.match(CMODParser.T__26)
+                pass
+            elif token in [28]:
+                self.enterOuterAlt(localctx, 3)
+                self.state = 173
+                self.match(CMODParser.T__27)
+                pass
+            elif token in [29]:
+                self.enterOuterAlt(localctx, 4)
+                self.state = 174
+                self.match(CMODParser.T__28)
+                pass
+            elif token in [30]:
+                self.enterOuterAlt(localctx, 5)
+                self.state = 175
+                self.match(CMODParser.T__29)
+                pass
+            elif token in [31]:
+                self.enterOuterAlt(localctx, 6)
+                self.state = 176
+                self.match(CMODParser.T__30)
+                pass
+            elif token in [32]:
+                self.enterOuterAlt(localctx, 7)
+                self.state = 177
+                self.match(CMODParser.T__31)
+                pass
+            elif token in [5]:
+                self.enterOuterAlt(localctx, 8)
+                self.state = 178
+                self.match(CMODParser.T__4)
+                self.state = 179
+                self.match(CMODParser.Identifier)
+                pass
+            else:
+                raise NoViableAltException(self)
+
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class DeclaratorContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def Identifier(self):
+            return self.getToken(CMODParser.Identifier, 0)
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_declarator
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterDeclarator" ):
+                listener.enterDeclarator(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitDeclarator" ):
+                listener.exitDeclarator(self)
+
+
+
+
+    def declarator(self):
+
+        localctx = CMODParser.DeclaratorContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 28, self.RULE_declarator)
+        self._la = 0 # Token type
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 183
+            self._errHandler.sync(self)
+            _la = self._input.LA(1)
+            if _la==14:
+                self.state = 182
+                self.match(CMODParser.T__13)
+
+
+            self.state = 185
+            self.match(CMODParser.Identifier)
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+
+    def sempred(self, localctx:RuleContext, ruleIndex:int, predIndex:int):
+        if self._predicates == None:
+            self._predicates = dict()
+        self._predicates[12] = self.expression_sempred
+        pred = self._predicates.get(ruleIndex, None)
+        if pred is None:
+            raise Exception("No predicate with index:" + str(ruleIndex))
+        else:
+            return pred(localctx, predIndex)
+
+    def expression_sempred(self, localctx:ExpressionContext, predIndex:int):
+            if predIndex == 0:
+                return self.precpred(self._ctx, 22)
+         
+
+
+
+
Index: doc/proposals/modules-alvin/3_implementation_details/prototype/requirements.txt
===================================================================
--- doc/proposals/modules-alvin/3_implementation_details/prototype/requirements.txt	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
+++ doc/proposals/modules-alvin/3_implementation_details/prototype/requirements.txt	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
@@ -0,0 +1,1 @@
+antlr4-python3-runtime==4.13.2
Index: doc/proposals/modules-alvin/3_implementation_details/prototype/testing/a.cmod
===================================================================
--- doc/proposals/modules-alvin/3_implementation_details/prototype/testing/a.cmod	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
+++ doc/proposals/modules-alvin/3_implementation_details/prototype/testing/a.cmod	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
@@ -0,0 +1,11 @@
+module A;
+
+import Basic;
+
+export struct S foo(int i, int j, int k) {
+    struct S s;
+    s.i = i;
+    s.j = j;
+    s.k = f(k);
+    return s;
+}
Index: doc/proposals/modules-alvin/3_implementation_details/prototype/testing/basic.cmod
===================================================================
--- doc/proposals/modules-alvin/3_implementation_details/prototype/testing/basic.cmod	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
+++ doc/proposals/modules-alvin/3_implementation_details/prototype/testing/basic.cmod	(revision 893fb47b2db218374db74879e660c64fc69c93a3)
@@ -0,0 +1,24 @@
+module Basic;
+
+export struct S {
+    int i;
+    int j;
+    struct SS k;
+};
+
+struct SS {
+    struct S *a;
+    float b;
+};
+
+export struct SS f(int i) {
+    struct SS ss;
+    ss.b = ff(i);
+    return ss;
+}
+
+float ff(int i) {
+    return (float) i + j;
+}
+
+float j = 4.4;
