| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | // Copyright 2009 The Go Authors.  All rights reserved. | 
					
						
							|  |  |  | // Use of this source code is governed by a BSD-style | 
					
						
							|  |  |  | // license that can be found in the LICENSE file. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package Parser | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | import Utils "utils" | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | import Scanner "scanner" | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | import Globals "globals" | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | import Object "object" | 
					
						
							|  |  |  | import Type "type" | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | import Universe "universe" | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | import Import "import" | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | import AST "ast" | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-04 15:37:47 -07:00
										 |  |  | export type Parser struct { | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 	comp *Globals.Compilation; | 
					
						
							| 
									
										
										
										
											2008-07-30 17:36:03 -07:00
										 |  |  | 	semantic_checks bool; | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 	verbose bool; | 
					
						
							|  |  |  | 	indent uint; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	S *Scanner.Scanner; | 
					
						
							| 
									
										
										
										
											2008-08-06 18:57:37 -07:00
										 |  |  | 	C *chan *Scanner.Token; | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	// Token | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	tok int;  // one token look-ahead | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 	pos int;  // token source position | 
					
						
							|  |  |  | 	val string;  // token value (for IDENT, NUMBER, STRING only) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Semantic analysis | 
					
						
							| 
									
										
										
										
											2008-07-30 21:26:15 -07:00
										 |  |  | 	level int;  // 0 = global scope, -1 = function/struct scope of global functions/structs, etc. | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	top_scope *Globals.Scope; | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 	forward_types *Globals.List; | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 	exports *Globals.List; | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | // ---------------------------------------------------------------------------- | 
					
						
							|  |  |  | // Support functions | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | func (P *Parser) PrintIndent() { | 
					
						
							|  |  |  | 	for i := P.indent; i > 0; i-- { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 		print(". "); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) Trace(msg string) { | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 	if P.verbose { | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.PrintIndent(); | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 		print(msg, " {\n"); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 	P.indent++; | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) Ecart() { | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 	P.indent--; | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 	if P.verbose { | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.PrintIndent(); | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 		print("}\n"); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) Next() { | 
					
						
							| 
									
										
										
										
											2008-08-06 18:57:37 -07:00
										 |  |  | 	if P.C == nil { | 
					
						
							|  |  |  | 		P.tok, P.pos, P.val = P.S.Scan(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		t := <- P.C; | 
					
						
							|  |  |  | 		P.tok, P.pos, P.val = t.tok, t.pos, t.val; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 	if P.verbose { | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.PrintIndent(); | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 		print("[", P.pos, "] ", Scanner.TokenName(P.tok), "\n"); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-06 18:57:37 -07:00
										 |  |  | func (P *Parser) Open(comp *Globals.Compilation, S *Scanner.Scanner, C *chan *Scanner.Token) { | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 	P.comp = comp; | 
					
						
							| 
									
										
										
										
											2008-08-07 19:32:22 -07:00
										 |  |  | 	P.semantic_checks = comp.flags.ast; | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 	P.verbose = comp.flags.verbosity > 2; | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.indent = 0; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.S = S; | 
					
						
							| 
									
										
										
										
											2008-08-06 18:57:37 -07:00
										 |  |  | 	P.C = C; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 	P.level = 0; | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.top_scope = Universe.scope; | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 	P.forward_types = Globals.NewList(); | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 	P.exports = Globals.NewList(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-10 14:42:33 -07:00
										 |  |  | func (P *Parser) Error(pos int, msg string) { | 
					
						
							|  |  |  | 	P.S.Error(pos, msg); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) Expect(tok int) { | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	if P.tok != tok { | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 		P.Error(P.pos, "expected '" + Scanner.TokenName(tok) + "', found '" + Scanner.TokenName(P.tok) + "'"); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	P.Next();  // make progress in any case | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | func (P *Parser) Optional(tok int) { | 
					
						
							|  |  |  | 	if P.tok == tok { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | // ---------------------------------------------------------------------------- | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | // Scopes | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) OpenScope() { | 
					
						
							|  |  |  | 	P.top_scope = Globals.NewScope(P.top_scope); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) CloseScope() { | 
					
						
							|  |  |  | 	P.top_scope = P.top_scope.parent; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) Lookup(ident string) *Globals.Object { | 
					
						
							|  |  |  | 	for scope := P.top_scope; scope != nil; scope = scope.parent { | 
					
						
							|  |  |  | 		obj := scope.Lookup(ident); | 
					
						
							|  |  |  | 		if obj != nil { | 
					
						
							|  |  |  | 			return obj; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) DeclareInScope(scope *Globals.Scope, obj *Globals.Object) { | 
					
						
							| 
									
										
										
										
											2008-07-30 17:36:03 -07:00
										 |  |  | 	if !P.semantic_checks { | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 	if P.level > 0 { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 		panic("cannot declare objects in other packages"); | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 	obj.pnolev = P.level; | 
					
						
							|  |  |  | 	if scope.Lookup(obj.ident) != nil { | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		P.Error(obj.pos, `"` + obj.ident + `" is declared already`); | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 		return;  // don't insert it into the scope | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	scope.Insert(obj); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) Declare(obj *Globals.Object) { | 
					
						
							|  |  |  | 	P.DeclareInScope(P.top_scope, obj); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | func MakeFunctionType(sig *Globals.Scope, p0, r0 int, check_recv bool) *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 	// Determine if we have a receiver or not. | 
					
						
							|  |  |  | 	// TODO do we still need this? | 
					
						
							|  |  |  | 	if p0 > 0 && check_recv { | 
					
						
							|  |  |  | 		// method | 
					
						
							|  |  |  | 		if p0 != 1 { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 			panic("p0 != 1"); | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	typ := Globals.NewType(Type.FUNCTION); | 
					
						
							|  |  |  | 	if p0 == 0 { | 
					
						
							|  |  |  | 		typ.flags = 0; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		typ.flags = Type.RECV; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	typ.len_ = r0 - p0; | 
					
						
							|  |  |  | 	typ.scope = sig; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// parameters are always exported (they can't be accessed w/o the function | 
					
						
							|  |  |  | 	// or function type being exported) | 
					
						
							|  |  |  | 	for p := sig.entries.first; p != nil; p = p.next { | 
					
						
							|  |  |  | 		p.obj.exported = true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return typ; | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | func (P *Parser) DeclareFunc(pos int, ident string, typ *Globals.Type) *Globals.Object { | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 	// determine scope | 
					
						
							|  |  |  | 	scope := P.top_scope; | 
					
						
							|  |  |  | 	if typ.flags & Type.RECV != 0 { | 
					
						
							|  |  |  | 		// method - declare in corresponding struct | 
					
						
							|  |  |  | 		if typ.scope.entries.len_ < 1 { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 			panic("no recv in signature?"); | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		recv_typ := typ.scope.entries.first.obj.typ; | 
					
						
							|  |  |  | 		if recv_typ.form == Type.POINTER { | 
					
						
							|  |  |  | 			recv_typ = recv_typ.elt; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		scope = recv_typ.scope; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// declare the function | 
					
						
							|  |  |  | 	obj := scope.Lookup(ident); | 
					
						
							|  |  |  | 	if obj == nil { | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 		obj = Globals.NewObject(pos, Object.FUNC, ident); | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 		obj.typ = typ; | 
					
						
							|  |  |  | 		// TODO do we need to set the primary type? probably... | 
					
						
							|  |  |  | 		P.DeclareInScope(scope, obj); | 
					
						
							|  |  |  | 		return obj; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 	// obj != NULL: possibly a forward declaration | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 	if obj.kind != Object.FUNC { | 
					
						
							|  |  |  | 		P.Error(-1, `"` + ident + `" is declared already`); | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 		// continue but do not insert this function into the scope | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 		obj = Globals.NewObject(-1, Object.FUNC, ident); | 
					
						
							|  |  |  | 		obj.typ = typ; | 
					
						
							|  |  |  | 		// TODO do we need to set the primary type? probably... | 
					
						
							|  |  |  | 		return obj; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 	// we have a function with the same name | 
					
						
							|  |  |  | 	if !Type.Equal(typ, obj.typ) { | 
					
						
							|  |  |  | 		P.Error(-1, `type of "` + ident + `" does not match its forward declaration`); | 
					
						
							|  |  |  | 		// continue but do not insert this function into the scope | 
					
						
							|  |  |  | 		obj = Globals.NewObject(-1, Object.FUNC, ident); | 
					
						
							|  |  |  | 		obj.typ = typ; | 
					
						
							|  |  |  | 		// TODO do we need to set the primary type? probably... | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 		return obj;     | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// We have a matching forward declaration. Use it. | 
					
						
							|  |  |  | 	return obj; | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | // ---------------------------------------------------------------------------- | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | // Common productions | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) TryType() *Globals.Type; | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | func (P *Parser) ParseExpression() Globals.Expr; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) TryStatement() bool; | 
					
						
							|  |  |  | func (P *Parser) ParseDeclaration(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | func (P *Parser) ParseIdent(allow_keyword bool) (pos int, ident string) { | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	P.Trace("Ident"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 	pos, ident = P.pos, ""; | 
					
						
							|  |  |  | 	// NOTE Can make this faster by not doing the keyword lookup in the | 
					
						
							|  |  |  | 	// scanner if we don't care about keywords. | 
					
						
							|  |  |  | 	if P.tok == Scanner.IDENT || allow_keyword && P.tok > Scanner.IDENT { | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 		ident = P.val; | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 		if P.verbose { | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 			P.PrintIndent(); | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 			print("Ident = \"", ident, "\"\n"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		P.Expect(Scanner.IDENT);  // use Expect() error handling | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 	return pos, ident; | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseIdentDecl(kind int) *Globals.Object { | 
					
						
							|  |  |  | 	P.Trace("IdentDecl"); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 	pos, ident := P.ParseIdent(kind == Object.FIELD); | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 	obj := Globals.NewObject(pos, kind, ident); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	P.Declare(obj); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | 	return obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseIdentDeclList(kind int) *Globals.List { | 
					
						
							|  |  |  | 	P.Trace("IdentDeclList"); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	list := Globals.NewList(); | 
					
						
							|  |  |  | 	list.AddObj(P.ParseIdentDecl(kind)); | 
					
						
							|  |  |  | 	for P.tok == Scanner.COMMA { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		list.AddObj(P.ParseIdentDecl(kind)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | 	return list; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseIdentList() { | 
					
						
							|  |  |  | 	P.Trace("IdentList"); | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 	P.ParseIdent(false); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	for P.tok == Scanner.COMMA { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 		P.ParseIdent(false); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | func (P *Parser) ParseQualifiedIdent(pos int, ident string) *Globals.Object { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Trace("QualifiedIdent"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	if pos < 0 { | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 		pos, ident = P.ParseIdent(false); | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-30 17:36:03 -07:00
										 |  |  | 	if P.semantic_checks { | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		obj := P.Lookup(ident); | 
					
						
							|  |  |  | 		if obj == nil { | 
					
						
							|  |  |  | 			P.Error(pos, `"` + ident + `" is not declared`); | 
					
						
							|  |  |  | 			obj = Globals.NewObject(pos, Object.BAD, ident); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if obj.kind == Object.PACKAGE && P.tok == Scanner.PERIOD { | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 			if obj.pnolev < 0 { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 				panic("obj.pnolev < 0"); | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-08-04 10:19:36 -07:00
										 |  |  | 			pkg := P.comp.pkg_list[obj.pnolev]; | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 			//if pkg.obj.ident != ident { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 			//	panic("pkg.obj.ident != ident"); | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 			//} | 
					
						
							|  |  |  | 			P.Next();  // consume "." | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 			pos, ident = P.ParseIdent(false); | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 			obj = pkg.scope.Lookup(ident); | 
					
						
							|  |  |  | 			if obj == nil { | 
					
						
							|  |  |  | 				P.Error(pos, `"` + ident + `" is not declared in package "` + pkg.obj.ident + `"`); | 
					
						
							|  |  |  | 				obj = Globals.NewObject(pos, Object.BAD, ident); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		P.Ecart(); | 
					
						
							|  |  |  | 		return obj; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		if P.tok == Scanner.PERIOD { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 			P.ParseIdent(false); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		P.Ecart(); | 
					
						
							|  |  |  | 		return nil; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | // ---------------------------------------------------------------------------- | 
					
						
							|  |  |  | // Types | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | func (P *Parser) ParseType() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	P.Trace("Type"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	typ := P.TryType(); | 
					
						
							|  |  |  | 	if typ == nil { | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 		P.Error(P.pos, "type expected"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		typ = Universe.bad_t; | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	return typ; | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | func (P *Parser) ParseVarType() *Globals.Type { | 
					
						
							|  |  |  | 	P.Trace("VarType"); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	pos := P.pos; | 
					
						
							|  |  |  | 	typ := P.ParseType(); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if P.semantic_checks { | 
					
						
							|  |  |  | 		switch typ.form { | 
					
						
							|  |  |  | 		case Type.ARRAY: | 
					
						
							|  |  |  | 			if P.comp.flags.sixg || typ.len_ >= 0 { | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// open arrays must be pointers | 
					
						
							|  |  |  | 			fallthrough; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 		case Type.MAP, Type.CHANNEL, Type.FUNCTION: | 
					
						
							|  |  |  | 			P.Error(pos, "must be pointer to this type"); | 
					
						
							|  |  |  | 			typ = Universe.bad_t; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | 	return typ; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) ParseTypeName() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("TypeName"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-30 17:36:03 -07:00
										 |  |  | 	if P.semantic_checks { | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 		pos := P.pos; | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 		obj := P.ParseQualifiedIdent(-1, ""); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		typ := obj.typ; | 
					
						
							|  |  |  | 		if obj.kind != Object.TYPE { | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 			P.Error(pos, "qualified identifier does not denote a type"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 			typ = Universe.bad_t; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		P.Ecart(); | 
					
						
							|  |  |  | 		return typ; | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 		P.ParseQualifiedIdent(-1, ""); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		P.Ecart(); | 
					
						
							|  |  |  | 		return Universe.bad_t; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) ParseArrayType() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Trace("ArrayType"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Expect(Scanner.LBRACK); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	typ := Globals.NewType(Type.ARRAY); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	if P.tok != Scanner.RBRACK { | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 		// TODO set typ.len_ | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		P.ParseExpression(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.RBRACK); | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | 	typ.elt = P.ParseVarType(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	return typ; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) ParseChannelType() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Trace("ChannelType"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	P.Expect(Scanner.CHAN); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	typ := Globals.NewType(Type.CHANNEL); | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	switch P.tok { | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	case Scanner.SEND: | 
					
						
							|  |  |  | 		typ.flags = Type.SEND; | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-16 17:00:48 -07:00
										 |  |  | 	case Scanner.RECV: | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 		typ.flags = Type.RECV; | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 		typ.flags = Type.SEND + Type.RECV; | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | 	typ.elt = P.ParseVarType(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return typ; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | func (P *Parser) ParseVarDeclList(kind int) { | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	P.Trace("VarDeclList"); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 	list := P.ParseIdentDeclList(kind); | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | 	typ := P.ParseVarType(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	for p := list.first; p != nil; p = p.next { | 
					
						
							|  |  |  | 		p.obj.typ = typ;  // TODO should use/have set_type() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseParameterList() { | 
					
						
							|  |  |  | 	P.Trace("ParameterList"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 	P.ParseVarDeclList(Object.VAR); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	for P.tok == Scanner.COMMA { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 		P.ParseVarDeclList(Object.VAR); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseParameters() { | 
					
						
							|  |  |  | 	P.Trace("Parameters"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.LPAREN); | 
					
						
							|  |  |  | 	if P.tok != Scanner.RPAREN { | 
					
						
							|  |  |  | 		P.ParseParameterList(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.RPAREN); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) TryResult() bool { | 
					
						
							|  |  |  | 	P.Trace("Result (try)"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	res := false; | 
					
						
							|  |  |  | 	if P.tok == Scanner.LPAREN { | 
					
						
							|  |  |  | 		// TODO: here we allow empty returns - should proably fix this | 
					
						
							|  |  |  | 		P.ParseParameters(); | 
					
						
							|  |  |  | 		res = true; | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		res = P.TryType() != nil; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Anonymous signatures | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //          (params) | 
					
						
							|  |  |  | //          (params) type | 
					
						
							|  |  |  | //          (params) (results) | 
					
						
							|  |  |  | // (recv) . (params) | 
					
						
							|  |  |  | // (recv) . (params) type | 
					
						
							|  |  |  | // (recv) . (params) (results) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | func (P *Parser) ParseAnonymousSignature() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("AnonymousSignature"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.OpenScope(); | 
					
						
							| 
									
										
										
										
											2008-07-30 21:26:15 -07:00
										 |  |  | 	P.level--; | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	sig := P.top_scope; | 
					
						
							|  |  |  | 	p0 := 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	recv_pos := P.pos; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.ParseParameters(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	if P.tok == Scanner.PERIOD { | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 		p0 = sig.entries.len_; | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 		if P.semantic_checks && p0 != 1 { | 
					
						
							| 
									
										
										
										
											2008-09-02 17:26:00 -07:00
										 |  |  | 			P.Error(recv_pos, "must have exactly one receiver"); | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 			panic("UNIMPLEMENTED (ParseAnonymousSignature)"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 			// TODO do something useful here | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseParameters(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	r0 := sig.entries.len_; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.TryResult(); | 
					
						
							| 
									
										
										
										
											2008-07-30 21:26:15 -07:00
										 |  |  | 	P.level++; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.CloseScope(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	return MakeFunctionType(sig, p0, r0, true); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Named signatures | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | //        ident (params) | 
					
						
							|  |  |  | //        ident (params) type | 
					
						
							|  |  |  | //        ident (params) (results) | 
					
						
							|  |  |  | // (recv) ident (params) | 
					
						
							|  |  |  | // (recv) ident (params) type | 
					
						
							|  |  |  | // (recv) ident (params) (results) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseNamedSignature() (pos int, ident string, typ *Globals.Type) { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("NamedSignature"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.OpenScope(); | 
					
						
							| 
									
										
										
										
											2008-07-30 21:26:15 -07:00
										 |  |  | 	P.level--; | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	sig := P.top_scope; | 
					
						
							|  |  |  | 	p0 := 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	if P.tok == Scanner.LPAREN { | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 		recv_pos := P.pos; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		P.ParseParameters(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 		p0 = sig.entries.len_; | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 		if P.semantic_checks && p0 != 1 { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 			print("p0 = ", p0, "\n"); | 
					
						
							| 
									
										
										
										
											2008-09-02 17:26:00 -07:00
										 |  |  | 			P.Error(recv_pos, "must have exactly one receiver"); | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 			panic("UNIMPLEMENTED (ParseNamedSignature)"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 			// TODO do something useful here | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 	pos, ident = P.ParseIdent(true); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.ParseParameters(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	r0 := sig.entries.len_; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.TryResult(); | 
					
						
							| 
									
										
										
										
											2008-07-30 21:26:15 -07:00
										 |  |  | 	P.level++; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.CloseScope(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 	return pos, ident, MakeFunctionType(sig, p0, r0, true); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) ParseFunctionType() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("FunctionType"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.FUNC); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	typ := P.ParseAnonymousSignature(); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	return typ; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-07-09 10:45:04 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-01 13:33:31 -07:00
										 |  |  | func (P *Parser) ParseMethodDecl(recv_typ *Globals.Type) { | 
					
						
							| 
									
										
										
										
											2008-07-09 10:45:04 -07:00
										 |  |  | 	P.Trace("MethodDecl"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 	pos, ident := P.ParseIdent(true); | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 	P.OpenScope(); | 
					
						
							| 
									
										
										
										
											2008-07-30 21:26:15 -07:00
										 |  |  | 	P.level--; | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 	sig := P.top_scope; | 
					
						
							| 
									
										
										
										
											2008-08-01 13:33:31 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | 	// dummy receiver (give it a name so it won't conflict with unnamed result) | 
					
						
							| 
									
										
										
										
											2008-08-01 13:33:31 -07:00
										 |  |  | 	recv := Globals.NewObject(pos, Object.VAR, ".recv"); | 
					
						
							|  |  |  | 	recv.typ = recv_typ; | 
					
						
							|  |  |  | 	sig.Insert(recv); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 10:45:04 -07:00
										 |  |  | 	P.ParseParameters(); | 
					
						
							| 
									
										
										
										
											2008-08-01 13:33:31 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 	r0 := sig.entries.len_; | 
					
						
							| 
									
										
										
										
											2008-07-09 10:45:04 -07:00
										 |  |  | 	P.TryResult(); | 
					
						
							| 
									
										
										
										
											2008-07-30 21:26:15 -07:00
										 |  |  | 	P.level++; | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 	P.CloseScope(); | 
					
						
							| 
									
										
										
										
											2008-07-09 10:45:04 -07:00
										 |  |  | 	P.Optional(Scanner.SEMICOLON); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | 	obj := Globals.NewObject(pos, Object.FUNC, ident); | 
					
						
							|  |  |  | 	obj.typ = MakeFunctionType(sig, 1, r0, true); | 
					
						
							|  |  |  | 	P.Declare(obj); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 10:45:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) ParseInterfaceType() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Trace("InterfaceType"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 10:45:04 -07:00
										 |  |  | 	P.Expect(Scanner.INTERFACE); | 
					
						
							|  |  |  | 	P.Expect(Scanner.LBRACE); | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.OpenScope(); | 
					
						
							| 
									
										
										
										
											2008-07-30 21:26:15 -07:00
										 |  |  | 	P.level--; | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	typ := Globals.NewType(Type.INTERFACE); | 
					
						
							|  |  |  | 	typ.scope = P.top_scope; | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 	for P.tok >= Scanner.IDENT { | 
					
						
							| 
									
										
										
										
											2008-08-01 13:33:31 -07:00
										 |  |  | 		P.ParseMethodDecl(typ); | 
					
						
							| 
									
										
										
										
											2008-07-09 10:45:04 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-30 21:26:15 -07:00
										 |  |  | 	P.level++; | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.CloseScope(); | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	P.Expect(Scanner.RBRACE); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	return typ; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) ParseMapType() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Trace("MapType"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Expect(Scanner.MAP); | 
					
						
							|  |  |  | 	P.Expect(Scanner.LBRACK); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	typ := Globals.NewType(Type.MAP); | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 	typ.aux = P.ParseVarType(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Expect(Scanner.RBRACK); | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | 	typ.elt = P.ParseVarType(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	return typ; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) ParseStructType() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Trace("StructType"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Expect(Scanner.STRUCT); | 
					
						
							|  |  |  | 	P.Expect(Scanner.LBRACE); | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.OpenScope(); | 
					
						
							| 
									
										
										
										
											2008-07-30 21:26:15 -07:00
										 |  |  | 	P.level--; | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	typ := Globals.NewType(Type.STRUCT); | 
					
						
							|  |  |  | 	typ.scope = P.top_scope; | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 	for P.tok >= Scanner.IDENT { | 
					
						
							|  |  |  | 		P.ParseVarDeclList(Object.FIELD); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		if P.tok != Scanner.RBRACE { | 
					
						
							|  |  |  | 			P.Expect(Scanner.SEMICOLON); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	P.Optional(Scanner.SEMICOLON); | 
					
						
							| 
									
										
										
										
											2008-07-30 21:26:15 -07:00
										 |  |  | 	P.level++; | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.CloseScope(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Expect(Scanner.RBRACE); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	return typ; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) ParsePointerType() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Trace("PointerType"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Expect(Scanner.MUL); | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 	typ := Globals.NewType(Type.POINTER); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 	var elt *Globals.Type; | 
					
						
							| 
									
										
										
										
											2008-08-11 18:44:41 -07:00
										 |  |  | 	if P.semantic_checks { | 
					
						
							|  |  |  | 		if P.tok == Scanner.STRING && !P.comp.flags.sixg { | 
					
						
							|  |  |  | 			// implicit package.type forward declaration | 
					
						
							|  |  |  | 			// TODO eventually the scanner should strip the quotes | 
					
						
							|  |  |  | 			pkg_name := P.val[1 : len(P.val) - 1];  // strip quotes | 
					
						
							|  |  |  | 			pkg := P.comp.Lookup(pkg_name); | 
					
						
							|  |  |  | 			if pkg == nil { | 
					
						
							|  |  |  | 				// package doesn't exist yet - add it to the package list | 
					
						
							|  |  |  | 				obj := Globals.NewObject(P.pos, Object.PACKAGE, ".pkg"); | 
					
						
							|  |  |  | 				pkg = Globals.NewPackage(pkg_name, obj, Globals.NewScope(nil)); | 
					
						
							|  |  |  | 				pkg.key = "";  // mark as forward-declared package | 
					
						
							|  |  |  | 				P.comp.Insert(pkg); | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				// package exists already - must be forward declaration | 
					
						
							|  |  |  | 				if pkg.key != "" { | 
					
						
							|  |  |  | 					P.Error(P.pos, `cannot use implicit package forward declaration for imported package "` + P.val + `"`); | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 					panic("wrong package forward decl"); | 
					
						
							| 
									
										
										
										
											2008-08-11 18:44:41 -07:00
										 |  |  | 					// TODO introduce dummy package so we can continue safely | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			P.Next();  // consume package name | 
					
						
							|  |  |  | 			P.Expect(Scanner.PERIOD); | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 			pos, ident := P.ParseIdent(false); | 
					
						
							| 
									
										
										
										
											2008-08-11 18:44:41 -07:00
										 |  |  | 			obj := pkg.scope.Lookup(ident); | 
					
						
							|  |  |  | 			if obj == nil { | 
					
						
							|  |  |  | 				elt = Globals.NewType(Type.FORWARD); | 
					
						
							|  |  |  | 				elt.scope = P.top_scope;  // not really needed here, but for consistency | 
					
						
							|  |  |  | 				obj = Globals.NewObject(pos, Object.TYPE, ident); | 
					
						
							|  |  |  | 				obj.exported = true;  // the type name must be visible | 
					
						
							|  |  |  | 				obj.typ = elt; | 
					
						
							|  |  |  | 				elt.obj = obj;  // primary type object; | 
					
						
							|  |  |  | 				pkg.scope.Insert(obj); | 
					
						
							|  |  |  | 				obj.pnolev = pkg.obj.pnolev; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				if obj.kind != Object.TYPE || obj.typ.form != Type.FORWARD { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 					panic("inconsistency in package.type forward declaration"); | 
					
						
							| 
									
										
										
										
											2008-08-11 18:44:41 -07:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				elt = obj.typ; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 			 | 
					
						
							| 
									
										
										
										
											2008-08-11 18:44:41 -07:00
										 |  |  | 		} else if P.tok == Scanner.IDENT { | 
					
						
							|  |  |  | 			if P.Lookup(P.val) == nil { | 
					
						
							|  |  |  | 				// implicit type forward declaration | 
					
						
							|  |  |  | 				// create a named forward type  | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 				pos, ident := P.ParseIdent(false); | 
					
						
							| 
									
										
										
										
											2008-08-11 18:44:41 -07:00
										 |  |  | 				obj := Globals.NewObject(pos, Object.TYPE, ident); | 
					
						
							|  |  |  | 				elt = Globals.NewType(Type.FORWARD); | 
					
						
							|  |  |  | 				obj.typ = elt; | 
					
						
							|  |  |  | 				elt.obj = obj;  // primary type object; | 
					
						
							|  |  |  | 				// remember the current scope - resolving the forward | 
					
						
							|  |  |  | 				// type must find a matching declaration in this or a less nested scope | 
					
						
							|  |  |  | 				elt.scope = P.top_scope; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				// type name | 
					
						
							|  |  |  | 				// (ParseType() (via TryType()) checks for forward types and complains, | 
					
						
							|  |  |  | 				// so call ParseTypeName() directly) | 
					
						
							|  |  |  | 				// we can only have a foward type here if we refer to the name of a | 
					
						
							|  |  |  | 				// yet incomplete type (i.e. if we are in the middle of a type's declaration) | 
					
						
							|  |  |  | 				elt = P.ParseTypeName(); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-11 18:44:41 -07:00
										 |  |  | 			// collect uses of pointer types referring to forward types | 
					
						
							|  |  |  | 			if elt.form == Type.FORWARD { | 
					
						
							|  |  |  | 				P.forward_types.AddTyp(typ); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			elt = P.ParseType(); | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-08-11 18:44:41 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 		elt = P.ParseType(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 	typ.elt = elt; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	return typ; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | // Returns nil if no type was found. | 
					
						
							|  |  |  | func (P *Parser) TryType() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	P.Trace("Type (try)"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 	pos := P.pos; | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	var typ *Globals.Type = nil; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	switch P.tok { | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	case Scanner.IDENT: typ = P.ParseTypeName(); | 
					
						
							|  |  |  | 	case Scanner.LBRACK: typ = P.ParseArrayType(); | 
					
						
							|  |  |  | 	case Scanner.CHAN: typ = P.ParseChannelType(); | 
					
						
							|  |  |  | 	case Scanner.INTERFACE: typ = P.ParseInterfaceType(); | 
					
						
							|  |  |  | 	case Scanner.FUNC: typ = P.ParseFunctionType(); | 
					
						
							|  |  |  | 	case Scanner.MAP: typ = P.ParseMapType(); | 
					
						
							|  |  |  | 	case Scanner.STRUCT: typ = P.ParseStructType(); | 
					
						
							|  |  |  | 	case Scanner.MUL: typ = P.ParsePointerType(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 	if typ != nil && typ.form == Type.FORWARD { | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 		P.Error(pos, "incomplete type"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	return typ; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | // ---------------------------------------------------------------------------- | 
					
						
							|  |  |  | // Blocks | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseStatement() { | 
					
						
							|  |  |  | 	P.Trace("Statement"); | 
					
						
							|  |  |  | 	if !P.TryStatement() { | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 		P.Error(P.pos, "statement expected"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		P.Next();  // make progress | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseStatementList() { | 
					
						
							|  |  |  | 	P.Trace("StatementList"); | 
					
						
							|  |  |  | 	for P.TryStatement() { | 
					
						
							|  |  |  | 		P.Optional(Scanner.SEMICOLON); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | func (P *Parser) ParseBlock(sig *Globals.Scope) { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("Block"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.LBRACE); | 
					
						
							|  |  |  | 	P.OpenScope(); | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 	if sig != nil { | 
					
						
							|  |  |  | 		P.level--; | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | 		// add copies of the formal parameters to the function scope | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 		scope := P.top_scope; | 
					
						
							|  |  |  | 		for p := sig.entries.first; p != nil; p = p.next { | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | 			scope.Insert(p.obj.Copy()) | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	if P.tok != Scanner.RBRACE && P.tok != Scanner.SEMICOLON { | 
					
						
							|  |  |  | 		P.ParseStatementList(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Optional(Scanner.SEMICOLON); | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 	if sig != nil { | 
					
						
							|  |  |  | 		P.level++; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.CloseScope(); | 
					
						
							|  |  |  | 	P.Expect(Scanner.RBRACE); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | // ---------------------------------------------------------------------------- | 
					
						
							|  |  |  | // Expressions | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | func (P *Parser) ParseExpressionList(list *Globals.List) { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("ExpressionList"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 	list.AddExpr(P.ParseExpression()); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	for P.tok == Scanner.COMMA { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 		list.AddExpr(P.ParseExpression()); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseNewExpressionList() *Globals.List { | 
					
						
							|  |  |  | 	P.Trace("NewExpressionList"); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	list := Globals.NewList(); | 
					
						
							|  |  |  | 	P.ParseExpressionList(list); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | 	return list; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | func (P *Parser) ParseNew() Globals.Expr { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("New"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.NEW); | 
					
						
							|  |  |  | 	P.Expect(Scanner.LPAREN); | 
					
						
							|  |  |  | 	P.ParseType(); | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 	args := Globals.NewList(); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	if P.tok == Scanner.COMMA { | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 		P.ParseExpressionList(args) | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.RPAREN); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | 	return nil; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | func (P *Parser) ParseFunctionLit() Globals.Expr { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("FunctionLit"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 	typ := P.ParseFunctionType(); | 
					
						
							|  |  |  | 	P.ParseBlock(typ.scope); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | 	return nil; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | func (P *Parser) ParseExpressionPair(list *Globals.List) { | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | 	P.Trace("ExpressionPair"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 	list.AddExpr(P.ParseExpression()); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | 	P.Expect(Scanner.COLON); | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 	list.AddExpr(P.ParseExpression()); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | func (P *Parser) ParseExpressionPairList(list *Globals.List) { | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | 	P.Trace("ExpressionPairList"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 	P.ParseExpressionPair(list); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | 	for (P.tok == Scanner.COMMA) { | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 		P.ParseExpressionPair(list); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | func (P *Parser) ParseCompositeLit(typ *Globals.Type) Globals.Expr { | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | 	P.Trace("CompositeLit"); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// TODO I think we should use {} instead of () for | 
					
						
							|  |  |  | 	// composite literals to syntactically distinguish | 
					
						
							|  |  |  | 	// them from conversions. For now: allow both. | 
					
						
							|  |  |  | 	var paren int; | 
					
						
							|  |  |  | 	if P.tok == Scanner.LPAREN { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		paren = Scanner.RPAREN; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		P.Expect(Scanner.LBRACE); | 
					
						
							|  |  |  | 		paren = Scanner.RBRACE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// TODO: should allow trailing ',' | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 	list := Globals.NewList(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | 	if P.tok != paren { | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 		list.AddExpr(P.ParseExpression()); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | 		if P.tok == Scanner.COMMA { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 			if P.tok != paren { | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 				P.ParseExpressionList(list); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} else if P.tok == Scanner.COLON { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 			list.AddExpr(P.ParseExpression()); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | 			if P.tok == Scanner.COMMA { | 
					
						
							|  |  |  | 				P.Next(); | 
					
						
							|  |  |  | 				if P.tok != paren { | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 					P.ParseExpressionPairList(list); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	P.Expect(paren); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | 	return nil; | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | func (P *Parser) ParseOperand(pos int, ident string) Globals.Expr { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("Operand"); | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if pos < 0 && P.tok == Scanner.IDENT { | 
					
						
							|  |  |  | 		// no look-ahead yet | 
					
						
							|  |  |  | 		pos = P.pos; | 
					
						
							|  |  |  | 		ident = P.val; | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	var res Globals.Expr = AST.Bad; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	if pos >= 0 { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 		obj := P.ParseQualifiedIdent(pos, ident); | 
					
						
							|  |  |  | 		if P.semantic_checks { | 
					
						
							|  |  |  | 			if obj.kind == Object.TYPE { | 
					
						
							|  |  |  | 				res = P.ParseCompositeLit(obj.typ); | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				res = AST.NewObject(pos, obj); | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 		switch P.tok { | 
					
						
							|  |  |  | 		case Scanner.IDENT: | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 			panic("UNREACHABLE"); | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 			 | 
					
						
							|  |  |  | 		case Scanner.LPAREN: | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 			res = P.ParseExpression(); | 
					
						
							|  |  |  | 			P.Expect(Scanner.RPAREN); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 		case Scanner.INT: | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 			x := AST.NewLiteral(P.pos, Universe.int_t); | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 			x.i = 42;  // TODO set the right value | 
					
						
							|  |  |  | 			res = x; | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case Scanner.FLOAT: | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 			x := AST.NewLiteral(P.pos, Universe.float_t); | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 			x.f = 42.0;  // TODO set the right value | 
					
						
							|  |  |  | 			res = x; | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case Scanner.STRING: | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 			x := AST.NewLiteral(P.pos, Universe.string_t); | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 			x.s = P.val;  // TODO need to strip quotes, interpret string properly | 
					
						
							|  |  |  | 			res = x; | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case Scanner.NIL: | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 			res = AST.Nil; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 		case Scanner.IOTA: | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 			x := AST.NewLiteral(P.pos, Universe.int_t); | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 			x.i = 42;  // TODO set the right value | 
					
						
							|  |  |  | 			res = x; | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case Scanner.TRUE: | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 			res = AST.True; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case Scanner.FALSE: | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 			res = AST.False; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 		case Scanner.FUNC: | 
					
						
							|  |  |  | 			res = P.ParseFunctionLit(); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 		case Scanner.NEW: | 
					
						
							|  |  |  | 			res = P.ParseNew(); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			typ := P.TryType(); | 
					
						
							|  |  |  | 			if typ != nil { | 
					
						
							|  |  |  | 				res = P.ParseCompositeLit(typ); | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				P.Error(P.pos, "operand expected"); | 
					
						
							|  |  |  | 				P.Next();  // make progress | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 	return res; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | func (P *Parser) ParseSelectorOrTypeAssertion(x Globals.Expr) Globals.Expr { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("SelectorOrTypeAssertion"); | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 	period_pos := P.pos; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.PERIOD); | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 	if P.tok >= Scanner.IDENT { | 
					
						
							|  |  |  | 		ident_pos, ident := P.ParseIdent(true); | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 		if P.semantic_checks { | 
					
						
							|  |  |  | 			switch typ := x.typ(); typ.form { | 
					
						
							|  |  |  | 			case Type.BAD: | 
					
						
							|  |  |  | 				// ignore | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case Type.STRUCT, Type.INTERFACE: | 
					
						
							|  |  |  | 				obj := typ.scope.Lookup(ident); | 
					
						
							|  |  |  | 				if obj != nil { | 
					
						
							|  |  |  | 					x = AST.NewSelector(x.pos(), obj.typ); | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					P.Error(ident_pos, `no field/method "` + ident + `"`); | 
					
						
							|  |  |  | 					x = AST.Bad; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			default: | 
					
						
							|  |  |  | 				P.Error(period_pos, `"." not applicable`); | 
					
						
							|  |  |  | 				x = AST.Bad; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		P.Expect(Scanner.LPAREN); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		P.ParseType(); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		P.Expect(Scanner.RPAREN); | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		if P.semantic_checks { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 			panic("UNIMPLEMENTED"); | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 	return x; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | func (P *Parser) ParseIndexOrSlice(x Globals.Expr) Globals.Expr { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("IndexOrSlice"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 	pos := P.pos; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.LBRACK); | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 	i1 := P.ParseExpression(); | 
					
						
							|  |  |  | 	var i2 Globals.Expr; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	if P.tok == Scanner.COLON { | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 		i2 := P.ParseExpression(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.RBRACK); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 	if P.semantic_checks { | 
					
						
							|  |  |  | 		switch typ := x.typ(); typ.form { | 
					
						
							|  |  |  | 		case Type.BAD: | 
					
						
							|  |  |  | 			// ignore | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case Type.STRING, Type.ARRAY: | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 			panic("UNIMPLEMENTED"); | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 			 | 
					
						
							|  |  |  | 		case Type.MAP: | 
					
						
							|  |  |  | 			if Type.Equal(typ.aux, i1.typ()) { | 
					
						
							|  |  |  | 				// x = AST.NewSubscript(x, i1); | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 				panic("UNIMPLEMENTED"); | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 				 | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				P.Error(x.pos(), "map key type mismatch"); | 
					
						
							|  |  |  | 				x = AST.Bad; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			P.Error(pos, `"[]" not applicable`); | 
					
						
							|  |  |  | 			x = AST.Bad; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 	return x; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | func (P *Parser) ParseCall(x Globals.Expr) Globals.Expr { | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	P.Trace("Call"); | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.LPAREN); | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 	args := Globals.NewList(); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	if P.tok != Scanner.RPAREN { | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 		P.ParseExpressionList(args); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.RPAREN); | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if P.semantic_checks { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 		panic("UNIMPLEMENTED"); | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 	return x; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | func (P *Parser) ParsePrimaryExpr(pos int, ident string) Globals.Expr { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("PrimaryExpr"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 	x := P.ParseOperand(pos, ident); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	for { | 
					
						
							|  |  |  | 		switch P.tok { | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 		case Scanner.PERIOD: x = P.ParseSelectorOrTypeAssertion(x); | 
					
						
							|  |  |  | 		case Scanner.LBRACK: x = P.ParseIndexOrSlice(x); | 
					
						
							|  |  |  | 		case Scanner.LPAREN: x = P.ParseCall(x); | 
					
						
							|  |  |  | 		default: goto exit; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | exit: | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 	return x; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | // TODO is this function needed? | 
					
						
							|  |  |  | func (P *Parser) ParsePrimaryExprList() *Globals.List { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("PrimaryExprList"); | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	list := Globals.NewList(); | 
					
						
							|  |  |  | 	list.AddExpr(P.ParsePrimaryExpr(-1, "")); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	for P.tok == Scanner.COMMA { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 		list.AddExpr(P.ParsePrimaryExpr(-1, "")); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 	return list; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | func (P *Parser) ParseUnaryExpr() Globals.Expr { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("UnaryExpr"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	switch P.tok { | 
					
						
							|  |  |  | 	case Scanner.ADD: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.SUB: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.NOT: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.XOR: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.MUL: fallthrough; | 
					
						
							| 
									
										
										
										
											2008-07-16 17:00:48 -07:00
										 |  |  | 	case Scanner.RECV: fallthrough; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	case Scanner.AND: | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseUnaryExpr(); | 
					
						
							|  |  |  | 		P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 		return nil;  // TODO fix this | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	P.ParsePrimaryExpr(-1, ""); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 	return nil;  // TODO fix this | 
					
						
							| 
									
										
										
										
											2008-07-09 10:45:04 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func Precedence(tok int) int { | 
					
						
							|  |  |  | 	// TODO should use a map or array here for lookup | 
					
						
							|  |  |  | 	switch tok { | 
					
						
							|  |  |  | 	case Scanner.LOR: | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	case Scanner.LAND: | 
					
						
							|  |  |  | 		return 2; | 
					
						
							| 
									
										
										
										
											2008-07-16 17:00:48 -07:00
										 |  |  | 	case Scanner.SEND, Scanner.RECV: | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		return 3; | 
					
						
							| 
									
										
										
										
											2008-07-16 17:00:48 -07:00
										 |  |  | 	case Scanner.EQL, Scanner.NEQ, Scanner.LSS, Scanner.LEQ, Scanner.GTR, Scanner.GEQ: | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		return 4; | 
					
						
							| 
									
										
										
										
											2008-07-16 17:00:48 -07:00
										 |  |  | 	case Scanner.ADD, Scanner.SUB, Scanner.OR, Scanner.XOR: | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		return 5; | 
					
						
							| 
									
										
										
										
											2008-07-16 17:00:48 -07:00
										 |  |  | 	case Scanner.MUL, Scanner.QUO, Scanner.REM, Scanner.SHL, Scanner.SHR, Scanner.AND: | 
					
						
							|  |  |  | 		return 6; | 
					
						
							| 
									
										
										
										
											2008-07-09 10:45:04 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | func (P *Parser) ParseBinaryExpr(pos int, ident string, prec1 int) Globals.Expr { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("BinaryExpr"); | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | 	var x Globals.Expr; | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	if pos >= 0 { | 
					
						
							|  |  |  | 		x = P.ParsePrimaryExpr(pos, ident); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		x = P.ParseUnaryExpr(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	for prec := Precedence(P.tok); prec >= prec1; prec-- { | 
					
						
							|  |  |  | 		for Precedence(P.tok) == prec { | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 			e := new(AST.BinaryExpr); | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 			e.typ_ = Universe.bad_t;  // TODO fix this | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 			e.op = P.tok;  // TODO should we use tokens or separate operator constants? | 
					
						
							|  |  |  | 			e.x = x; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 			P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 			e.y = P.ParseBinaryExpr(-1, "", prec + 1); | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 			x = e; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | 	return x; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-25 11:27:13 -07:00
										 |  |  | // Expressions where the first token may be an identifier which has already | 
					
						
							|  |  |  | // been consumed. If the identifier is present, pos is the identifier position, | 
					
						
							|  |  |  | // otherwise pos must be < 0 (and ident is ignored). | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | func (P *Parser) ParseIdentExpression(pos int, ident string) Globals.Expr { | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	P.Trace("IdentExpression"); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	indent := P.indent; | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | 	x := P.ParseBinaryExpr(pos, ident, 1); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	if indent != P.indent { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 		panic("imbalanced tracing code (Expression)"); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | 	return x; | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | func (P *Parser) ParseExpression() Globals.Expr { | 
					
						
							|  |  |  | 	P.Trace("Expression"); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	x := P.ParseIdentExpression(-1, ""); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | 	return x; | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | // ---------------------------------------------------------------------------- | 
					
						
							|  |  |  | // Statements | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | func (P *Parser) ConvertToExprList(pos_list, ident_list, expr_list *Globals.List) { | 
					
						
							|  |  |  | 	for p, q := pos_list.first, ident_list.first; q != nil; p, q = p.next, q.next { | 
					
						
							|  |  |  | 		pos, ident := p.val, q.str; | 
					
						
							| 
									
										
										
										
											2008-07-30 17:36:03 -07:00
										 |  |  | 		if P.semantic_checks { | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | 			obj := P.Lookup(ident); | 
					
						
							|  |  |  | 			if obj == nil { | 
					
						
							|  |  |  | 				P.Error(pos, `"` + ident + `" is not declared`); | 
					
						
							|  |  |  | 				obj = Globals.NewObject(pos, Object.BAD, ident); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		expr_list.AddInt(0);  // TODO fix this - add correct expression | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ident_list.Clear(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseIdentOrExpr(pos_list, ident_list, expr_list *Globals.List) { | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	P.Trace("IdentOrExpr"); | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	pos_list.AddInt(P.pos); | 
					
						
							|  |  |  | 	pos, ident := -1, ""; | 
					
						
							|  |  |  | 	just_ident := false; | 
					
						
							|  |  |  | 	if expr_list.len_ == 0 /* only idents so far */ && P.tok == Scanner.IDENT { | 
					
						
							|  |  |  | 		pos, ident = P.pos, P.val; | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		switch P.tok { | 
					
						
							|  |  |  | 		case Scanner.COMMA, | 
					
						
							|  |  |  | 			Scanner.COLON, | 
					
						
							|  |  |  | 			Scanner.DEFINE, | 
					
						
							|  |  |  | 			Scanner.ASSIGN, | 
					
						
							|  |  |  | 			Scanner.ADD_ASSIGN, | 
					
						
							|  |  |  | 			Scanner.SUB_ASSIGN, | 
					
						
							|  |  |  | 			Scanner.MUL_ASSIGN, | 
					
						
							|  |  |  | 			Scanner.QUO_ASSIGN, | 
					
						
							|  |  |  | 			Scanner.REM_ASSIGN, | 
					
						
							|  |  |  | 			Scanner.AND_ASSIGN, | 
					
						
							|  |  |  | 			Scanner.OR_ASSIGN, | 
					
						
							|  |  |  | 			Scanner.XOR_ASSIGN, | 
					
						
							|  |  |  | 			Scanner.SHL_ASSIGN, | 
					
						
							|  |  |  | 			Scanner.SHR_ASSIGN: | 
					
						
							|  |  |  | 			// identifier is not part of a more complicated expression | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | 			just_ident = true; | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if just_ident { | 
					
						
							|  |  |  | 		ident_list.AddStr(ident); | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | 		P.ConvertToExprList(pos_list, ident_list, expr_list); | 
					
						
							|  |  |  | 		P.ParseIdentExpression(pos, ident); | 
					
						
							|  |  |  | 		expr_list.AddInt(0);  // TODO fix this - add correct expression | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | func (P *Parser) ParseIdentOrExprList() (pos_list, ident_list, expr_list *Globals.List) { | 
					
						
							|  |  |  | 	P.Trace("IdentOrExprList"); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	pos_list, ident_list, expr_list = Globals.NewList(), Globals.NewList(), Globals.NewList(); | 
					
						
							|  |  |  | 	P.ParseIdentOrExpr(pos_list, ident_list, expr_list); | 
					
						
							|  |  |  | 	for P.tok == Scanner.COMMA { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseIdentOrExpr(pos_list, ident_list, expr_list); | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | 	return pos_list, ident_list, expr_list; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseSimpleStat() { | 
					
						
							|  |  |  | 	P.Trace("SimpleStat"); | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	// If we see an identifier, we don't know if it's part of a | 
					
						
							|  |  |  | 	// label declaration, (multiple) variable declaration, assignment, | 
					
						
							|  |  |  | 	// or simply an expression, without looking ahead. | 
					
						
							|  |  |  | 	// Strategy: We parse an expression list, but simultaneously, as | 
					
						
							|  |  |  | 	// long as possible, maintain a list of identifiers which is converted | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | 	// into an expression list only if neccessary. The result of | 
					
						
							|  |  |  | 	// ParseIdentOrExprList is a list of ident/expr positions and either | 
					
						
							|  |  |  | 	// a non-empty list of identifiers or a non-empty list of expressions | 
					
						
							|  |  |  | 	// (but not both). | 
					
						
							|  |  |  | 	pos_list, ident_list, expr_list := P.ParseIdentOrExprList(); | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	switch P.tok { | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	case Scanner.COLON: | 
					
						
							|  |  |  | 		// label declaration | 
					
						
							| 
									
										
										
										
											2008-07-30 17:36:03 -07:00
										 |  |  | 		if P.semantic_checks && ident_list.len_ != 1 { | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 			P.Error(P.pos, "illegal label declaration"); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 		 | 
					
						
							|  |  |  | 	case Scanner.DEFINE: | 
					
						
							|  |  |  | 		// variable declaration | 
					
						
							| 
									
										
										
										
											2008-07-30 17:36:03 -07:00
										 |  |  | 		if P.semantic_checks && ident_list.len_ == 0 { | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | 			P.Error(P.pos, "illegal left-hand side for declaration"); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | 		pos := P.pos; | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 		val_list := P.ParseNewExpressionList(); | 
					
						
							| 
									
										
										
										
											2008-07-30 17:36:03 -07:00
										 |  |  | 		if P.semantic_checks && val_list.len_ != ident_list.len_ { | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | 			P.Error(pos, "number of expressions does not match number of variables"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// declare variables | 
					
						
							| 
									
										
										
										
											2008-07-30 17:36:03 -07:00
										 |  |  | 		if P.semantic_checks { | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | 			for p, q := pos_list.first, ident_list.first; q != nil; p, q = p.next, q.next { | 
					
						
							|  |  |  | 				obj := Globals.NewObject(p.val, Object.VAR, q.str); | 
					
						
							|  |  |  | 				P.Declare(obj); | 
					
						
							|  |  |  | 				// TODO set correct types | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	case Scanner.ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.ADD_ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.SUB_ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.MUL_ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.QUO_ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.REM_ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.AND_ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.OR_ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.XOR_ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.SHL_ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.SHR_ASSIGN: | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | 		P.ConvertToExprList(pos_list, ident_list, expr_list); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | 		pos := P.pos; | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 		val_list := P.ParseNewExpressionList(); | 
					
						
							| 
									
										
										
										
											2008-07-30 17:36:03 -07:00
										 |  |  | 		if P.semantic_checks && val_list.len_ != expr_list.len_ { | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | 			P.Error(pos, "number of expressions does not match number of variables"); | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | 		P.ConvertToExprList(pos_list, ident_list, expr_list); | 
					
						
							| 
									
										
										
										
											2008-07-30 17:36:03 -07:00
										 |  |  | 		if P.semantic_checks && expr_list.len_ != 1 { | 
					
						
							| 
									
										
										
										
											2008-07-25 09:35:03 -07:00
										 |  |  | 			P.Error(P.pos, "no expression list allowed"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if P.tok == Scanner.INC || P.tok == Scanner.DEC { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | func (P *Parser) ParseGoStat() { | 
					
						
							|  |  |  | 	P.Trace("GoStat"); | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	P.Expect(Scanner.GO); | 
					
						
							|  |  |  | 	P.ParseExpression(); | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | func (P *Parser) ParseReturnStat() { | 
					
						
							|  |  |  | 	P.Trace("ReturnStat"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Expect(Scanner.RETURN); | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 	res := Globals.NewList(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE { | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 		P.ParseExpressionList(res); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | func (P *Parser) ParseControlFlowStat(tok int) { | 
					
						
							|  |  |  | 	P.Trace("ControlFlowStat"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	P.Expect(tok); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	if P.tok == Scanner.IDENT { | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 		P.ParseIdent(false); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | func (P *Parser) ParseIfStat() *AST.IfStat { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Trace("IfStat"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Expect(Scanner.IF); | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.OpenScope(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	if P.tok != Scanner.LBRACE { | 
					
						
							| 
									
										
										
										
											2008-07-10 20:50:38 -07:00
										 |  |  | 		if P.tok != Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.ParseSimpleStat(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		if P.tok == Scanner.SEMICOLON { | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 			P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-10 20:50:38 -07:00
										 |  |  | 			if P.tok != Scanner.LBRACE { | 
					
						
							|  |  |  | 				P.ParseExpression(); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 	P.ParseBlock(nil); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	if P.tok == Scanner.ELSE { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		if P.tok == Scanner.IF { | 
					
						
							|  |  |  | 			P.ParseIfStat(); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			// TODO should be P.ParseBlock() | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 			P.ParseStatement(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.CloseScope(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseForStat() { | 
					
						
							|  |  |  | 	P.Trace("ForStat"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Expect(Scanner.FOR); | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.OpenScope(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	if P.tok != Scanner.LBRACE { | 
					
						
							|  |  |  | 		if P.tok != Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.ParseSimpleStat(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 			if P.tok != Scanner.SEMICOLON { | 
					
						
							|  |  |  | 				P.ParseExpression(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			P.Expect(Scanner.SEMICOLON); | 
					
						
							|  |  |  | 			if P.tok != Scanner.LBRACE { | 
					
						
							|  |  |  | 				P.ParseSimpleStat(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 	P.ParseBlock(nil); | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.CloseScope(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseCase() { | 
					
						
							|  |  |  | 	P.Trace("Case"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	if P.tok == Scanner.CASE { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 		list := Globals.NewList(); | 
					
						
							|  |  |  | 		P.ParseExpressionList(list); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		P.Expect(Scanner.DEFAULT); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.COLON); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseCaseClause() { | 
					
						
							|  |  |  | 	P.Trace("CaseClause"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-11 18:44:41 -07:00
										 |  |  | 	P.ParseCase(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	if P.tok != Scanner.FALLTHROUGH && P.tok != Scanner.RBRACE { | 
					
						
							|  |  |  | 		P.ParseStatementList(); | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 		P.Optional(Scanner.SEMICOLON); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if P.tok == Scanner.FALLTHROUGH { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 		P.Optional(Scanner.SEMICOLON); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseSwitchStat() { | 
					
						
							|  |  |  | 	P.Trace("SwitchStat"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Expect(Scanner.SWITCH); | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.OpenScope(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	if P.tok != Scanner.LBRACE { | 
					
						
							| 
									
										
										
										
											2008-07-10 20:50:38 -07:00
										 |  |  | 		if P.tok != Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.ParseSimpleStat(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		if P.tok == Scanner.SEMICOLON { | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 			P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-10 20:50:38 -07:00
										 |  |  | 			if P.tok != Scanner.LBRACE { | 
					
						
							|  |  |  | 				P.ParseExpression(); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.LBRACE); | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT { | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.ParseCaseClause(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.RBRACE); | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.CloseScope(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  | func (P *Parser) ParseCommCase() { | 
					
						
							|  |  |  |   P.Trace("CommCase"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  |   if P.tok == Scanner.CASE { | 
					
						
							|  |  |  | 	P.Next(); | 
					
						
							|  |  |  | 	if P.tok == Scanner.GTR { | 
					
						
							|  |  |  | 		// send | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseExpression(); | 
					
						
							|  |  |  | 		P.Expect(Scanner.EQL); | 
					
						
							|  |  |  | 		P.ParseExpression(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		// receive | 
					
						
							|  |  |  | 		if P.tok != Scanner.LSS { | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 			P.ParseIdent(false); | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  | 			P.Expect(Scanner.ASSIGN); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		P.Expect(Scanner.LSS); | 
					
						
							|  |  |  | 		P.ParseExpression(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  | 	P.Expect(Scanner.DEFAULT); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   P.Expect(Scanner.COLON); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  |   P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseCommClause() { | 
					
						
							|  |  |  | 	P.Trace("CommClause"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  | 	P.ParseCommCase(); | 
					
						
							|  |  |  | 	if P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE { | 
					
						
							|  |  |  | 		P.ParseStatementList(); | 
					
						
							|  |  |  | 		P.Optional(Scanner.SEMICOLON); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseRangeStat() bool { | 
					
						
							|  |  |  | 	P.Trace("RangeStat"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  | 	P.Expect(Scanner.RANGE); | 
					
						
							|  |  |  | 	P.ParseIdentList(); | 
					
						
							|  |  |  | 	P.Expect(Scanner.DEFINE); | 
					
						
							|  |  |  | 	P.ParseExpression(); | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 	P.ParseBlock(nil); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseSelectStat() bool { | 
					
						
							|  |  |  | 	P.Trace("SelectStat"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  | 	P.Expect(Scanner.SELECT); | 
					
						
							|  |  |  | 	P.Expect(Scanner.LBRACE); | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF { | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  | 		P.ParseCommClause(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | func (P *Parser) TryStatement() bool { | 
					
						
							|  |  |  | 	P.Trace("Statement (try)"); | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 	indent := P.indent; | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 	res := true; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	switch P.tok { | 
					
						
							|  |  |  | 	case Scanner.CONST: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.TYPE: fallthrough; | 
					
						
							| 
									
										
										
										
											2008-07-15 09:22:20 -07:00
										 |  |  | 	case Scanner.VAR: | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		P.ParseDeclaration(); | 
					
						
							| 
									
										
										
										
											2008-07-15 09:22:20 -07:00
										 |  |  | 	case Scanner.FUNC: | 
					
						
							|  |  |  | 		// for now we do not allow local function declarations | 
					
						
							|  |  |  | 		fallthrough; | 
					
						
							| 
									
										
										
										
											2008-07-30 13:01:28 -07:00
										 |  |  | 	case Scanner.MUL, Scanner.SEND, Scanner.RECV, Scanner.IDENT, Scanner.LPAREN: | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 		P.ParseSimpleStat(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	case Scanner.GO: | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 		P.ParseGoStat(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	case Scanner.RETURN: | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.ParseReturnStat(); | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO: | 
					
						
							|  |  |  | 		P.ParseControlFlowStat(P.tok); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	case Scanner.LBRACE: | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 		P.ParseBlock(nil); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	case Scanner.IF: | 
					
						
							|  |  |  | 		P.ParseIfStat(); | 
					
						
							|  |  |  | 	case Scanner.FOR: | 
					
						
							|  |  |  | 		P.ParseForStat(); | 
					
						
							|  |  |  | 	case Scanner.SWITCH: | 
					
						
							|  |  |  | 		P.ParseSwitchStat(); | 
					
						
							|  |  |  | 	case Scanner.RANGE: | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  | 		P.ParseRangeStat(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	case Scanner.SELECT: | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  | 		P.ParseSelectStat(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		// no statement found | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 		res = false; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 	if indent != P.indent { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 		panic("imbalanced tracing code (Statement)"); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 	return res; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | // ---------------------------------------------------------------------------- | 
					
						
							|  |  |  | // Declarations | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseImportSpec() { | 
					
						
							|  |  |  | 	P.Trace("ImportSpec"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 	var obj *Globals.Object = nil; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	if P.tok == Scanner.PERIOD { | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 		P.Error(P.pos, `"import ." not yet handled properly`); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	} else if P.tok == Scanner.IDENT { | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 		obj = P.ParseIdentDecl(Object.PACKAGE); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 	if P.semantic_checks && P.tok == Scanner.STRING { | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 		// TODO eventually the scanner should strip the quotes | 
					
						
							|  |  |  | 		pkg_name := P.val[1 : len(P.val) - 1];  // strip quotes | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 		// TODO switch to indirect import once the compiler problems are fixed | 
					
						
							|  |  |  | 		//pkg := Import.Import(P.comp, pkg_name); | 
					
						
							|  |  |  | 		pkg := P.comp.env.Import(P.comp, pkg_name); | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 		if pkg != nil { | 
					
						
							| 
									
										
										
										
											2008-07-30 21:26:15 -07:00
										 |  |  | 			pno := pkg.obj.pnolev;  // preserve pno | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 			if obj == nil { | 
					
						
							|  |  |  | 				// use original package name | 
					
						
							|  |  |  | 				obj = pkg.obj; | 
					
						
							| 
									
										
										
										
											2008-07-30 21:26:15 -07:00
										 |  |  | 				P.Declare(obj);  // this changes (pkg.)obj.pnolev! | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-07-30 21:26:15 -07:00
										 |  |  | 			obj.pnolev = pno;  // correct pno | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			P.Error(P.pos, `import of "` + pkg_name + `" failed`); | 
					
						
							| 
									
										
										
										
											2008-07-09 10:16:33 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-09 10:16:33 -07:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 		P.Expect(Scanner.STRING);  // use Expect() error handling | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-25 11:27:13 -07:00
										 |  |  | func (P *Parser) ParseConstSpec(exported bool) { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("ConstSpec"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	list := P.ParseIdentDeclList(Object.CONST); | 
					
						
							|  |  |  | 	typ := P.TryType(); | 
					
						
							|  |  |  | 	if typ != nil { | 
					
						
							|  |  |  | 		for p := list.first; p != nil; p = p.next { | 
					
						
							| 
									
										
										
										
											2008-08-01 14:50:18 -07:00
										 |  |  | 			p.obj.typ = typ; | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-08-01 14:50:18 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	if P.tok == Scanner.ASSIGN { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 		P.ParseNewExpressionList(); | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-01 14:50:18 -07:00
										 |  |  | 	if exported { | 
					
						
							|  |  |  | 		for p := list.first; p != nil; p = p.next { | 
					
						
							|  |  |  | 			p.obj.exported = true; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-25 11:27:13 -07:00
										 |  |  | func (P *Parser) ParseTypeSpec(exported bool) { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("TypeSpec"); | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-11 18:44:41 -07:00
										 |  |  | 	var typ *Globals.Type; | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 	pos, ident := P.ParseIdent(false); | 
					
						
							| 
									
										
										
										
											2008-08-11 18:44:41 -07:00
										 |  |  | 	obj := P.Lookup(ident); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-11 18:44:41 -07:00
										 |  |  | 	if !P.comp.flags.sixg && obj != nil { | 
					
						
							|  |  |  | 		if obj.typ.form == Type.FORWARD { | 
					
						
							|  |  |  | 			// imported forward-declared type | 
					
						
							|  |  |  | 			if !exported { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 				panic("foo"); | 
					
						
							| 
									
										
										
										
											2008-08-11 18:44:41 -07:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 			panic("bar"); | 
					
						
							| 
									
										
										
										
											2008-08-11 18:44:41 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		// Immediately after declaration of the type name, the type is | 
					
						
							|  |  |  | 		// considered forward-declared. It may be referred to from inside | 
					
						
							|  |  |  | 		// the type specification only via a pointer type. | 
					
						
							|  |  |  | 		typ = Globals.NewType(Type.FORWARD); | 
					
						
							|  |  |  | 		typ.scope = P.top_scope;  // not really needed here, but for consistency | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		obj = Globals.NewObject(pos, Object.TYPE, ident); | 
					
						
							|  |  |  | 		obj.exported = exported; | 
					
						
							|  |  |  | 		obj.typ = typ; | 
					
						
							|  |  |  | 		typ.obj = obj;  // primary type object | 
					
						
							|  |  |  | 		P.Declare(obj); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-31 10:47:10 -07:00
										 |  |  | 	// If the next token is an identifier and we have a legal program, | 
					
						
							|  |  |  | 	// it must be a typename. In that case this declaration introduces | 
					
						
							|  |  |  | 	// an alias type. | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 	if P.tok == Scanner.IDENT { | 
					
						
							|  |  |  | 		typ = Globals.NewType(Type.ALIAS); | 
					
						
							|  |  |  | 		elt := P.ParseType();  // we want a complete type - don't shortcut to ParseTypeName() | 
					
						
							|  |  |  | 		typ.elt = elt; | 
					
						
							|  |  |  | 		if elt.form == Type.ALIAS { | 
					
						
							|  |  |  | 			typ.aux = elt.aux;  // the base type | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			typ.aux = elt; | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		typ = P.ParseType(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	obj.typ = typ; | 
					
						
							|  |  |  | 	if typ.obj == nil { | 
					
						
							|  |  |  | 		typ.obj = obj;  // primary type object | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// if the type is exported, for now we export all fields | 
					
						
							|  |  |  | 	// of structs and interfaces by default | 
					
						
							|  |  |  | 	// TODO this needs to change eventually | 
					
						
							|  |  |  | 	// Actually in 6g even types referred to are exported - sigh... | 
					
						
							|  |  |  | 	if exported && (typ.form == Type.STRUCT || typ.form == Type.INTERFACE) { | 
					
						
							|  |  |  | 		for p := typ.scope.entries.first; p != nil; p = p.next { | 
					
						
							|  |  |  | 			p.obj.exported = true; | 
					
						
							| 
									
										
										
										
											2008-08-05 15:20:58 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-25 11:27:13 -07:00
										 |  |  | func (P *Parser) ParseVarSpec(exported bool) { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("VarSpec"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	list := P.ParseIdentDeclList(Object.VAR); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	if P.tok == Scanner.ASSIGN { | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 		P.ParseNewExpressionList(); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | 		typ := P.ParseVarType(); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		for p := list.first; p != nil; p = p.next { | 
					
						
							| 
									
										
										
										
											2008-07-31 13:35:30 -07:00
										 |  |  | 			p.obj.typ = typ; | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		if P.tok == Scanner.ASSIGN { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							| 
									
										
										
										
											2008-08-06 17:26:46 -07:00
										 |  |  | 			P.ParseNewExpressionList(); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-01 14:50:18 -07:00
										 |  |  | 	if exported { | 
					
						
							|  |  |  | 		for p := list.first; p != nil; p = p.next { | 
					
						
							|  |  |  | 			p.obj.exported = true; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | // TODO With method variables, we wouldn't need this dispatch function. | 
					
						
							|  |  |  | func (P *Parser) ParseSpec(exported bool, keyword int) { | 
					
						
							|  |  |  | 	switch keyword { | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 	case Scanner.IMPORT: P.ParseImportSpec(); | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 	case Scanner.CONST: P.ParseConstSpec(exported); | 
					
						
							|  |  |  | 	case Scanner.TYPE: P.ParseTypeSpec(exported); | 
					
						
							|  |  |  | 	case Scanner.VAR: P.ParseVarSpec(exported); | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 	default: panic("UNREACHABLE"); | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseDecl(exported bool, keyword int) { | 
					
						
							|  |  |  | 	P.Trace("Decl"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 	P.Expect(keyword); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	if P.tok == Scanner.LPAREN { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 		for P.tok == Scanner.IDENT { | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 			P.ParseSpec(exported, keyword); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 			if P.tok != Scanner.RPAREN { | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 				// P.Expect(Scanner.SEMICOLON); | 
					
						
							|  |  |  | 				P.Optional(Scanner.SEMICOLON);  // TODO this seems wrong! (needed for math.go) | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 		P.ParseSpec(exported, keyword); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-25 11:27:13 -07:00
										 |  |  | func (P *Parser) ParseFuncDecl(exported bool) { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("FuncDecl"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.FUNC); | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 	pos, ident, typ := P.ParseNamedSignature(); | 
					
						
							|  |  |  | 	obj := P.DeclareFunc(pos, ident, typ);  // need obj later for statements | 
					
						
							| 
									
										
										
										
											2008-07-30 13:01:28 -07:00
										 |  |  | 	obj.exported = exported; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	if P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 		// forward declaration | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 		P.ParseBlock(typ.scope); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseExportDecl() { | 
					
						
							|  |  |  | 	P.Trace("ExportDecl"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-04 15:37:47 -07:00
										 |  |  | 	// TODO This is deprecated syntax and should go away eventually. | 
					
						
							|  |  |  | 	// (Also at the moment the syntax is everything goes...) | 
					
						
							| 
									
										
										
										
											2008-07-25 11:27:13 -07:00
										 |  |  | 	//P.Expect(Scanner.EXPORT); | 
					
						
							| 
									
										
										
										
											2008-08-04 15:37:47 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if !P.comp.flags.sixg { | 
					
						
							|  |  |  | 		P.Error(P.pos, "deprecated export syntax (use -6g to enable)"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 	has_paren := false; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	if P.tok == Scanner.LPAREN { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 		has_paren = true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for P.tok == Scanner.IDENT { | 
					
						
							| 
									
										
										
										
											2008-08-11 20:40:37 -07:00
										 |  |  | 		pos, ident := P.ParseIdent(false); | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 		P.exports.AddStr(ident); | 
					
						
							| 
									
										
										
										
											2008-07-24 17:00:58 -07:00
										 |  |  | 		P.Optional(Scanner.COMMA);  // TODO this seems wrong | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if has_paren { | 
					
						
							|  |  |  | 		P.Expect(Scanner.RPAREN) | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseDeclaration() { | 
					
						
							|  |  |  | 	P.Trace("Declaration"); | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 	indent := P.indent; | 
					
						
							| 
									
										
										
										
											2008-07-25 11:27:13 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	exported := false; | 
					
						
							|  |  |  | 	if P.tok == Scanner.EXPORT { | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 		if P.level == 0 { | 
					
						
							|  |  |  | 			exported = true; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			P.Error(P.pos, "local declarations cannot be exported"); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-25 11:27:13 -07:00
										 |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	switch P.tok { | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 	case Scanner.CONST, Scanner.TYPE, Scanner.VAR: | 
					
						
							|  |  |  | 		P.ParseDecl(exported, P.tok); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	case Scanner.FUNC: | 
					
						
							| 
									
										
										
										
											2008-07-25 11:27:13 -07:00
										 |  |  | 		P.ParseFuncDecl(exported); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	case Scanner.EXPORT: | 
					
						
							| 
									
										
										
										
											2008-07-25 11:27:13 -07:00
										 |  |  | 		if exported { | 
					
						
							|  |  |  | 			P.Error(P.pos, "cannot mark export declaration for export"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		P.ParseExportDecl(); | 
					
						
							|  |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2008-07-25 11:27:13 -07:00
										 |  |  | 		if exported && (P.tok == Scanner.IDENT || P.tok == Scanner.LPAREN) { | 
					
						
							|  |  |  | 			P.ParseExportDecl(); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			P.Error(P.pos, "declaration expected"); | 
					
						
							|  |  |  | 			P.Next();  // make progress | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-25 11:27:13 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 	if indent != P.indent { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 		panic("imbalanced tracing code (Declaration)"); | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | // ---------------------------------------------------------------------------- | 
					
						
							|  |  |  | // Program | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | func (P *Parser) ResolveForwardTypes() { | 
					
						
							| 
									
										
										
										
											2008-07-30 17:36:03 -07:00
										 |  |  | 	if !P.semantic_checks { | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 	for p := P.forward_types.first; p != nil; p = p.next { | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 		typ := p.typ; | 
					
						
							|  |  |  | 		if typ.form != Type.POINTER { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 			panic("unresolved types should be pointers only"); | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		elt := typ.elt; | 
					
						
							|  |  |  | 		if typ.elt.form != Type.FORWARD { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 			panic("unresolved pointer should point to forward type"); | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		obj := elt.obj; | 
					
						
							|  |  |  | 		if obj.typ == elt { | 
					
						
							|  |  |  | 			// actual forward declaration (as opposed to forward types introduced | 
					
						
							|  |  |  | 			// during type declaration) - need to lookup the actual type object | 
					
						
							|  |  |  | 			var elt_obj *Globals.Object; | 
					
						
							|  |  |  | 			for scope := elt.scope; scope != nil && elt_obj == nil; scope = scope.parent { | 
					
						
							|  |  |  | 				elt_obj = scope.Lookup(obj.ident); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// update the type object if we found one | 
					
						
							|  |  |  | 			if elt_obj != nil { | 
					
						
							|  |  |  | 				if elt_obj.kind == Object.TYPE { | 
					
						
							|  |  |  | 					obj = elt_obj; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					P.Error(obj.pos, `"` + obj.ident + `" does not denote a type`); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// update the pointer type | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 		typ.elt = obj.typ; | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		// TODO as long as we don't *use* a forward type, we are ok | 
					
						
							|  |  |  | 		// => consider not reporting this as an error | 
					
						
							|  |  |  | 		// (in a real forward declaration, the corresponding objects are not in a scope | 
					
						
							|  |  |  | 		// and have incorrect pnolev) | 
					
						
							|  |  |  | 		if typ.elt.form == Type.FORWARD { | 
					
						
							|  |  |  | 			P.Error(obj.pos, `"` + obj.ident + `" is not declared after forward declaration`); | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | func (P *Parser) MarkExports() { | 
					
						
							| 
									
										
										
										
											2008-07-30 17:36:03 -07:00
										 |  |  | 	if !P.semantic_checks { | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	scope := P.top_scope; | 
					
						
							|  |  |  | 	for p := P.exports.first; p != nil; p = p.next { | 
					
						
							|  |  |  | 		obj := scope.Lookup(p.str); | 
					
						
							|  |  |  | 		if obj != nil { | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 			obj.exported = true; | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 			// For now we export deep | 
					
						
							|  |  |  | 			// TODO this should change eventually - we need selective export | 
					
						
							|  |  |  | 			if obj.kind == Object.TYPE { | 
					
						
							|  |  |  | 				typ := obj.typ; | 
					
						
							|  |  |  | 				if typ.form == Type.STRUCT || typ.form == Type.INTERFACE { | 
					
						
							|  |  |  | 					scope := typ.scope; | 
					
						
							|  |  |  | 					for p := scope.entries.first; p != nil; p = p.next { | 
					
						
							| 
									
										
										
										
											2008-07-29 12:03:06 -07:00
										 |  |  | 						p.obj.exported = true; | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			// TODO need to report proper src position | 
					
						
							| 
									
										
										
										
											2008-07-30 17:36:03 -07:00
										 |  |  | 			P.Error(-1, `"` + p.str + `" is not declared - cannot be exported`); | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | func (P *Parser) ParseProgram() { | 
					
						
							|  |  |  | 	P.Trace("Program"); | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.OpenScope(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Expect(Scanner.PACKAGE); | 
					
						
							| 
									
										
										
										
											2008-08-04 10:19:36 -07:00
										 |  |  | 	obj := P.ParseIdentDecl(Object.PACKAGE); | 
					
						
							| 
									
										
										
										
											2008-07-10 18:05:00 -07:00
										 |  |  | 	P.Optional(Scanner.SEMICOLON); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 	{	P.OpenScope(); | 
					
						
							|  |  |  | 		if P.level != 0 { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 			panic("incorrect scope level"); | 
					
						
							| 
									
										
										
										
											2008-07-30 21:26:15 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-08-04 13:27:05 -07:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		P.comp.Insert(Globals.NewPackage(P.S.filename, obj, P.top_scope)); | 
					
						
							|  |  |  | 		if P.comp.pkg_ref != 1 { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 			panic("should have exactly one package now"); | 
					
						
							| 
									
										
										
										
											2008-08-04 13:27:05 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 		for P.tok == Scanner.IMPORT { | 
					
						
							| 
									
										
										
										
											2008-07-29 19:02:49 -07:00
										 |  |  | 			P.ParseDecl(false, Scanner.IMPORT); | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 			P.Optional(Scanner.SEMICOLON); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		for P.tok != Scanner.EOF { | 
					
						
							|  |  |  | 			P.ParseDeclaration(); | 
					
						
							|  |  |  | 			P.Optional(Scanner.SEMICOLON); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2008-08-11 09:45:40 -07:00
										 |  |  | 		P.ResolveForwardTypes(); | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 		P.MarkExports(); | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2008-07-30 21:26:15 -07:00
										 |  |  | 		if P.level != 0 { | 
					
						
							| 
									
										
										
										
											2008-08-11 21:20:42 -07:00
										 |  |  | 			panic("incorrect scope level"); | 
					
						
							| 
									
										
										
										
											2008-07-30 21:26:15 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-08-05 18:52:37 -07:00
										 |  |  | 		P.CloseScope(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-10 18:05:00 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.CloseScope(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } |