diff --git a/src/snc/expr.h b/src/snc/expr.h
index 9ff21050c8ae4bf43eea268b8d07fd9d5e97b3b1..67431a2a811f2fbd8d2e41e61e54257d080e3803 100644
--- a/src/snc/expr.h
+++ b/src/snc/expr.h
@@ -46,5 +46,6 @@ Expr *decl_create(Token name);
 Expr *decl_postfix_array(Expr *d, char *s);
 Expr *decl_postfix_function(Expr *d, Expr *args);
 Expr *decl_prefix_pointer(Expr *d);
+Expr *decl_prefix_const(Expr *d);
 
 #endif	/*INCLparseh*/
diff --git a/src/snc/snl.lem b/src/snc/snl.lem
index 7e017f307f293308d718d9a617190fcb2278ee9c..f61b7887efb473fcc18c0a6d2d3b3343f4fc65b8 100644
--- a/src/snc/snl.lem
+++ b/src/snc/snl.lem
@@ -194,6 +194,7 @@ declarator(p) ::= declarator(x)
 		LPAREN param_decls(ps) RPAREN.	[POST]	{ p = decl_postfix_function(x, ps); }
 declarator(p) ::= LPAREN declarator(x) RPAREN.	[PRE]	{ p = x; }
 declarator(p) ::= ASTERISK declarator(x).	[PRE]	{ p = decl_prefix_pointer(x); }
+declarator(p) ::= CONST declarator(x).		[PRE]	{ p = decl_prefix_const(x); }
 
 param_decls(p) ::= param_decl(x).			{ p = x; }
 param_decls(p) ::= param_decls(xs) COMMA param_decl(x).	{ p = link_expr(xs, x); }
@@ -257,6 +258,8 @@ type_expr(p) ::= basetype(t) abs_decl(d).	{ p = decl_add_base_type(d, t); }
 abs_decl(p) ::= LPAREN abs_decl(x) RPAREN.	{ p = x; }
 abs_decl(p) ::= ASTERISK. [PRE]			{ p = decl_prefix_pointer(abs_decl_create()); }
 abs_decl(p) ::= ASTERISK abs_decl(d). [PRE]	{ p = decl_prefix_pointer(d); }
+abs_decl(p) ::= CONST. [PRE]			{ p = decl_prefix_const(abs_decl_create()); }
+abs_decl(p) ::= CONST abs_decl(d). [PRE]	{ p = decl_prefix_const(d); }
 abs_decl(p) ::= subscript(s). [POST]		{ p = decl_postfix_array(abs_decl_create(), s.str); }
 abs_decl(p) ::= abs_decl(d) subscript(s). [POST]{ p = decl_postfix_array(d, s.str); }
 abs_decl(p) ::= LPAREN param_decls(ps) RPAREN. [POST]
diff --git a/src/snc/snl.re b/src/snc/snl.re
index 267b7d9505f84dca5c490fa756cccabc1329dae0..3d514522b19845afd23f31080ea9031124f73d32 100644
--- a/src/snc/snl.re
+++ b/src/snc/snl.re
@@ -234,6 +234,7 @@ snl:
 	"break"		{ KEYWORD(BREAK,	"break"); }
 	"char"		{ TYPEWORD(CHAR,	"char"); }
 	"connect"	{ KEYWORD(CONNECT,	"connect"); }
+	"const"		{ TYPEWORD(CONST,	"const"); }
 	"continue"	{ KEYWORD(CONTINUE,	"continue"); }
 	"double"	{ TYPEWORD(DOUBLE,	"double"); }
 	"else"		{ KEYWORD(ELSE,		"else"); }
diff --git a/src/snc/var_types.c b/src/snc/var_types.c
index 3c2cb6e1754a16d9b2b86b13c679803a6f96b815..e22e6839014e0627c3f7a28fbb414d02918787f8 100644
--- a/src/snc/var_types.c
+++ b/src/snc/var_types.c
@@ -64,6 +64,33 @@ Expr *decl_add_base_type(Expr *ds, Type basetype)
                 }
                 t->parent->val.function.return_type = t;
                 break;
+            case T_CONST:
+                switch (t->tag) {
+                case T_NONE:
+                    error_at_expr(d, "cannot declare constant foreign entity\n");
+                    break;
+                case T_EVFLAG:
+                    error_at_expr(d, "cannot declare constant event flag\n");
+                    break;
+                case T_VOID:
+                    error_at_expr(d, "cannot declare constant void\n");
+                    break;
+                case T_ARRAY:
+                    error_at_expr(d, "cannot declare constant array\n");
+                    break;
+                case T_FUNCTION:
+                    warning_at_expr(d, "declaring constant function is redundant\n");
+                    break;
+                case T_CONST:
+                    warning_at_expr(d, "declaring constant constant is redundant\n");
+                    break;
+                case T_PRIM:
+                case T_FOREIGN:
+                case T_POINTER:
+                    break;
+                }
+                t->parent->val.constant.value_type = t;
+                break;
             default:
                 assert(impossible);
             }
@@ -163,6 +190,19 @@ Expr *decl_prefix_pointer(Expr *d)
     return d;
 }
 
+Expr *decl_prefix_const(Expr *d)
+{
+    Type *t = new(Type);
+
+#ifdef DEBUG
+    report("decl_prefix_const\n");
+#endif
+    assert(d->type == D_DECL);          /* pre-condition */
+    t->tag = T_CONST;
+    t->parent = d->extra.e_decl->type;
+    d->extra.e_decl->type = t;
+    return d;
+}
 
 Type mk_prim_type(enum prim_type_tag tag)
 {
@@ -248,6 +288,7 @@ static unsigned type_assignable_array(Type *t, int depth)
     case T_FUNCTION:
     case T_EVFLAG:
     case T_VOID:
+    case T_CONST:
         return FALSE;
     case T_ARRAY:
         return type_assignable_array(t->val.array.elem_type, depth + 1);
@@ -278,6 +319,16 @@ static void gen_array_pointer(Type *t, enum type_tag last_tag, const char *prefi
         if (paren)
             gen_code(")");
         break;
+    case T_CONST:
+        if (paren)
+            gen_code("(");
+        else
+            gen_code(" ");
+        gen_code("const");
+        gen_array_pointer(t->parent, t->tag, prefix, name);
+        if (paren)
+            gen_code(")");
+        break;
     case T_ARRAY:
         gen_array_pointer(t->parent, t->tag, prefix, name);
         gen_code("[%d]", t->val.array.num_elems);
diff --git a/src/snc/var_types.h b/src/snc/var_types.h
index ba48b05f7662feb6f43bfbfacc14260d68e37812..2194fbeca11ce3bcb76a01426f25630071e6e62e 100644
--- a/src/snc/var_types.h
+++ b/src/snc/var_types.h
@@ -18,6 +18,7 @@ enum type_tag {
     T_POINTER,
     T_ARRAY,
     T_FUNCTION,
+    T_CONST,
 };
 
 enum foreign_type_tag {
@@ -36,6 +37,10 @@ struct pointer_type {
     struct type *value_type;
 };
 
+struct constant_type {
+    struct type *value_type;
+};
+
 struct function_type {
     struct expression *param_decls;
     struct type *return_type;
@@ -56,6 +61,7 @@ struct type {
         struct pointer_type     pointer;
         struct array_type       array;
         struct function_type    function;
+        struct constant_type    constant;
     } val;
     struct type *parent;
 };
diff --git a/test/compiler/type_expr.st b/test/compiler/type_expr.st
index fa2415b06c80afccf1a53a15d2a80e4b6e29e708..7f95c815a05ae8eb27cce17344a82928bf1a2531 100644
--- a/test/compiler/type_expr.st
+++ b/test/compiler/type_expr.st
@@ -33,6 +33,9 @@ entry {
     void (*pf4)(int**) = (void (*)(int**))n;
     void (*pf5)(double**,int) = (void (*)(double**,int))n;
     void (*pf6)(double**,int(**)[2]) = (void (*)(double**,int(**)[2]))n;
+    int const c = (int const)n;
+    int const *pc = (int const *)n;
+    unsigned long *const cp = (unsigned long *const)n;
     double **pd = (double**)(int*)n;
     double **ppd = (double**)(int(*)[3])n;
     void (*lf)(
@@ -44,6 +47,9 @@ entry {
         void (*pf4)(int**),
         void (*pf5)(double**,int),
         void (*pf6)(double**,int(**)[2]),
+        int const c,
+        int const *pc,
+        unsigned long *const cp,
         double **pd,
         double **ppd
     ) = (void (*)(
@@ -55,10 +61,13 @@ entry {
         void (*pf4)(int**),
         void (*pf5)(double**,int),
         void (*pf6)(double**,int(**)[2]),
+        int const c,
+        int const *pc,
+        unsigned long *const cp,
         double **pd,
         double **ppd
     ))n;
-    lf(p,pp,pf1,pf2,pf3,pf4,pf5,pf6,pd,ppd);
+    lf(p,pp,pf1,pf2,pf3,pf4,pf5,pf6,c,pc,cp,pd,ppd);
 }
 
 #include "../simple.st"