static Optional <ProjectBytecode> TryCompile(ProjectMarkup markup, IObserver <IBinaryMessage> buildEvents, Guid buildId) { try { var projectDirectory = Path.GetDirectoryName(markup.Build.Project); var dependencies = ImmutableList.ToImmutableList( markup.Project.RootClasses .SelectMany(node => ImportExpression.FindFiles(node, projectDirectory)) .Distinct()); var ids = ProjectObjectIdentifiers.Create(markup.Project, markup.Build.TypeInfo, onError: e => ReportFactory.FallbackReport.Exception("Failed to create identifiers for document", e)); var ctx = new Context( names: new UniqueNames(), tryGetTagHash: ids.TryGetIdentifier, projectDirectory: projectDirectory, typesDeclaredInUx: markup.Project .AllNodesInProject() .OfType <ClassNode>() .Select(c => c.GetTypeName()) .ToImmutableHashSet()); var reify = markup.Project.GenerateGlobalScopeConstructor(ctx); var metadata = markup.Project.GenerateMetadata(ids); return(new ProjectBytecode(reify, dependencies, metadata)); } catch (Exception e) { buildEvents.OnNext(new BuildIssueDetected(BuildIssueType.Error, "", e.Message, Optional.None(), buildId)); return(Optional.None()); } }
public ISymbolValue Visit(ImportExpression x) { var strType = GetStringType(); var cnst = resolveConstOnly; resolveConstOnly = true; var v = x.AssignExpression != null?x.AssignExpression.Accept(this) as ArrayValue : null; resolveConstOnly = cnst; if (v == null || !v.IsString) { EvalError(new InvalidStringException(x)); return(null); } var fn = Path.IsPathRooted(v.StringValue) ? v.StringValue : Path.Combine(Path.GetDirectoryName((ctxt.ScopedBlock.NodeRoot as DModule).FileName), v.StringValue); if (!File.Exists(fn)) { EvalError(x, "Could not find \"" + fn + "\""); return(null); } var text = File.ReadAllText(fn); return(new ArrayValue(GetStringType(), text)); }
ISemantic E(ImportExpression x) { var strType = GetStringType(); if (eval) { var cnst = resolveConstOnly; resolveConstOnly = true; var v = E(((ImportExpression)x).AssignExpression) as ArrayValue; resolveConstOnly = cnst; if (v == null || !v.IsString) { throw new InvalidStringException(x); } var fn = Path.IsPathRooted(v.StringValue) ? v.StringValue : Path.Combine(Path.GetDirectoryName((ctxt.ScopedBlock.NodeRoot as IAbstractSyntaxTree).FileName), v.StringValue); if (!File.Exists(fn)) { throw new EvaluationException(x, "Could not find \"" + fn + "\""); } var text = File.ReadAllText(fn); return(new ArrayValue(GetStringType(), x, text)); } else { return(strType); } }
public void Visit(ImportExpression x) { }
IExpression PrimaryExpression(IBlockNode Scope=null) { bool isModuleScoped = laKind == Dot; if (isModuleScoped) { Step(); if (IsEOF) { var dot = new TokenExpression(Dot) { Location = t.Location, EndLocation = t.EndLocation }; return new PostfixExpression_Access{ PostfixForeExpression = dot, AccessExpression = new TokenExpression(DTokens.Incomplete) }; } } // TemplateInstance if (IsTemplateInstance) { var tix = TemplateInstance(Scope); if (tix != null) tix.ModuleScopedIdentifier = isModuleScoped; return tix; } if (IsLambaExpression()) return LambaExpression(Scope); CodeLocation startLoc; switch (laKind) { // ArrayLiteral | AssocArrayLiteral case OpenSquareBracket: return ArrayLiteral(Scope); case New: return NewExpression(Scope); case Typeof: return new TypeDeclarationExpression(TypeOf()); case __traits: return TraitsExpression(); // Dollar (== Array length expression) case Dollar: Step(); return new TokenExpression(t.Kind) { Location = t.Location, EndLocation = t.EndLocation }; case Identifier: Step(); return new IdentifierExpression(t.Value) { Location = t.Location, EndLocation = t.EndLocation, ModuleScoped = isModuleScoped }; // SpecialTokens (this,super,null,true,false,$) // $ has been handled before case This: case Super: case Null: case True: case False: Step(); return new TokenExpression(t.Kind) { Location = t.Location, EndLocation = t.EndLocation }; case OpenParenthesis: if (IsFunctionLiteral()) goto case Function; // ( Expression ) Step(); var ret = new SurroundingParenthesesExpression() {Location=t.Location }; ret.Expression = Expression(); Expect(CloseParenthesis); ret.EndLocation = t.EndLocation; return ret; case Literal: Step(); startLoc = t.Location; // Concatenate multiple string literals here if (t.LiteralFormat == LiteralFormat.StringLiteral || t.LiteralFormat == LiteralFormat.VerbatimStringLiteral) { var sb = new StringBuilder(t.RawCodeRepresentation ?? t.Value); while (la.LiteralFormat == LiteralFormat.StringLiteral || la.LiteralFormat == LiteralFormat.VerbatimStringLiteral) { Step(); sb.Append(t.RawCodeRepresentation ?? t.Value); } return new IdentifierExpression(sb.ToString(), t.LiteralFormat, t.Subformat) { Location = startLoc, EndLocation = t.EndLocation }; } //else if (t.LiteralFormat == LiteralFormat.CharLiteral)return new IdentifierExpression(t.LiteralValue) { LiteralFormat=t.LiteralFormat,Location = startLoc, EndLocation = t.EndLocation }; return new IdentifierExpression(t.LiteralValue, t.LiteralFormat, t.Subformat) { Location = startLoc, EndLocation = t.EndLocation }; // FunctionLiteral case Delegate: case Function: case OpenCurlyBrace: var fl = new FunctionLiteral() { Location=la.Location}; fl.AnonymousMethod.Location = la.Location; if (laKind == Delegate || laKind == Function) { Step(); fl.LiteralToken = t.Kind; } // file.d:1248 /* listdir (".", delegate bool (DirEntry * de) { auto s = std.string.format("%s : c %s, w %s, a %s", de.name, toUTCString (de.creationTime), toUTCString (de.lastWriteTime), toUTCString (de.lastAccessTime)); return true; } ); */ if (laKind != OpenCurlyBrace) // foo( 1, {bar();} ); -> is a legal delegate { if (!IsFunctionAttribute && Lexer.CurrentPeekToken.Kind == OpenParenthesis) fl.AnonymousMethod.Type = BasicType(); else if (laKind != OpenParenthesis && laKind != OpenCurlyBrace) fl.AnonymousMethod.Type = Type(); if (laKind == OpenParenthesis) fl.AnonymousMethod.Parameters = Parameters(fl.AnonymousMethod); FunctionAttributes(fl.AnonymousMethod); } if (!IsEOF) { FunctionBody(fl.AnonymousMethod); fl.EndLocation = fl.AnonymousMethod.EndLocation; } else fl.EndLocation = la.Location; if (Scope != null) Scope.Add(fl.AnonymousMethod); return fl; // AssertExpression case Assert: Step(); startLoc = t.Location; Expect(OpenParenthesis); var ce = new AssertExpression() { Location=startLoc}; var exprs = new List<IExpression>(); exprs.Add(AssignExpression()); if (laKind == (Comma)) { Step(); exprs.Add(AssignExpression()); } ce.AssignExpressions = exprs.ToArray(); Expect(CloseParenthesis); ce.EndLocation = t.EndLocation; return ce; // MixinExpression case Mixin: Step(); var me = new MixinExpression() { Location=t.Location}; if (Expect(OpenParenthesis)) { me.AssignExpression = AssignExpression(); Expect(CloseParenthesis); } me.EndLocation = t.EndLocation; return me; // ImportExpression case Import: Step(); var ie = new ImportExpression() { Location=t.Location}; Expect(OpenParenthesis); ie.AssignExpression = AssignExpression(); Expect(CloseParenthesis); ie.EndLocation = t.EndLocation; return ie; // TypeidExpression case Typeid: Step(); var tide = new TypeidExpression() { Location=t.Location}; Expect(OpenParenthesis); if (IsAssignExpression()) tide.Expression = AssignExpression(Scope); else { Lexer.PushLookAheadBackup(); AllowWeakTypeParsing = true; tide.Type = Type(); AllowWeakTypeParsing = false; if (tide.Type == null || laKind != CloseParenthesis) { Lexer.RestoreLookAheadBackup(); tide.Expression = AssignExpression(); } else Lexer.PopLookAheadBackup(); } Expect (CloseParenthesis); tide.EndLocation = t.EndLocation; return tide; // IsExpression case Is: Step(); var ise = new IsExpression() { Location = t.Location }; Expect(OpenParenthesis); if ((ise.TestedType = Type()) == null) SynErr(laKind, "In an IsExpression, either a type or an expression is required!"); if (ise.TestedType != null) { if (laKind == Identifier && (Lexer.CurrentPeekToken.Kind == CloseParenthesis || Lexer.CurrentPeekToken.Kind == Equal || Lexer.CurrentPeekToken.Kind == Colon)) { Step(); Strings.Add(strVal); ise.TypeAliasIdentifierHash = strVal.GetHashCode(); ise.TypeAliasIdLocation = t.Location; } else if (IsEOF) ise.TypeAliasIdentifierHash = DTokens.IncompleteIdHash; } if (laKind == Colon || laKind == Equal) { Step(); ise.EqualityTest = t.Kind == Equal; } else if (laKind == CloseParenthesis) { Step(); ise.EndLocation = t.EndLocation; return ise; } /* TypeSpecialization: Type struct union class interface enum function delegate super const immutable inout shared return */ bool specialTest = false; if (ise.EqualityTest) { switch (laKind) { case Typedef: // typedef is possible although it's not yet documented in the syntax docs case Enum: case Delegate: case Function: case Super: case Return: specialTest = true; break; case Const: case Immutable: case InOut: case Shared: specialTest = Peek(1).Kind == CloseParenthesis || Lexer.CurrentPeekToken.Kind == Comma; break; default: specialTest = IsClassLike(laKind); break; } } if (specialTest) { Step(); ise.TypeSpecializationToken = t.Kind; } else ise.TypeSpecialization = Type(); // TemplateParameterList if (laKind == Comma) { var tempParam = new List<TemplateParameter>(); do { Step(); tempParam.Add(TemplateParameter(null)); } while (laKind == Comma); ise.TemplateParameterList = tempParam.ToArray(); } Expect(CloseParenthesis); ise.EndLocation = t.EndLocation; return ise; default: if (DTokens.IsMetaIdentifier(laKind)) goto case Dollar; else if (IsBasicType()) { // BasicType . Identifier startLoc = la.Location; var bt=BasicType(); if ((bt is TypeOfDeclaration || bt is MemberFunctionAttributeDecl) && laKind!=Dot) return new TypeDeclarationExpression(bt); // Things like incomplete 'float.' expressions shall be parseable, too if (Expect(Dot) && (Expect(Identifier) || IsEOF)) return new PostfixExpression_Access() { PostfixForeExpression = new TypeDeclarationExpression(bt), AccessExpression = IsEOF ? new TokenExpression(Incomplete) as IExpression : new IdentifierExpression(t.Value) { Location=t.Location, EndLocation=t.EndLocation }, EndLocation = t.EndLocation }; return null; } SynErr(Identifier); if(laKind != CloseCurlyBrace) Step(); if (IsEOF) return new TokenExpression (DTokens.Incomplete) { Location = t.Location, EndLocation = t.Location }; // Don't know why, in rare situations, t tends to be null.. if (t == null) return null; return new TokenExpression() { Location = t.Location, EndLocation = t.EndLocation }; } }
IExpression PrimaryExpression(IBlockNode Scope=null) { bool isModuleScoped = laKind == Dot; if (isModuleScoped) { Step(); if (IsEOF) { LastParsedObject = new TokenExpression(Dot) { Location = t.Location, EndLocation = t.EndLocation }; TrackerVariables.ExpectingIdentifier = true; } } // Dollar (== Array length expression) if (laKind == Dollar || DTokens.MetaIdentifiers[laKind]) { Step(); return new TokenExpression(t.Kind) { Location = t.Location, EndLocation = t.EndLocation }; } // TemplateInstance if (IsTemplateInstance) { var tix = TemplateInstance(Scope); if (tix != null) tix.ModuleScopedIdentifier = isModuleScoped; return tix; } if (IsLambaExpression()) return LambaExpression(Scope); // Identifier if (laKind == Identifier) { Step(); return new IdentifierExpression(t.Value) { Location = t.Location, EndLocation = t.EndLocation, ModuleScoped = isModuleScoped }; } // SpecialTokens (this,super,null,true,false,$) // $ has been handled before if (laKind == (This) || laKind == (Super) || laKind == (Null) || laKind == (True) || laKind == (False)) { Step(); return new TokenExpression(t.Kind) { Location = t.Location, EndLocation = t.EndLocation }; } #region Literal if (laKind == Literal) { Step(); var startLoc = t.Location; // Concatenate multiple string literals here if (t.LiteralFormat == LiteralFormat.StringLiteral || t.LiteralFormat == LiteralFormat.VerbatimStringLiteral) { var sb = new StringBuilder(t.RawCodeRepresentation ?? t.Value); while (la.LiteralFormat == LiteralFormat.StringLiteral || la.LiteralFormat == LiteralFormat.VerbatimStringLiteral) { Step(); sb.Append(t.RawCodeRepresentation ?? t.Value); } return new IdentifierExpression(sb.ToString(), t.LiteralFormat, t.Subformat) { Location = startLoc, EndLocation = t.EndLocation }; } //else if (t.LiteralFormat == LiteralFormat.CharLiteral)return new IdentifierExpression(t.LiteralValue) { LiteralFormat=t.LiteralFormat,Location = startLoc, EndLocation = t.EndLocation }; return new IdentifierExpression(t.LiteralValue, t.LiteralFormat, t.Subformat) { Location = startLoc, EndLocation = t.EndLocation }; } #endregion #region ArrayLiteral | AssocArrayLiteral if (laKind == (OpenSquareBracket)) { Step(); var startLoc = t.Location; // Empty array literal if (laKind == CloseSquareBracket) { Step(); return new ArrayLiteralExpression(null) {Location=startLoc, EndLocation = t.EndLocation }; } /* * If it's an initializer, allow NonVoidInitializers as values. * Normal AssignExpressions otherwise. */ bool isInitializer = TrackerVariables.IsParsingInitializer; var firstExpression = isInitializer? NonVoidInitializer(Scope) : AssignExpression(Scope); // Associtative array if (laKind == Colon) { Step(); var ae = isInitializer ? new ArrayInitializer { Location = startLoc } : new AssocArrayExpression { Location=startLoc }; LastParsedObject = ae; var firstValueExpression = isInitializer? NonVoidInitializer(Scope) : AssignExpression(); ae.Elements.Add(new KeyValuePair<IExpression,IExpression>(firstExpression, firstValueExpression)); while (laKind == Comma) { Step(); if (laKind == CloseSquareBracket) break; var keyExpr = AssignExpression(); var valExpr=Expect(Colon) ? (isInitializer? NonVoidInitializer(Scope) : AssignExpression(Scope)) : null; ae.Elements.Add(new KeyValuePair<IExpression,IExpression>(keyExpr,valExpr)); } Expect(CloseSquareBracket); ae.EndLocation = t.EndLocation; return ae; } else // Normal array literal { var ae = new List<IExpression>(); LastParsedObject = ae; ae.Add(firstExpression); while (laKind == Comma) { Step(); if (laKind == CloseSquareBracket) // And again, empty expressions are allowed break; ae.Add(isInitializer? NonVoidInitializer(Scope) : AssignExpression(Scope)); } Expect(CloseSquareBracket); return new ArrayLiteralExpression(ae){ Location=startLoc, EndLocation = t.EndLocation }; } } #endregion #region FunctionLiteral if (laKind == Delegate || laKind == Function || laKind == OpenCurlyBrace || (laKind == OpenParenthesis && IsFunctionLiteral())) { var fl = new FunctionLiteral() { Location=la.Location}; LastParsedObject = fl; fl.AnonymousMethod.Location = la.Location; if (laKind == Delegate || laKind == Function) { Step(); fl.LiteralToken = t.Kind; } // file.d:1248 /* listdir (".", delegate bool (DirEntry * de) { auto s = std.string.format("%s : c %s, w %s, a %s", de.name, toUTCString (de.creationTime), toUTCString (de.lastWriteTime), toUTCString (de.lastAccessTime)); return true; } ); */ if (laKind != OpenCurlyBrace) // foo( 1, {bar();} ); -> is a legal delegate { if (!IsFunctionAttribute && Lexer.CurrentPeekToken.Kind == OpenParenthesis) fl.AnonymousMethod.Type = BasicType(); else if (laKind != OpenParenthesis && laKind != OpenCurlyBrace) fl.AnonymousMethod.Type = Type(); if (laKind == OpenParenthesis) fl.AnonymousMethod.Parameters = Parameters(fl.AnonymousMethod); FunctionAttributes(fl.AnonymousMethod); } if(!IsEOF) FunctionBody(fl.AnonymousMethod); fl.EndLocation = t.EndLocation; if (Scope != null) Scope.Add(fl.AnonymousMethod); return fl; } #endregion #region AssertExpression if (laKind == (Assert)) { Step(); var startLoc = t.Location; Expect(OpenParenthesis); var ce = new AssertExpression() { Location=startLoc}; LastParsedObject = ce; var exprs = new List<IExpression>(); exprs.Add(AssignExpression()); if (laKind == (Comma)) { Step(); exprs.Add(AssignExpression()); } ce.AssignExpressions = exprs.ToArray(); Expect(CloseParenthesis); ce.EndLocation = t.EndLocation; return ce; } #endregion #region MixinExpression | ImportExpression if (laKind == Mixin) { Step(); var e = new MixinExpression() { Location=t.Location}; LastParsedObject = e; if (Expect(OpenParenthesis)) { e.AssignExpression = AssignExpression(); Expect(CloseParenthesis); } e.EndLocation = t.EndLocation; return e; } if (laKind == Import) { Step(); var e = new ImportExpression() { Location=t.Location}; LastParsedObject = e; Expect(OpenParenthesis); e.AssignExpression = AssignExpression(); Expect(CloseParenthesis); e.EndLocation = t.EndLocation; return e; } #endregion if (laKind == (Typeof)) { return new TypeDeclarationExpression(TypeOf()); } // TypeidExpression if (laKind == (Typeid)) { Step(); var ce = new TypeidExpression() { Location=t.Location}; LastParsedObject = ce; Expect(OpenParenthesis); if (IsAssignExpression()) ce.Expression = AssignExpression(Scope); else { Lexer.PushLookAheadBackup(); AllowWeakTypeParsing = true; ce.Type = Type(); AllowWeakTypeParsing = false; if (ce.Type == null || laKind != CloseParenthesis) { Lexer.RestoreLookAheadBackup(); ce.Expression = AssignExpression(); } else Lexer.PopLookAheadBackup(); } if (!Expect(CloseParenthesis) && IsEOF) LastParsedObject = (ISyntaxRegion)ce.Type ?? ce.Expression; ce.EndLocation = t.EndLocation; return ce; } #region IsExpression if (laKind == Is) { Step(); var ce = new IsExpression() { Location=t.Location}; LastParsedObject = ce; Expect(OpenParenthesis); if((ce.TestedType = Type())==null) SynErr(laKind, "In an IsExpression, either a type or an expression is required!"); if (ce.TestedType!=null && laKind == Identifier && (Lexer.CurrentPeekToken.Kind == CloseParenthesis || Lexer.CurrentPeekToken.Kind == Equal || Lexer.CurrentPeekToken.Kind == Colon)) { Step(); Strings.Add(strVal); ce.TypeAliasIdentifierHash = strVal.GetHashCode(); ce.TypeAliasIdLocation = t.Location; } if (laKind == CloseParenthesis) { Step(); ce.EndLocation = t.EndLocation; return ce; } if (laKind == Colon || laKind == Equal) { Step(); ce.EqualityTest = t.Kind == Equal; } else if (laKind == CloseParenthesis) { Step(); ce.EndLocation = t.EndLocation; return ce; } /* TypeSpecialization: Type struct union class interface enum function delegate super const immutable inout shared return */ if (ce.EqualityTest && (ClassLike[laKind] || laKind==Typedef || // typedef is possible although it's not yet documented in the syntax docs laKind==Enum || laKind==Delegate || laKind==Function || laKind==Super || laKind==Return || ((laKind==Const || laKind == Immutable || laKind == InOut || laKind == Shared) && (Peek(1).Kind==CloseParenthesis || Lexer.CurrentPeekToken.Kind==Comma)))) { Step(); ce.TypeSpecializationToken = t.Kind; } else ce.TypeSpecialization = Type(); // TemplateParameterList if (laKind == Comma) { var ret = new List<TemplateParameter>(); do { Step(); ret.Add(TemplateParameter(null)); } while (laKind == Comma); ce.TemplateParameterList = ret.ToArray(); } Expect(CloseParenthesis); ce.EndLocation = t.EndLocation; return ce; } #endregion // NewExpression if (laKind == (New)) return NewExpression(Scope); // ( Expression ) if (laKind == OpenParenthesis) { Step(); var ret = new SurroundingParenthesesExpression() {Location=t.Location }; LastParsedObject = ret; ret.Expression = Expression(); Expect(CloseParenthesis); ret.EndLocation = t.EndLocation; return ret; } // TraitsExpression if (laKind == (__traits)) return TraitsExpression(); #region BasicType . Identifier if (IsBasicType()) { var startLoc = la.Location; var bt=BasicType(); if ((bt is TypeOfDeclaration || bt is MemberFunctionAttributeDecl) && laKind!=Dot) return new TypeDeclarationExpression(bt); // Things like incomplete 'float.' expressions shall be parseable, too if (Expect(Dot) && (Expect(Identifier) || IsEOF)) return new PostfixExpression_Access() { PostfixForeExpression = new TypeDeclarationExpression(bt), AccessExpression = string.IsNullOrEmpty(t.Value) ? null : new IdentifierExpression(t.Value) { Location=t.Location, EndLocation=t.EndLocation }, EndLocation = t.EndLocation }; return null; } #endregion SynErr(Identifier); if(laKind != CloseCurlyBrace) Step(); // Don't know why, in rare situations, t tends to be null.. if (t == null) return null; return new TokenExpression() { Location = t.Location, EndLocation = t.EndLocation }; }
public ISymbolValue Visit(ImportExpression x) { var cnst = resolveConstOnly; resolveConstOnly = true; var v = x.AssignExpression != null ? x.AssignExpression.Accept(this) as ArrayValue : null; resolveConstOnly = cnst; if (v == null || !v.IsString){ EvalError( new InvalidStringException(x)); return null; } var fn = Path.IsPathRooted(v.StringValue) ? v.StringValue : Path.Combine(Path.GetDirectoryName((ctxt.ScopedBlock.NodeRoot as DModule).FileName), v.StringValue); if (!File.Exists(fn)){ EvalError(x, "Could not find \"" + fn + "\""); return null; } var text = File.ReadAllText(fn); return new ArrayValue(GetStringType(), text); }
IExpression PrimaryExpression(IBlockNode Scope=null) { bool isModuleScoped = false; // For minimizing possible overhead, skip 'useless' tokens like an initial dot <<< TODO if (isModuleScoped= laKind == Dot) Step(); if (laKind == __FILE__ || laKind == __LINE__) { Step(); object id = null; if (t.Kind == __FILE__ && doc != null) id = doc.FileName; else if(t.Kind==__LINE__) id = t.line; return new IdentifierExpression(id) { Location=t.Location, EndLocation=t.EndLocation }; } // Dollar (== Array length expression) if (laKind == Dollar) { Step(); return new TokenExpression(laKind) { Location = t.Location, EndLocation = t.EndLocation }; } // TemplateInstance if (laKind == (Identifier) && Lexer.CurrentPeekToken.Kind == (Not) && (Peek().Kind != Is && Lexer.CurrentPeekToken.Kind != In) /* Very important: The 'template' could be a '!is'/'!in' expression - With two tokens each! */) return TemplateInstance(); // Identifier if (laKind == (Identifier)) { Step(); return new IdentifierExpression(t.Value) { Location = t.Location, EndLocation = t.EndLocation }; } // SpecialTokens (this,super,null,true,false,$) // $ has been handled before if (laKind == (This) || laKind == (Super) || laKind == (Null) || laKind == (True) || laKind == (False)) { Step(); return new TokenExpression(t.Kind) { Location = t.Location, EndLocation = t.EndLocation }; } #region Literal if (laKind == Literal) { Step(); var startLoc = t.Location; // Concatenate multiple string literals here if (t.LiteralFormat == LiteralFormat.StringLiteral || t.LiteralFormat == LiteralFormat.VerbatimStringLiteral) { var a = t.LiteralValue as string; while (la.LiteralFormat == LiteralFormat.StringLiteral || la.LiteralFormat == LiteralFormat.VerbatimStringLiteral) { Step(); a += t.LiteralValue as string; } return new IdentifierExpression(a, t.LiteralFormat) { Location = startLoc, EndLocation = t.EndLocation }; } //else if (t.LiteralFormat == LiteralFormat.CharLiteral)return new IdentifierExpression(t.LiteralValue) { LiteralFormat=t.LiteralFormat,Location = startLoc, EndLocation = t.EndLocation }; return new IdentifierExpression(t.LiteralValue, t.LiteralFormat) { Location = startLoc, EndLocation = t.EndLocation }; } #endregion #region ArrayLiteral | AssocArrayLiteral if (laKind == (OpenSquareBracket)) { Step(); var startLoc = t.Location; // Empty array literal if (laKind == CloseSquareBracket) { Step(); return new ArrayLiteralExpression() {Location=startLoc, EndLocation = t.EndLocation }; } var firstExpression = AssignExpression(); // Associtative array if (laKind == Colon) { Step(); var ae = new AssocArrayExpression() { Location=startLoc}; LastParsedObject = ae; var firstValueExpression = AssignExpression(); ae.KeyValuePairs.Add(firstExpression, firstValueExpression); while (laKind == Comma) { Step(); var keyExpr = AssignExpression(); Expect(Colon); var valueExpr = AssignExpression(); ae.KeyValuePairs.Add(keyExpr, valueExpr); } Expect(CloseSquareBracket); ae.EndLocation = t.EndLocation; return ae; } else // Normal array literal { var ae = new ArrayLiteralExpression() { Location=startLoc}; LastParsedObject = ae; var expressions = new List<IExpression>(); expressions.Add(firstExpression); while (laKind == Comma) { Step(); if (laKind == CloseSquareBracket) // And again, empty expressions are allowed break; expressions.Add(AssignExpression()); } ae.Expressions = expressions; Expect(CloseSquareBracket); ae.EndLocation = t.EndLocation; return ae; } } #endregion #region FunctionLiteral if (laKind == Delegate || laKind == Function || laKind == OpenCurlyBrace || (laKind == OpenParenthesis && IsFunctionLiteral())) { var fl = new FunctionLiteral() { Location=la.Location}; LastParsedObject = fl; fl.AnonymousMethod.StartLocation = la.Location; if (laKind == Delegate || laKind == Function) { Step(); fl.LiteralToken = t.Kind; } // file.d:1248 /* listdir (".", delegate bool (DirEntry * de) { auto s = std.string.format("%s : c %s, w %s, a %s", de.name, toUTCString (de.creationTime), toUTCString (de.lastWriteTime), toUTCString (de.lastAccessTime)); return true; } ); */ if (laKind != OpenCurlyBrace) // foo( 1, {bar();} ); -> is a legal delegate { if (!MemberFunctionAttribute[laKind] && Lexer.CurrentPeekToken.Kind == OpenParenthesis) fl.AnonymousMethod.Type = BasicType(); else if (laKind != OpenParenthesis && laKind != OpenCurlyBrace) fl.AnonymousMethod.Type = Type(); if (laKind == OpenParenthesis) fl.AnonymousMethod.Parameters = Parameters(fl.AnonymousMethod); } FunctionBody(fl.AnonymousMethod); fl.EndLocation = t.EndLocation; if (Scope != null) Scope.Add(fl.AnonymousMethod); return fl; } #endregion #region AssertExpression if (laKind == (Assert)) { Step(); var startLoc = t.Location; Expect(OpenParenthesis); var ce = new AssertExpression() { Location=startLoc}; LastParsedObject = ce; var exprs = new List<IExpression>(); exprs.Add(AssignExpression()); if (laKind == (Comma)) { Step(); exprs.Add(AssignExpression()); } ce.AssignExpressions = exprs.ToArray(); Expect(CloseParenthesis); ce.EndLocation = t.EndLocation; return ce; } #endregion #region MixinExpression | ImportExpression if (laKind == Mixin) { Step(); var e = new MixinExpression() { Location=t.Location}; LastParsedObject = e; Expect(OpenParenthesis); e.AssignExpression = AssignExpression(); Expect(CloseParenthesis); e.EndLocation = t.EndLocation; return e; } if (laKind == Import) { Step(); var e = new ImportExpression() { Location=t.Location}; LastParsedObject = e; Expect(OpenParenthesis); e.AssignExpression = AssignExpression(); Expect(CloseParenthesis); e.EndLocation = t.EndLocation; return e; } #endregion if (laKind == (Typeof)) { var startLoc = la.Location; return new TypeDeclarationExpression(TypeOf()) {Location=startLoc,EndLocation=t.EndLocation}; } // TypeidExpression if (laKind == (Typeid)) { Step(); var ce = new TypeidExpression() { Location=t.Location}; LastParsedObject = ce; Expect(OpenParenthesis); AllowWeakTypeParsing = true; ce.Type = Type(); AllowWeakTypeParsing = false; if (ce.Type==null) ce.Expression = AssignExpression(); Expect(CloseParenthesis); ce.EndLocation = t.EndLocation; return ce; } #region IsExpression if (laKind == Is) { Step(); var ce = new IsExpression() { Location=t.Location}; LastParsedObject = ce; Expect(OpenParenthesis); var LookAheadBackup = la; AllowWeakTypeParsing = true; ce.TestedType = Type(); AllowWeakTypeParsing = false; if (ce.TestedType!=null && laKind == Identifier && (Lexer.CurrentPeekToken.Kind == CloseParenthesis || Lexer.CurrentPeekToken.Kind == Equal || Lexer.CurrentPeekToken.Kind == Colon)) { Step(); ce.TypeAliasIdentifier = strVal; } else // D Language specs mistake: In an IsExpression there also can be expressions! if(ce.TestedType==null || !(laKind==CloseParenthesis || laKind==Equal||laKind==Colon)) { // Reset lookahead token to prior position la = LookAheadBackup; // Reset wrongly parsed type declaration ce.TestedType = null; ce.TestedExpression = ConditionalExpression(); } if(ce.TestedExpression==null && ce.TestedType==null) SynErr(laKind,"In an IsExpression, either a type or an expression is required!"); if (laKind == CloseParenthesis) { Step(); ce.EndLocation = t.EndLocation; return ce; } if (laKind == Colon || laKind == Equal) { Step(); ce.EqualityTest = t.Kind == Equal; } else if (laKind == CloseParenthesis) { Step(); ce.EndLocation = t.EndLocation; return ce; } /* TypeSpecialization: Type struct union class interface enum function delegate super const immutable inout shared return */ if (ClassLike[laKind] || laKind==Typedef || // typedef is possible although it's not yet documented in the syntax docs laKind==Enum || laKind==Delegate || laKind==Function || laKind==Super || laKind==Return) { Step(); ce.TypeSpecializationToken = t.Kind; } else ce.TypeSpecialization = Type(); if (laKind == Comma) { Step(); ce.TemplateParameterList = TemplateParameterList(false); } Expect(CloseParenthesis); ce.EndLocation = t.EndLocation; return ce; } #endregion // ( Expression ) if (laKind == OpenParenthesis) { Step(); var ret = new SurroundingParenthesesExpression() {Location=t.Location }; LastParsedObject = ret; ret.Expression = Expression(); Expect(CloseParenthesis); ret.EndLocation = t.EndLocation; return ret; } // TraitsExpression if (laKind == (__traits)) return TraitsExpression(); #region BasicType . Identifier if (laKind == (Const) || laKind == (Immutable) || laKind == (Shared) || laKind == (InOut) || BasicTypes[laKind]) { Step(); var startLoc = t.Location; IExpression left = null; if (!BasicTypes[t.Kind]) { int tk = t.Kind; // Put an artificial parenthesis around the following type declaration if (laKind != OpenParenthesis) { var mttd = new MemberFunctionAttributeDecl(tk); LastParsedObject = mttd; mttd.InnerType = Type(); left = new TypeDeclarationExpression(mttd) { Location = startLoc, EndLocation = t.EndLocation }; } else { Expect(OpenParenthesis); var mttd = new MemberFunctionAttributeDecl(tk); LastParsedObject = mttd; mttd.InnerType = Type(); Expect(CloseParenthesis); left = new TypeDeclarationExpression(mttd) { Location = startLoc, EndLocation = t.EndLocation }; } } else left = new TokenExpression(t.Kind) {Location=startLoc,EndLocation=t.EndLocation }; if (laKind == (Dot) && Peek(1).Kind==Identifier) { Step(); Step(); var meaex = new PostfixExpression_Access() { PostfixForeExpression=left, TemplateOrIdentifier=new IdentifierDeclaration(t.Value),EndLocation=t.EndLocation }; return meaex; } return left; } #endregion // TODO? Expressions can of course be empty... //return null; SynErr(Identifier); Step(); return new TokenExpression(t.Kind) { Location = t.Location, EndLocation = t.EndLocation }; }
public static ParsedCode Parse(string code, Dictionary <string, object> variables = null, InterpreterOptions opts = null) { code = code.Replace("\r", ""); //todo this might cause throws in osx. StringSpan output_sb; var output = new LineBuilder(output_sb = StringSpan.Create(code)); variables = variables ?? new Dictionary <string, object>(); opts = opts ?? new InterpreterOptions(); // Define the context of our expression var ew = new ExpressionWalker(ExpressionLexer.Tokenize(code).Where(t => t.Token != ExpressionToken.UnixNewLine).ToList()); //if no tokens detected if (ew.Count == 0) { return(new ParsedCode() { OriginalCode = code, Output = output, Variables = variables, Options = opts, ParseActions = new OList <ParserAction>(0) }); } var parserTokens = new OList <ParserAction>(); do { var current = ew.Current; switch (ew.Current.Token) { case ExpressionToken.Mod: { //copypastes.Add(sb.Substring(from, ew.Current.Match.Index + ew.Current.Match.Length - 1)); current = ew.NextToken(); if (current == null) { break; } switch (current.Token) { case ExpressionToken.Template: { //this is import %import namespace.type as aliasnmae var template = TemplateExpression.Parse(ew); parserTokens += new ParserAction(ParserToken.Template, output.MarkDeleteLinesRelated(template.Matches()), template); break; } case ExpressionToken.Import: { //this is import %import namespace.type as aliasnmae var import = ImportExpression.Parse(ew); parserTokens += new ParserAction(ParserToken.Import, output.MarkDeleteLinesRelated(import.Matches()), import); break; } case ExpressionToken.Literal: { //this is variable declaration %varname = expr var peak = ew.PeakNext.Token; if (peak == ExpressionToken.Equal) { var expr = VariableDeclarationExpression.Parse(ew); parserTokens += new ParserAction(ParserToken.Declaration, output.MarkDeleteLinesRelated(expr.Matches()), expr); } else { break; } break; } case ExpressionToken.LeftParen: { //it is an expression block %(expr) ew.NextOrThrow(); var expr = Expression.ParseExpression(ew); parserTokens += new ParserAction(ParserToken.Expression, output.MarkDeleteLinesRelated(expr.Matches()), expr); ew.IsCurrentOrThrow(ExpressionToken.RightParen); ew.Next(); break; } case ExpressionToken.Foreach: { parserTokens += ForeachExpression.Parse(ew, code, output); break; } case ExpressionToken.CommentRow: //skip untill we hit newline ew.SkipForwardWhile(t => t.Token != ExpressionToken.NewLine); //todo test break; default: { var precentageLine = output.GetLineAt(ew.PeakBack.Match.Index); if (precentageLine.CleanContent() != "%") { throw new UnexpectedTokenException(current.Token, $"The given token was not expected at line {precentageLine.LineNumber}, offset: {current.Match.Index - precentageLine.StartIndex}"); } break; } } break; } default: break; } } while (ew.Next()); return(new ParsedCode() { OriginalCode = code, Output = output, Variables = variables, ETokens = (List <TokenMatch>)ew.Walking, ParseActions = parserTokens, Options = opts }); }
ISemantic E(ImportExpression x) { var strType = GetStringType(); if (eval) { var cnst = resolveConstOnly; resolveConstOnly = true; var v = E(((ImportExpression)x).AssignExpression) as ArrayValue; resolveConstOnly = cnst; if (v == null || !v.IsString){ EvalError( new InvalidStringException(x)); return null; } var fn = Path.IsPathRooted(v.StringValue) ? v.StringValue : Path.Combine(Path.GetDirectoryName((ctxt.ScopedBlock.NodeRoot as DModule).FileName), v.StringValue); if (!File.Exists(fn)){ EvalError(x, "Could not find \"" + fn + "\""); return null; } var text = File.ReadAllText(fn); return new ArrayValue(GetStringType(), text); } else return strType; }