Exemple #1
0
        }         // ReadNextToken

        // Parse an identifier beginning at the current stream location.
        private Token ParseIdentifier(SrcLoc loc)
        {
            // Get a buffer from which we can parse the identifier.
            char[] charBuf;
            int    startPos;
            int    bufLen = buffer.GetBuffer(maxTokenLen, out charBuf,
                                             out startPos);

            if (bufLen > maxTokenLen)
            {
                bufLen = maxTokenLen;
            }

            // Find the last character in the identifier.  We begin
            // at 1 because we know (from matcher.Match returning
            // TokDispatch.ident) that the identifier is at least
            // one character long.
            int tokenLen = 1;

            while (tokenLen < bufLen &&
                   CharUtils.IsIdentifierChar(charBuf[startPos + tokenLen]))
            {
                tokenLen++;
            }

            Identifier token = new Identifier();

            token.rawText = buffer.ConsumeString(tokenLen);
            loc.len       = tokenLen;
            token.loc     = loc;
            return(token);
        }         // ParseIdentifier
Exemple #2
0
		} // ParseExpression
	
	
	// Parse a LeftHandSideExpression.
	// 
	// If checkForCallExpr is false, then we don't check for CallExpressions.
	// This is used when parsing the function in a "new" expression, to
	// avoid parsing arguments to "new" as part of the expression that
	// specifies the function.
	private ExprFrag ParseLeftHandSideExpression( FunctionInfo info,
												  bool checkForCallExpr )
		{
		ExprFrag expr;
		if (tok.TryMatchKeyword("new"))
			{
			SrcLoc newLoc = tok.Prev().loc;
			
			ExprFrag constructor = ParseLeftHandSideExpression(info, false);
			ArrayList args = null;
			if (tok.TryMatchOp("("))
				args = MatchOptionalArgumentList(info);
			
			expr = gen.Construct(newLoc, constructor, args);
			}
		else if (tok.TryMatchKeyword("function"))
			{
			SrcLoc functionLoc = tok.Prev().loc;
			FunctionInfo childInfo = info.GetNextChild();
			ParseFunction(childInfo, true);
			expr = gen.FunctionExpr(functionLoc, childInfo);
			}
		else
			expr = ParsePrimaryExpression(info);
		
		while (true)
			if (checkForCallExpr && tok.TryMatchOp("("))
				{
				SrcLoc opLoc = tok.Prev().loc;
				ArrayList args = MatchOptionalArgumentList(info);
				expr = gen.Call(opLoc, expr, args);
				}
			else if (tok.TryMatchOp("["))
				{
				SrcLoc opLoc = tok.Prev().loc;
				expr = gen.ArrayReference(opLoc, expr, this.ParseExpression(info, true));
				tok.MatchOp("]");
				}
			else if (tok.TryMatchOp("."))
				{
				SrcLoc opLoc = tok.Prev().loc;
				expr = gen.FieldReference(opLoc, expr, tok.MatchID());
				}
			else
				return expr;
		
		} // ParseLeftHandSideExpression
Exemple #3
0
        }         // ParseStringLiteral

        // Advance the stream past a comment beginning at the current stream
        // location.
        private void SkipComment(SrcLoc loc)
        {
            // HACK SN 7/13/01: rewrite this to support comments longer
            // than maxTokenLen.

            // Get a buffer from which we can parse the comment.
            char[] charBuf;
            int    startPos;
            int    bufLen = buffer.GetBuffer(maxTokenLen, out charBuf,
                                             out startPos);

            int tokenLen = 2;

            if (charBuf[startPos + 1] == '/')
            {
                // C++ style comment; search for end of line
                while (tokenLen < bufLen &&
                       !CharUtils.IsEOLChar(charBuf[startPos + tokenLen]))
                {
                    tokenLen++;
                }
            }
            else
            {
                // C style comment; search for "*/"
                // NOTE: we might extend this to warn for nested comments.
                while (tokenLen < bufLen - 1 &&
                       (charBuf[startPos + tokenLen] != '*' ||
                        charBuf[startPos + tokenLen + 1] != '/'))
                {
                    tokenLen++;
                }

                if (tokenLen >= bufLen - 1)
                {
                    loc.len = tokenLen;
                    throw new ParseError("unterminated /* comment", loc);
                }

                // Include the trailing "*/" in tokenLen.
                tokenLen += 2;
            }

            buffer.Skip(tokenLen);
        }         // SkipComment
Exemple #4
0
		} // ParseStatement
	
	
	// Parse a VariableDeclaration.  See ParseExpression for an explanation
	// of allowIN.  We set varName to the name of the declared variable.
	private StmtFrag ParseVariableDeclaration( FunctionInfo info, bool allowIN,
											   out string varName,
											   out SrcLoc varLoc )
		{
		varName = tok.MatchID();
		varLoc = tok.Prev().loc;
		if (tok.TryMatchOp("="))
			{
			SrcLoc opLoc = tok.Prev().loc;
			ExprFrag lhs = gen.IdentifierExpr( varLoc, varName, info,
											   CloneStack(withs) );
			ExprFrag rhs = ParseExpression(info, allowIN, assignmentPrec);
			ExprFrag assignment = gen.BinaryExpr(opLoc, "=", lhs, rhs);
			return gen.ExpressionStmt(assignment);
			}
		else
			return gen.NewStmtFrag(tok.Prev().loc);
		
		} // ParseVariableDeclaration
Exemple #5
0
		} // BoolLiteralExpr
	
	
	// Return an expression for the given numeric literal.
	public ExprFrag NumLiteralExpr(SrcLoc loc, double d)
		{
		return new CSharpRHSExpr(loc, System.Convert.ToString(d));
		} // NumLiteralExpr
Exemple #6
0
        }         // ParseNumber

        // Parse a string literal or regexp expression beginning at the current
        // stream location.
        private Token ParseStringLiteral(SrcLoc loc)
        {
            // HACK SN 7/14/01: rewrite this to support literals longer
            // than maxTokenLen.

            // HACK SN 7/14/01: parse regexps as well as single- or double-quoted strings

            // Get a buffer from which we can parse the string.
            char[] charBuf;
            int    startPos;
            int    bufLen = buffer.GetBuffer(maxTokenLen, out charBuf, out startPos);

            Trace.Assert(bufLen > 1);

            // Scan to find the end of the string.
            char          quoteChar          = charBuf[startPos];
            int           tokenLen           = 1;
            StringBuilder parsedValueBuilder = new StringBuilder();

            while (tokenLen < bufLen)
            {
                char curChar = charBuf[startPos + tokenLen];
                if (curChar == quoteChar)
                {
                    break;
                }
                else if (curChar == '\\')
                {
                    // HACK SN 7/14/01: extend this to parse all ECMAScript backslash
                    // sequences.

                    if (tokenLen + 1 >= bufLen)
                    {
                        throw new ParseError("unterminated string literal or regexp", loc);
                    }

                    curChar = charBuf[startPos + tokenLen + 1];
                    switch (curChar)
                    {
                    case 'b': curChar = '\b'; break;

                    case 'f': curChar = '\f'; break;

                    case 'n': curChar = '\n'; break;

                    case 'r': curChar = '\r'; break;

                    case 't': curChar = '\t'; break;

                    case 'v': curChar = '\v'; break;
                    }

                    parsedValueBuilder.Append(curChar);
                    tokenLen += 2;
                }
                else
                {
                    parsedValueBuilder.Append(curChar);
                    tokenLen++;
                }
            }             // while (tokenLen < bufLen)

            if (tokenLen >= bufLen)
            {
                throw new ParseError("unterminated string literal or regexp", loc);
            }

            loc.len = tokenLen + 1;
            StringLit litToken = new StringLit();

            litToken.rawText    = buffer.ConsumeString(tokenLen + 1);
            litToken.loc        = loc;
            litToken.parsedText = parsedValueBuilder.ToString();

            switch (quoteChar)
            {
            case '\'': litToken.quoteType = StringLit.QuoteType.singleQ; break;

            case '"':  litToken.quoteType = StringLit.QuoteType.doubleQ; break;

            case '/':  litToken.quoteType = StringLit.QuoteType.regexp;  break;

            default:
                Trace.Assert(false);
                break;
            }

            return(litToken);
        }         // ParseStringLiteral
Exemple #7
0
        }         // ParseIdentifier

        // Parse a numeric literal beginning at the current stream location.
        private Token ParseNumber(SrcLoc loc)
        {
            // Get a buffer from which we can parse the number.
            char[] charBuf;
            int    startPos;
            int    bufLen = buffer.GetBuffer(maxTokenLen, out charBuf,
                                             out startPos);

            if (bufLen > maxTokenLen)
            {
                bufLen = maxTokenLen;
            }

            // Find the end of the number.  We match for the following
            // components:
            //
            //    integer part (1 or more digits)
            //    optional fractional part ('.' plus one or more digits)
            //    optional exponent ('E' or 'e', optional '+' or '-', and 1-3 digits)
            //
            // HACK SN 7/14/01: for now, we aren't enforcing that the fractional
            // part must have at least one digit, or that the exponent must have
            // at least 1 and no more than 3 digits.  Review the ECMAScript spec for
            // the correct rules.  Also, should we allow numbers that begin with a '.'
            // (no integer part)?

            int tokenLen = 0;

            while (tokenLen < bufLen &&
                   CharUtils.IsDigitChar(charBuf[startPos + tokenLen]))
            {
                tokenLen++;
            }

            if (tokenLen < bufLen && charBuf[startPos + tokenLen] == '.')
            {
                tokenLen++;
                while (tokenLen < bufLen &&
                       CharUtils.IsDigitChar(charBuf[startPos + tokenLen]))
                {
                    tokenLen++;
                }
            }

            if (tokenLen < bufLen &&
                (charBuf[startPos + tokenLen] == 'E' ||
                 charBuf[startPos + tokenLen] == 'e'))
            {
                tokenLen++;
                if (tokenLen < bufLen &&
                    (charBuf[startPos + tokenLen] == '+' ||
                     charBuf[startPos + tokenLen] == '-'))
                {
                    tokenLen++;
                }

                while (tokenLen < bufLen &&
                       CharUtils.IsDigitChar(charBuf[startPos + tokenLen]))
                {
                    tokenLen++;
                }
            }

            NumLit token = new NumLit();

            token.rawText = buffer.ConsumeString(tokenLen);
            loc.len       = tokenLen;
            token.loc     = loc;

            try
            {
                token.value = Double.Parse(token.rawText);
            }
            catch (FormatException e)
            {
                throw new ParseError("FormatException parsing numeric literal \"" +
                                     token.rawText + "\": " + e.ToString(),
                                     loc);
            }
            catch (OverflowException e)
            {
                throw new ParseError("OverflowException parsing numeric literal \"" +
                                     token.rawText + "\": " + e.ToString(),
                                     loc);
            }

            return(token);
        }         // ParseNumber
Exemple #8
0
		} // NewLabeledStmtInfo
	
	
	// Return a new WithInfo object.
	public WithInfo NewWithInfo(CGFuncInfo cgFuncInfo, SrcLoc loc)
		{
		return new CSharpWithInfo((CSharpGenFuncInfo)cgFuncInfo, loc);
		} // NewWithInfo
Exemple #9
0
		} // NewStmtFrag
	
	
	// Return a new LoopInfo object for an iteratiion statement with the
	// given label set.  The labels parameter can be null if there were no
	// labels.
	public LoopInfo NewLoopInfo( CGFuncInfo cgFuncInfo, SrcLoc loc,
								 StringCollection labels )
		{
		return new CSharpLoopInfo( (CSharpGenFuncInfo)cgFuncInfo, loc, labels,
								   true, false );
		} // NewLoopInfo
Exemple #10
0
	internal CSharpRHSExpr(SrcLoc loc, string code) : base(loc)
		{
		code_ = code;
		} // CSharpRHSExpr constructor
Exemple #11
0
	internal CSharpWithInfo(CSharpGenFuncInfo cgInfo, SrcLoc loc)
		{
		this.loc = loc;
		this.index = cgInfo.withCount++;
		} // CSharpWithInfo constructor
Exemple #12
0
		} // NullExpr
	
	
	// Return a BooleanLiteral expression.
	public ExprFrag BoolLiteralExpr(SrcLoc loc, bool b)
		{
		return new CSharpRHSExpr(loc, (b) ? "true" : "false");
		} // BoolLiteralExpr
Exemple #13
0
		} // ParseStringLiteral
	
	
	// Advance the stream past a comment beginning at the current stream
	// location.
	private void SkipComment(SrcLoc loc)
		{
		// HACK SN 7/13/01: rewrite this to support comments longer
		// than maxTokenLen.
		
		// Get a buffer from which we can parse the comment.
		char[] charBuf;
		int startPos;
		int bufLen = buffer.GetBuffer( maxTokenLen, out charBuf,
									   out startPos );
		
		int tokenLen = 2;
		if (charBuf[startPos+1] == '/')
			{
			// C++ style comment; search for end of line
			while ( tokenLen < bufLen &&
					!CharUtils.IsEOLChar(charBuf[startPos+tokenLen]) )
				tokenLen++;
			}
		else
			{
			// C style comment; search for "*/"
			// NOTE: we might extend this to warn for nested comments.
			while ( tokenLen < bufLen-1 &&
					( charBuf[startPos+tokenLen  ] != '*' ||
					  charBuf[startPos+tokenLen+1] != '/' ) )
				tokenLen++;
			
			if (tokenLen >= bufLen-1)
				{
				loc.len = tokenLen;
				throw new ParseError("unterminated /* comment", loc);
				}
			
			// Include the trailing "*/" in tokenLen.
			tokenLen += 2;
			}
		
		buffer.Skip(tokenLen);
		} // SkipComment
Exemple #14
0
		} // ThisExpr
	
	
	// Return an expression for the keyword "null".
	public ExprFrag NullExpr(SrcLoc loc)
		{
		return new CSharpRHSExpr(loc, "null");
		} // NullExpr
Exemple #15
0
		} // Construct
	
	
	// Return an expression for the keyword "this".
	public ExprFrag ThisExpr(SrcLoc loc, FunctionInfo info)
		{
		if (info.isRoot)
			return new CSharpRHSExpr(loc, "globals");
		else
			return new CSharpRHSExpr(loc, "this_");
		
		} // ThisExpr
Exemple #16
0
		} // Call
	
	
	// Return an expression for a constructor call (a "new" expression).
	// args is an array of ExprFrags, or null if no parameter list was
	// provided.
	public ExprFrag Construct(SrcLoc loc, ExprFrag functionExpr, ArrayList args)
		{
		String code = ((CSharpExprFrag)functionExpr).GenerateCall(args, true);
		return new CSharpRHSExpr(loc, code);
		} // Construct
Exemple #17
0
		} // ParseLeftHandSideExpression
	
	
	// Parse a PrimaryExpression.
	private ExprFrag ParsePrimaryExpression(FunctionInfo info)
		{
		string id;
		double d;
		string s;
		
		if (tok.TryMatchKeyword("this"))
			return gen.ThisExpr(tok.Prev().loc, info);
		else if (tok.TryMatchKeyword("null"))
			return gen.NullExpr(tok.Prev().loc);
		else if (tok.TryMatchKeyword("true"))
			return gen.BoolLiteralExpr(tok.Prev().loc, true);
		else if (tok.TryMatchKeyword("false"))
			return gen.BoolLiteralExpr(tok.Prev().loc, false);
		else if (tok.TryMatchOp("("))
			{
			ExprFrag expr = ParseExpression(info, true);
			tok.MatchOp(")");
			return expr;
			}
		else if (tok.TryMatchOp("{"))
			{
			SrcLoc startLoc = tok.Prev().loc;
			ObjectLiteralInfo litInfo = gen.NewObjectLiteralInfo();
			
			if (!tok.PeekOp("}"))
				{
				do
					{
					double tempD;
					if (tok.TryMatchNumLit(out tempD))
						{
						// HACK snewman 7/26/01: format according to the ECMA spec.
						id = System.Convert.ToString(tempD);
						}
					else if (tok.TryMatchStringLit(out id))
						{}
					else
						id = tok.MatchID();
					
					SrcLoc idLoc = tok.Prev().loc;
					tok.MatchOp(":");
					ExprFrag value = ParseExpression(info, true, assignmentPrec);
					
					litInfo.AddProp(idLoc, id, value);
					}
				while (tok.TryMatchOp(","));
				}
			
			tok.MatchOp("}");
			
			return gen.ObjectLiteralExpr(startLoc, litInfo);
			}
		else if (tok.TryMatchOp("["))
			{
			SrcLoc startLoc = tok.Prev().loc;
			ArrayLiteralInfo arrayInfo = gen.NewArrayLiteralInfo();
			
			bool anyCommas = false;
			bool requireComma = false;
			while (!tok.PeekOp("]"))
				if (tok.TryMatchOp(","))
					{
					anyCommas = true;
					if (!requireComma)
						arrayInfo.AddEntry(null);
					else
						requireComma = false;
					}
				else if (!requireComma)
					{
					ExprFrag value = ParseExpression(info, true, assignmentPrec);
					arrayInfo.AddEntry(value);
					requireComma = true;
					}
				else
					break;
			
			// If the list ends with a comma, then add one more null entry
			// to the end.
			if (anyCommas && !requireComma)
				arrayInfo.AddEntry(null);
			
			tok.MatchOp("]");
			return gen.ArrayLiteralExpr(startLoc, arrayInfo);
			}
		else if (tok.TryMatchID(out id))
			{
			SrcLoc idLoc = tok.Prev().loc;
			if (id == "eval")
				return gen.IdentifierExpr(idLoc, id, info, CloneStack(withs));
			else if (id == "arguments")
				return gen.ArgumentsExpr(idLoc, info, CloneStack(withs));
			else
				return gen.IdentifierExpr(idLoc, id, info, CloneStack(withs));
			
			}
		else if (tok.TryMatchNumLit(out d))
			return gen.NumLiteralExpr(tok.Prev().loc, d);
		else if (tok.TryMatchStringLit(out s))
			return gen.StringLiteralExpr(tok.Prev().loc, s);
		else
			{
			// One of the if clauses should fire; if not, the phase 1
			// parser would have reported an error.
			Trace.Assert(false);
			return null;
			}
		
		} // ParsePrimaryExpression
Exemple #18
0
		} // ParseExpression
	
	
	// Parse an Expression.
	// 
	// If allowIN is false, then we don't look for "in" operators.  (This
	// implements the "NoIn" variant of the grammar, e.g. ExpressionNoIn
	// as opposed to Expression.)
	// 
	// This method can also be used to parse "smaller" nonterminals such
	// as AssignmentExpression, ConditionalExpression, and so on down to
	// MultiplicativeExpression.  This is controlled by the maxPrecedence
	// parameter: we ignore any operators with a looser (numerically
	// greater) precedence than maxPrecedence.
	private ExprFrag ParseExpression( FunctionInfo info, bool allowIN,
								      int maxPrecedence )
		{
		// Note that we use a simpler grammar than ECMAScript, because
		// we don't need to catch assignment to non-lvalue in the parser
		// (it will have been caught in phase 1).
		
		// Parse any prefix operators.
		Stack stackedOps = new Stack();
		Stack stackedOpsLocs = new Stack();
		OperatorInfo matchedOp;
		while (TryMatchOperator(true, -1, out matchedOp, true))
			{
			stackedOps.Push(matchedOp);
			stackedOpsLocs.Push(tok.Prev().loc);
			}
		
		ExprFrag expr = ParseLeftHandSideExpression(info, true);
		
		if (stackedOps.Count > 0)
			{
			while (TryMatchOperator(allowIN, unarySuffixPrec, out matchedOp, true))
				{
				Trace.Assert(matchedOp.opType == OperatorInfo.Types.unarySuffix);
				expr = gen.UnaryExpr( tok.Prev().loc, matchedOp.text,
									  matchedOp.opType == OperatorInfo.Types.unarySuffix,
									  expr );
				}
			
			while (stackedOps.Count > 0)
				{
				OperatorInfo curOp = (OperatorInfo)stackedOps.Pop();
				expr = gen.UnaryExpr( (SrcLoc)stackedOpsLocs.Pop(),
									  curOp.text,
									  curOp.opType == OperatorInfo.Types.unarySuffix,
									  expr );
				}
			
			} // if (stackedOps.Count > 0)
		
		while (TryMatchOperator(allowIN, maxPrecedence, out matchedOp, true))
			{
			SrcLoc opLoc = tok.Prev().loc;
			if (matchedOp.text == "?")
				{
				ExprFrag p1 = ParseExpression(info, allowIN, assignmentPrec);
				tok.MatchOp(":");
				ExprFrag p2 = ParseExpression(info, allowIN, assignmentPrec);
				expr = gen.ConditionalExpr(opLoc, expr, p1, p2);
				}
			else if (matchedOp.opType == OperatorInfo.Types.assignment)
				expr = gen.BinaryExpr( opLoc, matchedOp.text, expr,
									   ParseExpression(info, allowIN, matchedOp.precedence) );
			else if (matchedOp.opType == OperatorInfo.Types.binary)
				expr = gen.BinaryExpr( opLoc, matchedOp.text, expr,
									   ParseExpression(info, allowIN, matchedOp.precedence-1) );
			else
				{
				Trace.Assert(matchedOp.opType == OperatorInfo.Types.unarySuffix);
				expr = gen.UnaryExpr( opLoc, matchedOp.text,
									  matchedOp.opType == OperatorInfo.Types.unarySuffix,
									  expr );
				}
			
			}
		
		return expr;
		} // ParseExpression
Exemple #19
0
		} // ReadNextToken
	
	
	// Parse an identifier beginning at the current stream location.
	private Token ParseIdentifier(SrcLoc loc)
		{
		// Get a buffer from which we can parse the identifier.
		char[] charBuf;
		int startPos;
		int bufLen = buffer.GetBuffer( maxTokenLen, out charBuf,
									   out startPos );
		if (bufLen > maxTokenLen)
			bufLen = maxTokenLen;
		
		// Find the last character in the identifier.  We begin
		// at 1 because we know (from matcher.Match returning
		// TokDispatch.ident) that the identifier is at least
		// one character long.
		int tokenLen = 1;
		while ( tokenLen < bufLen &&
				CharUtils.IsIdentifierChar(charBuf[startPos+tokenLen]) )
			tokenLen++;
		
		Identifier token = new Identifier();
		token.rawText = buffer.ConsumeString(tokenLen);
		loc.len = tokenLen;
		token.loc = loc;
		return token;
		} // ParseIdentifier
Exemple #20
0
		} // NumLiteralExpr
	
	
	// Return a StringLiteral expression.
	public ExprFrag StringLiteralExpr(SrcLoc loc, string s)
		{
		StringBuilder escapedBuilder = new StringBuilder();
		escapedBuilder.Append("@\"");
		
		foreach (char c in s)
			if (c == '"')
				escapedBuilder.Append("\"\"");
			else
				escapedBuilder.Append(c);
		
		escapedBuilder.Append("\"");
		
		return new CSharpRHSExpr(loc, escapedBuilder.ToString());
		} // StringLiteralExpr
Exemple #21
0
	internal CSharpLoopInfo( CSharpGenFuncInfo cgInfo, SrcLoc loc,
							 StringCollection labels, bool isLoop,
							 bool isSwitch )
		{
		this.loc      = loc;
		this.labels   = labels;
		this.isLoop   = isLoop;
		this.isSwitch = isSwitch;
		this.index    = cgInfo.loopCount++;
		} // CSharpLoopInfo constructor
Exemple #22
0
		} // StringLiteralExpr
	
	
	// Return an expression to reference the given identifier.
	// enclosingWiths should be a stack of WithInfo objects, giving
	// all with scopes in the current function that enclose the identifier
	// reference.
	// 
	// HACK snewman 8/13/01: this method, and ArgumentsExpr below, need a
	// way to search "with" statements in enclosing scopes (for function
	// expressions and expr code).
	public ExprFrag IdentifierExpr( SrcLoc loc, string id,
									FunctionInfo function,
									Stack enclosingWiths )
		{
		// HACK snewman 8/20/01: extend this to support function scopes
		// where not all identifiers are known at compile time (because
		// they invoke "eval").
		
		// Determine which enclosing scope, if any, defines the identifier.
		FunctionInfo bindingScope = function;
		while (bindingScope != null && !bindingScope.IDBoundInThisScope(id))
			bindingScope = bindingScope.parent;
		
		// HACK snewman 8/20/01: add support for locals that are implemented
		// directly as C# locals.  I think this needs to be added in some
		// other places as well, such as EmitFunction.
		if (bindingScope == null || bindingScope.isRoot)
			return new CSharpVariableRef(loc, id, null, enclosingWiths);
		else if (bindingScope == function)
			return new CSharpVariableRef(loc, id, function, enclosingWiths);
		else
			{
			// HACK snewman 8/20/01: add support for referencing a local
			// variable of an enclosing scope.
			throw new ParseError( "Access to parent function variables not yet implemented",
								  loc );
			}
		
		} // IdentifierExpr
Exemple #23
0
	public void AddProp(SrcLoc loc, string id, ExprFrag value)
		{
		Entry newEntry = new Entry();
		newEntry.loc   = loc;
		newEntry.id    = id;
		newEntry.value = value;
		entries.Add(newEntry);
		}
Exemple #24
0
		} // IdentifierExpr
	
	
	// Return an expression to reference the identifier "arguments".
	// enclosingWiths should be a stack of WithInfo objects, giving
	// all with scopes in the current function that enclose the identifier
	// reference.
	public ExprFrag ArgumentsExpr( SrcLoc loc, FunctionInfo function,
								   Stack enclosingWiths )
		{
		// HACK snewman 8/20/01: implement this.  Support "with"
		// scopes... we may be able to just fall through into
		// IdentifierExpr.
		throw new ParseError( "\"arguments\" not yet implemented",
							  loc );
		} // ArgumentsExpr
Exemple #25
0
		} // EmitStatements
	
	
	// Return a new, empty StmtFrag object.
	public StmtFrag NewStmtFrag(SrcLoc loc)
		{
		return new CSharpStmtFrag(loc);
		} // NewStmtFrag
Exemple #26
0
		} // ArgumentsExpr
	
	
	// Return a FunctionExpr.
	public ExprFrag FunctionExpr(SrcLoc loc, FunctionInfo childInfo)
		{
		// HACK snewman 8/15/01: implement function expressions.
		throw new ParseError( "Function expressions not yet implemented",
							  loc );
		} // FunctionExpr
Exemple #27
0
		} // NewLoopInfo
	
	
	// Return a new LoopInfo object for a labeled non-iteration statement
	// with the given label set.  isSwitch should be true if the statement
	// was a switch statement; in this case, if the statement had no labels,
	// the labels parameter can be null.
	public LoopInfo NewLabeledStmtInfo( CGFuncInfo cgFuncInfo, SrcLoc loc,
										StringCollection labels,
										bool isSwitch )
		{
		Trace.Assert(labels != null || isSwitch);
		return new CSharpLoopInfo( (CSharpGenFuncInfo)cgFuncInfo, loc, labels,
								   false, isSwitch );
		} // NewLabeledStmtInfo
Exemple #28
0
		} // FunctionExpr
	
	
	// Return an ObjectLiteral expression.
	public ExprFrag ObjectLiteralExpr(SrcLoc loc, ObjectLiteralInfo litInfo)
		{
		StringBuilder builder = new StringBuilder();
		builder.Append("Support.LiteralObject(");
		
		CSharpObjectLiteral csInfo = (CSharpObjectLiteral)litInfo;
		bool first = true;
		foreach (CSharpObjectLiteral.Entry entry in csInfo.entries)
			{
			if (first)
				first = false;
			else
				builder.Append(", ");
			
			builder.Append("\"");
			builder.Append(entry.id);
			builder.Append("\", ");
			builder.Append(((CSharpExprFrag)entry.value).GenerateRHS());
			}
		
		builder.Append(")");
		
		return new CSharpRHSExpr(loc, builder.ToString());
		} // ObjectLiteralExpr
Exemple #29
0
		} // ExpressionStmt
	
	
	// Return an if/then or if/then/else statement.  If there was no else
	// clause, elseClause will be null.
	public StmtFrag IfThenElse( SrcLoc loc, ExprFrag condition,
								StmtFrag ifClause, StmtFrag elseClause )
		{
		CSharpStmtFrag frag = new CSharpStmtFrag(loc);
		
		CSharpExprFrag csCondition = (CSharpExprFrag)condition;
		frag.Append("if (Support.BoolTest(" + csCondition.GenerateRHS() + "))");
		frag.AppendIndentedBody(ifClause);
		
		if (elseClause != null)
			{
			frag.Append("else");
			frag.AppendIndentedBody(elseClause);
			}
		
		return frag;
		} // IfThenElse
Exemple #30
0
		} // ObjectLiteralExpr
	
	
	// Return an ArrayLiteral expression.
	public ExprFrag ArrayLiteralExpr(SrcLoc loc, ArrayLiteralInfo arrayInfo)
		{
		// HACK snewman 8/28/01: properly implement missing elements in
		// the original array literal (commas with no values in between
		// them).  Properly implement the array "length" property.
		
		StringBuilder builder = new StringBuilder();
		builder.Append("Support.LiteralArray(");
		
		CSharpArrayLiteral csInfo = (CSharpArrayLiteral)arrayInfo;
		bool first = true;
		foreach (CSharpExprFrag entry in csInfo.entries)
			{
			if (first)
				first = false;
			else
				builder.Append(", ");
			
			builder.Append(entry.GenerateRHS());
			}
		
		builder.Append(")");
		
		return new CSharpRHSExpr(loc, builder.ToString());
		} // ArrayLiteralInfo
Exemple #31
0
 public ParseError(string message, SrcLoc loc) : base(message)
 {
     this.loc = loc;
 }
Exemple #32
0
	internal CSharpArrayRef(SrcLoc loc, string arrayCode, string indexCode)
	  : base(loc)
		{
		this.arrayCode = arrayCode;
		this.indexCode = indexCode;
		} // CSharpArrayRef constructor
Exemple #33
0
	internal CSharpFieldRef(SrcLoc loc, string objectCode, string id)
	  : base(loc)
		{
		this.objectCode = objectCode;
		this.id = id;
		} // CSharpFieldRef constructor
Exemple #34
0
	// Construct a CSharpVariableRef for a reference at the given location,
	// to the given variable, in the given function, and in the given stack
	// of WithInfo objects.  function should be null for global variable
	// references.
	internal CSharpVariableRef( SrcLoc loc, string id, FunctionInfo function,
							    Stack enclosingWiths )
	  : base(loc)
		{
		this.id = id;
		this.function = function;
		this.enclosingWiths = enclosingWiths;
		} // CSharpVariableRef constructor
Exemple #35
0
		} // ParseNumber
	
	
	// Parse a string literal or regexp expression beginning at the current
	// stream location.
	private Token ParseStringLiteral(SrcLoc loc)
		{
		// HACK SN 7/14/01: rewrite this to support literals longer
		// than maxTokenLen.
		
		// HACK SN 7/14/01: parse regexps as well as single- or double-quoted strings
		
		// Get a buffer from which we can parse the string.
		char[] charBuf;
		int startPos;
		int bufLen = buffer.GetBuffer(maxTokenLen, out charBuf, out startPos);
		Trace.Assert(bufLen > 1);
		
		// Scan to find the end of the string.
		char quoteChar = charBuf[startPos];
		int tokenLen = 1;
		StringBuilder parsedValueBuilder = new StringBuilder();
		while (tokenLen < bufLen)
			{
			char curChar = charBuf[startPos+tokenLen];
			if (curChar == quoteChar)
				break;
			else if (curChar == '\\')
				{
				// HACK SN 7/14/01: extend this to parse all ECMAScript backslash
				// sequences.
				
				if (tokenLen+1 >= bufLen)
					throw new ParseError("unterminated string literal or regexp", loc);
				
				curChar = charBuf[startPos+tokenLen+1];
				switch (curChar)
					{
					case 'b': curChar = '\b'; break;
					case 'f': curChar = '\f'; break;
					case 'n': curChar = '\n'; break;
					case 'r': curChar = '\r'; break;
					case 't': curChar = '\t'; break;
					case 'v': curChar = '\v'; break;
					}
				
				parsedValueBuilder.Append(curChar);
				tokenLen += 2;
				}
			else
				{
				parsedValueBuilder.Append(curChar);
				tokenLen++;
				}
			
			} // while (tokenLen < bufLen)
		
		if (tokenLen >= bufLen)
			throw new ParseError("unterminated string literal or regexp", loc);
		
		loc.len = tokenLen + 1;
		StringLit litToken = new StringLit();
		litToken.rawText    = buffer.ConsumeString(tokenLen+1);
		litToken.loc        = loc;
		litToken.parsedText = parsedValueBuilder.ToString();
		
		switch (quoteChar)
			{
			case '\'': litToken.quoteType = StringLit.QuoteType.singleQ; break;
			case '"':  litToken.quoteType = StringLit.QuoteType.doubleQ; break;
			case '/':  litToken.quoteType = StringLit.QuoteType.regexp;  break;
			
			default:
				Trace.Assert(false);
				break;
			}
		
		return litToken;
		} // ParseStringLiteral
Exemple #36
0
	internal CSharpExprFrag(SrcLoc loc)
		{
		loc_ = loc;
		} // CSharpExprFrag constructor
Exemple #37
0
	public ParseError(string message, SrcLoc loc) : base(message) { this.loc = loc; }
Exemple #38
0
	internal CSharpStmtFrag(SrcLoc loc)
		{
		loc_  = loc;
		code_ = null;
		last_ = null;
		used_ = false;
		} // CSharpStmtFrag constructor
Exemple #39
0
		} // ParseIdentifier
	
	
	// Parse a numeric literal beginning at the current stream location.
	private Token ParseNumber(SrcLoc loc)
		{
		// Get a buffer from which we can parse the number.
		char[] charBuf;
		int startPos;
		int bufLen = buffer.GetBuffer( maxTokenLen, out charBuf,
									   out startPos );
		if (bufLen > maxTokenLen)
			bufLen = maxTokenLen;
		
		// Find the end of the number.  We match for the following
		// components:
		// 
		//    integer part (1 or more digits)
		//    optional fractional part ('.' plus one or more digits)
		//    optional exponent ('E' or 'e', optional '+' or '-', and 1-3 digits)
		// 
		// HACK SN 7/14/01: for now, we aren't enforcing that the fractional
		// part must have at least one digit, or that the exponent must have
		// at least 1 and no more than 3 digits.  Review the ECMAScript spec for
		// the correct rules.  Also, should we allow numbers that begin with a '.'
		// (no integer part)?
		
		int tokenLen = 0;
		while ( tokenLen < bufLen &&
				CharUtils.IsDigitChar(charBuf[startPos+tokenLen]) )
			tokenLen++;
		
		if (tokenLen < bufLen && charBuf[startPos+tokenLen] == '.')
			{
			tokenLen++;
			while ( tokenLen < bufLen &&
					CharUtils.IsDigitChar(charBuf[startPos+tokenLen]) )
				tokenLen++;
			}
		
		if ( tokenLen < bufLen &&
			 ( charBuf[startPos+tokenLen] == 'E' ||
			   charBuf[startPos+tokenLen] == 'e' ) )
			{
			tokenLen++;
			if ( tokenLen < bufLen &&
				 ( charBuf[startPos+tokenLen] == '+' ||
				   charBuf[startPos+tokenLen] == '-' ) )
				tokenLen++;
			
			while ( tokenLen < bufLen &&
					CharUtils.IsDigitChar(charBuf[startPos+tokenLen]) )
				tokenLen++;
			}
		
		NumLit token = new NumLit();
		token.rawText = buffer.ConsumeString(tokenLen);
		loc.len = tokenLen;
		token.loc = loc;
		
		try
			{
			token.value = Double.Parse(token.rawText);
			}
		catch (FormatException e)
			{
			throw new ParseError( "FormatException parsing numeric literal \"" +
								  token.rawText + "\": " + e.ToString(),
								  loc );
			}
		catch (OverflowException e)
			{
			throw new ParseError( "OverflowException parsing numeric literal \"" +
								  token.rawText + "\": " + e.ToString(),
								  loc );
			}
		
		return token;
		} // ParseNumber
Exemple #40
0
		} // ParseForStatement
	
	
	// Parse a Statement.
	private StmtFrag ParseStatement(FunctionInfo info)
		{
		StringCollection labels = MatchLabelSet();
		
		if (tok.TryMatchKeyword("do"))
			{
			LoopInfo loopInfo = gen.NewLoopInfo( curCGFuncInfo, tok.Prev().loc,
												 labels );
			loops.Push(loopInfo);
			
			StmtFrag body = ParseStatement(info);
			tok.MatchKeyword("while");
			tok.MatchOp("(");
			ExprFrag condition = ParseExpression(info, true);
			tok.MatchOp(")");
			tok.MatchOp(";");
			
			LoopInfo temp = (LoopInfo) loops.Pop();
			Trace.Assert(temp == loopInfo);
			
			return gen.DoWhile(loopInfo, body, condition);
			}
		else if (tok.TryMatchKeyword("while"))
			{
			LoopInfo loopInfo = gen.NewLoopInfo( curCGFuncInfo, tok.Prev().loc,
												 labels );
			loops.Push(loopInfo);
			
			tok.MatchOp("(");
			ExprFrag condition = ParseExpression(info, true);
			tok.MatchOp(")");
			StmtFrag body = ParseStatement(info);
			
			LoopInfo temp = (LoopInfo) loops.Pop();
			Trace.Assert(temp == loopInfo);
			
			return gen.WhileDo(loopInfo, condition, body);
			}
		else if (tok.TryMatchKeyword("for"))
			return ParseForStatement(info, labels);
		else
			{
			bool isSwitch = tok.PeekKeyword("switch");
			LoopInfo labelInfo = null;
			if (labels != null || isSwitch)
				{
				labelInfo = gen.NewLabeledStmtInfo( curCGFuncInfo, tok.Prev().loc,
													labels, isSwitch );
				loops.Push(labelInfo);
				}
			
			StmtFrag stmt;
			if (tok.PeekOp("{"))
				stmt = ParseBlock(info);
			else if (tok.TryMatchKeyword("var"))
				{
				stmt = gen.NewStmtFrag(tok.Prev().loc);
				
				do
					{
					string varName;
					SrcLoc varLoc;
					stmt.Append(ParseVariableDeclaration( info, true, out varName,
														  out varLoc ));
					}
				while (tok.TryMatchOp(","));
				tok.MatchOp(";");
				}
			else if (tok.TryMatchOp(";"))
				{
				// EmptyStatement
				stmt = gen.NewStmtFrag(tok.Prev().loc);
				}
			else if (tok.TryMatchKeyword("if"))
				{
				SrcLoc ifLoc = tok.Prev().loc;
				
				tok.MatchOp("(");
				ExprFrag condition = ParseExpression(info, true);
				tok.MatchOp(")");
				
				StmtFrag ifClause = ParseStatement(info);
				StmtFrag elseClause = null;
				if (tok.TryMatchKeyword("else"))
					elseClause = ParseStatement(info);
				
				stmt = gen.IfThenElse(ifLoc, condition, ifClause, elseClause);
				}
			else if (tok.TryMatchKeyword("continue"))
				{
				SrcLoc continueLoc = tok.Prev().loc;
				
				// HACK snewman 8/7/01: the grammar (ContinueStatement) specifies
				// "no LineTerminator here".
				string id;
				tok.TryMatchID(out id);
				tok.MatchOp(";");
				
				stmt = gen.Continue(continueLoc, id, CloneStack(loops));
				}
			else if (tok.TryMatchKeyword("break"))
				{
				SrcLoc breakLoc = tok.Prev().loc;
				
				// HACK snewman 8/7/01: the grammar (BreakStatement) specifies
				// "no LineTerminator here".
				string id;
				tok.TryMatchID(out id);
				tok.MatchOp(";");
				
				stmt = gen.Break(breakLoc, id, CloneStack(loops));
				}
			else if (tok.TryMatchKeyword("return"))
				{
				SrcLoc returnLoc = tok.Prev().loc;
				
				// HACK snewman 8/7/01: the grammar (ReturnStatement) specifies
				// "no LineTerminator here".
				if (tok.TryMatchOp(";"))
					stmt = gen.Return(returnLoc, null);
				else
					{
					ExprFrag value = ParseExpression(info, true);
					tok.MatchOp(";");
					stmt = gen.Return(returnLoc, value);
					}
				
				}
			else if (tok.TryMatchKeyword("with"))
				{
				SrcLoc withLoc = tok.Prev().loc;
				
				tok.MatchOp("(");
				ExprFrag value = ParseExpression(info, true);
				tok.MatchOp(")");
				
				WithInfo withInfo = gen.NewWithInfo(curCGFuncInfo, withLoc);
				withs.Push(withInfo);
				
				StmtFrag body = ParseStatement(info);
				
				WithInfo temp = (WithInfo) withs.Pop();
				Trace.Assert(temp == withInfo);
				
				stmt = gen.With(withInfo, value, body);
				}
			else if (tok.TryMatchKeyword("switch"))
				{
				SrcLoc switchLoc = tok.Prev().loc;
				SwitchInfo switchInfo = gen.NewSwitchInfo();
				
				tok.MatchOp("(");
				ExprFrag switchValue = ParseExpression(info, true);
				tok.MatchOp(")");
				
				tok.MatchOp("{");
				while (!tok.TryMatchOp("}"))
					{
					ExprFrag caseValue;
					if (tok.TryMatchKeyword("default"))
						caseValue = null;
					else
						{
						tok.MatchKeyword("case");
						caseValue = ParseExpression(info, true);
						}
					
					StmtFrag clauseStmt = null;
					tok.MatchOp(":");
					while ( !tok.PeekOp("}") && !tok.PeekKeyword("case") &&
							!tok.PeekKeyword("default") )
						{
						StmtFrag tempStmt = ParseStatement(info);
						if (clauseStmt == null)
							clauseStmt = tempStmt;
						else
							clauseStmt.Append(tempStmt);
						}
					
					switchInfo.AddCase(caseValue, clauseStmt);
					}
				
				stmt = gen.Switch(switchLoc, switchValue, switchInfo);
				}
			else if (tok.TryMatchKeyword("throw"))
				{
				SrcLoc throwLoc = tok.Prev().loc;
				
				// HACK snewman 8/7/01: the grammar (ThrowStatement) specifies
				// "no LineTerminator here".
				ExprFrag value = ParseExpression(info, true);
				tok.MatchOp(";");
				
				stmt = gen.Throw(throwLoc, value);
				}
			else if (tok.TryMatchKeyword("try"))
				{
				SrcLoc tryLoc = tok.Prev().loc;
				StmtFrag tryBody = ParseBlock(info);
				String catchVar        = null;
				WithInfo catchWithInfo = null;
				StmtFrag catchBody     = null;
				StmtFrag finallyBody   = null;
				
				if (tok.TryMatchKeyword("catch"))
					{
					SrcLoc catchLoc = tok.Prev().loc;
					
					tok.MatchOp("(");
					catchVar = tok.MatchID();
					tok.MatchOp(")");
					
					catchWithInfo = gen.NewWithInfo(curCGFuncInfo, catchLoc);
					withs.Push(catchWithInfo);
					
					catchBody = ParseBlock(info);
					
					WithInfo temp = (WithInfo) withs.Pop();
					Trace.Assert(temp == catchWithInfo);
					}
				
				if (tok.TryMatchKeyword("finally"))
					finallyBody = ParseBlock(info);
				
				stmt = gen.TryCatchFinally( tryLoc, tryBody, catchVar,
											catchWithInfo, catchBody, finallyBody );
				}
			else
				{
				ExprFrag expr = ParseExpression(info, true);
				tok.MatchOp(";");
				stmt = gen.ExpressionStmt(expr);
				}
			
			if (labelInfo != null)
				{
				LoopInfo temp2 = (LoopInfo) loops.Pop();
				Trace.Assert(temp2 == labelInfo);
				
				stmt = gen.LabeledStmt(labelInfo, stmt);
				}
			
			return stmt;
			}
		
		} // ParseStatement