Scripti - Eine kleine Skriptsprache für simple Aufgaben

    • Beta
    • Open Source

    Es gibt 43 Antworten in diesem Thema. Der letzte Beitrag () ist von masterm.

      Scripti - Eine kleine Skriptsprache für simple Aufgaben

      Scripti

      Scripti ist ein Interpreter von Skriptdateien. Der Syntax ist relativ simpel: (Gruppe.)Befehl:(Argument)(;Argument)(...)
      Es gibt verschiedene Gruppen, in welchen Befehle gesammelt sind. Für einige Befehle müssen Argumente angegeben werden. Diese werden durch einen Doppelpunkt ":" vom Befehl getrennt (der Doppelpunkt muss immer vorhanden sein). Die Argumente untereinander werden durch Semikolons ";" getrennt.
      Beispiel ist folgender Befehl: io.movedirectory. Dies ist der Syntax: file.movedirectory:alterordner;neuerorder;überschreiben. Das Argument alterordner gibt den zu verschiebenen Ordner an, neuerorder ist das Zielverzeichnis und überschreiben legt fest, ob der Zielordner überschrieben werden soll, wenn er bereits existiert. Das letzte Argument kann bei diesem Befehl weggelassen werden. Gegebenenfalls fragt der Interpreter nach.

      Unter github.com/master-m1000/Scripti/ findet ihr den Quelltext.

      Ich suche fleißige Tester! Wir sind noch laaaange nicht am Ziel, sondern haben gerade erst 7 Zentimeter von 1000 Kilometer zurückgelegt. Ich bin auf euer Feedback angewiesen und freue mich auf die Zusammenarbeit.

      Infos:
      Größe des Interpreters: ca. 192 KB
      Entwickelt mit Visual Studio 2015 in Visual Basic Community (Framework Version 4.0)

      Aktuelle Version: 0.1.1.0
      Zur Versionsübersicht

      Download: als Setup oder als Zip
      Lizenz (MIT License)

      Screenshots:

      Hier mal ein Beispiel von einem Script:
      Spoiler anzeigen

      Quellcode

      1. |SCRIPTI SCRIPT FILE VERSION 0.1.0.0
      2. ' <- This at the beginning of a line marks a comment
      3. me.write:This is a test!
      4. me.write:
      5. me.write:Now we're going to change the color...
      6. me.color:3;11
      7. me.pause:
      8. me.write:And back!
      9. me.resetcolor:
      10. me.write:Tada!
      11. me.pause:
      Alle Angaben sind ohne Gewähr, jedoch mit Pistole. Glücksspiel, Drogen und leckeres Essen können süchtig machen.

      43232069737420636f6f6c21

      Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von „masterm“ ()

      Wie wäre es, wenn du erstmal die wichtigsten Sachen wie Userinputs, Variablen, ... implementierst? Außerdem wäre praktisch, einen Befehl zu haben, welcher es erlaubt, Cmd-Befehle zu senden. So wie sie jetzt ist, ist diese "Skriptsprache" so gut wie nutzlos.
      Warum hast du bei den Befehlen Deutsch und Englisch gemischt?

      Quellcode

      1. file.deletefile
      2. kommentar
      3. show
      4. startprogramm


      Das irritiert! Die Idee ist aber nicht schlecht und die Syntax recht einfach zu verstehen. Wenn du jetzt noch mehr Befehle und die Funktion, dass eine Skriptdatei auch per Doppelklick ausgeführt werden kann hinzufügst, wäre dein Projekt echt nützlich!

      Edit: Eine Frage habe Ich aber noch: Muss der ganze Skript in einer Zeile geschrieben sein? Hab gerade dein Wiki gefunden, liegt wohl an der Kodierung deiner Beispieldatei.
      @ichduersie Das zweite m in "startprogramm" ist mir auch schon aufgefallen und entfernt. Ein Kommentar wird mit einem Apostroph am Zeilenanfang angegeben. Ich habe ein Setup geschrieben, mit dem es per Doppelklick gestartet wird, aber die Deinstallation buggt noch, weswegen ich diese keinem antun wollte ;)

      @nafets Eine cmd-Implementierung - oder wie man es auch immer nennen möge - ist eine gute Idee. Ich habe aber keine Ahnung, wie ich diese umsetzten könnte. Variablen sind nur beschränkt vorhanden (10 Strings). Ich weiß leider nicht, wie ich dies dynamisch umsetzten soll.

      Wir befinden uns noch in der Alpha. Wir haben erst zwei Zentimeter von tausend Kilometern (ums mal etwas poetischer zu sagen ;) )
      Alle Angaben sind ohne Gewähr, jedoch mit Pistole. Glücksspiel, Drogen und leckeres Essen können süchtig machen.

      43232069737420636f6f6c21

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „masterm“ ()

      So, die 0.0.3.0 ist da mit ein paar Änderungen. Das Wiki wurde jetzt komplett auf die neuen Befehle aktualisiert und ist nun vollständig. Das zweite "m" bei startprogramm wurde entfernt und ein neuer Befehl hinzugefügt. Mehr Infos im Changelog. Dort findet ihr auch den Download-Link. Falls ein Problem auftritt oder ihr Vorschläge habt, könnt ihr mich gerne hier im Forum kontaktieren.
      Alle Angaben sind ohne Gewähr, jedoch mit Pistole. Glücksspiel, Drogen und leckeres Essen können süchtig machen.

      43232069737420636f6f6c21

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „masterm“ ()

      Hey @masterm
      Ich habe mir mal die Zeit genommen deinen Interpreter zu testen. Mir sind ein paar Dinge aufgefallen. Zuerst einmal habe ich es installiert und habe sogleich begonnen ein Script zu erstellen, wobei ich erstmal suchen musste was ich für einen Typ nehmen muss(habe ich dann aus deinen Screenshots entnommen).
      Positiv ist schonmal, dass die Scripts gleich auf dein Programm zugreifen wenn man sie doppelklickt. Ich habe dann mal die ersten Zeilen geschrieben und musste feststellen, dass der Interpreter einen Fehler auswarf.
      Ich habe dann bemerkt, dass ich vergessen habe an den Anfang zu setzen "|SCRIPTI SCRIPT FILE VERSION 0.0.3.0". Soweit so gut. Ich habe etwas herum experimentiert und kann nun sagen, dass die Syntax gut zu verstehen ist. Ich habe CopyDirectory ausprobiert, aber es wirft mir da einen Fehler aus, aus dem ich nicht die Ursache schließen kann. Vielleicht hängt es mit den : zusammen oder ich mache da einfach einen groben Fehler.

      Vielleicht könntest du ja ein kleines Tutorial erstellen, wie man solche Dateien richtig schreibt?
      Auch ist mir die Namensnennung etwas Suspekt aufgefallen: Es ist mMn etwas seltsam, dass du mit "File." Dateien und Ordner behandelst. Vielleicht benennst du es ja in sowas um wie "IO."? Auch könnte man "startprogram" mit sowas wie "Tasks." oder "Program." zusammenfassen und dann noch diverse Befehle wie beenden von Programmen hinzufügen.

      Aber soviel sei gesagt: Dein Projekt hat wirklich potenzial. Mit einer/mehreren Personen zusätzlich an Bord könnte man dein Projekt wirklich ausbauen und man könnte es für viele Dinge benutzen. Die Arbeit bis zu dieser Version ist schon ganz ordentlich(vom äußeren her, den Code kann ich ja nicht beurteilen ^^ ). Wenn noch Dinge wie Variablen, If-Clauses, Select-Cases und so ein Zeug hinzugefügt wird, dann kann man es wirklich für gute Dinge benutzen. Naja soviel von mir. Mach weiter so!

      LG

      P.S.
      Übrigens hatte ich mal sowas ähnliches, ein Shell-Programm, das konnte Variablen. Ich habe es dort einfach mit einer Klasse gelöst in der ich eine List(of String) hatte inder ich dann die Variablen geschrieben habe bspw. "int;hallo|5". Mit einer Funktion zum Suchen habe ich dann die Variablen herausgeholt und mit anderen Methoden habe ich welche hinzugefügt, gelöscht und umbenannt. Vielleicht ist das ein erster Ansatz für dich? LG
      Danke für deine Rückmeldung. Ich sollte wirklich mal eine Anleitung schreiben. Den Bereich File umzubenennen ist keine schlechte Idee. Es ist wirklich leicht irritierend. Danke für den Tipp mit den Variablen!
      Alle Angaben sind ohne Gewähr, jedoch mit Pistole. Glücksspiel, Drogen und leckeres Essen können süchtig machen.

      43232069737420636f6f6c21
      Naja - so toll ist der Ansatz nun auch wieder nicht. Anstatt Strings solltest du anständige Datentypen verwenden.
      Aber erstmal solltest du überlegen, welche Datentypen du haben willst - ich würde Boolean, String & Number empfehlen (also Ja/Nein, Zeichenfolge und Zahl). Damit lässt sich das meiste abdecken. Dann musst du überlegen, welche "Namen" Variablen haben können (z.B. B1-B999 für Booleans usw. oder ganz normale Namen, ...). Dann gibt es einen ganz einfachen Ansatz: du erstellst ein Dictionary(Of String, Variable), wo der String den Namen beschreibt und die Klasse Variable den Wert und den Typ des Wertes abspeichern. Zuletzt musst bei jedem Zugriff auf die Variable prüfen, ob sie deklariert ist und schauen, ob der Typ mit dem abgefragten/zugewiesenen Typ übereinstimmt. Dann hast du ein verhältnismäßig einfaches System für Variablen.



      (Sorry für den Doppelpost, will aber unbedingt noch was los werden)
      Hab mir mal den Source angeschaut - hoffe du hast nix dagegen. So wie dein "Interpreter" momentan aufgebaut ist (Hardgecodete Abfrage für jede Funktion) wird das nix. Der Aufbau sollte eher so sein:
      -Tokenizer zerlegt Datei in Tokens (Werte, Funktionsaufrufe, ...)
      -Du suchst die Funktionsaufrufe raus und holst aus einer zentralen Klasse die zugehörigen Funktionen raus
      -Ausführung des Codes

      Doppelpost zusammengefügt. Für nachträgliche Ergänzungen gibt es die 'Bearbeiten'-Funktion! ~Thunderbolt

      Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „nafets“ ()

      Hi,
      ich würde dir empfehlen, das Programm sofort auf Github (o. ä.) hochzuladen, denn wenn du mit dem Aufbau der Sprache falsch anfängst, kannst du zum Schluss alles übern Haufen werfen. Vielleicht wäre eine kleine IDE ganz gut, denn so simpel, wie die Sprache ist, wird das bestimmt nicht viel Arbeit in Anspruch nehmen. (Quasi den Windows Editor kopieren, gescheites Syntaxhighlighting einbauen und vielleicht noch eine Autovervollständigung, und natürlich den automatischen Header nicht vergessen. Sonst könnte man sogar eine Fehlerbehandlung (Syntaxfehler) einbauen, obwohl das wohl etwas länger dauern würde)
      Mfg
      Vincent

      Man braucht mMn dafür keine extra gecodete IDE. Es geht dabei ja hauptsächlich um die Übersichtlichkeit des Codes. Meines Wissens nach, kann man bspw. in Notepad++ die eigene Syntax reinschreiben und die entsprechende Datei exportieren. So etwas dauert vielleicht ein oder zwei Stunden zu schreiben und man muss nicht noch ein Programm schreiben. So etwas reicht doch erstmal zumal der Umfang noch relativ gering ist.

      LG
      @ChOoSeMyNaMe
      Sehe ich ehrlich gesagt genau anders rum: Wenn diese Sprache eine ordentlich IDE hätte, die man leicht bedienen kann, mit Syntaxhightlighting und einer IntelliSense, dann würde ich mir das eher angucken. Mir wäre der Aufwand zu groß, mir jetzt anzugucken, wie das geht, was man beachten muss, was nicht geht und wo die Fehler sind. Gäbe es aber eine IDE, die mir den Header generiert und sagt, wenn irgendwo ein Syntaxfehler ist, dann wäre es wesentlich unkomplizierter. Abgesehen davon soll diese Sprache doch Leute ansprechen, die, sorry, keine Ahnung haben und einfach nur ein schnelles Script schreiben wollen, um irgendeine Aufgabe zu erledigen. Um schnell etwas zu erledigen gibt es mehrer Faktoren: Die Sprache muss einfach gestaltet sein, sodass man nicht dauernd in irgendeiner Dokumentation nachgucken muss, sondern sich das schon denken kann, und möglichst kurz gehalten, sodass man für das einfache kopieren keine hundert Zeile Code braucht. Das wurde ja schon ganz gut erfüllt. Jetzt will ich aber auch schnell starten können. Dafür müsste ich momentan den Header auswendig lernen oder ihn jedes mal kopieren -> mit VB.Net würde es schneller gehen -> der Sinn wurde nicht ganz erfüllt. Außerdem werden Fehler erst erkannt, wenn ich das ganze ausführe und eine Autovervollständigung, die den Punkt "einfach zu merken" noch schneller macht, gibt es auch nicht.
      Mfg
      Vincent

      Da hier so ein Interesse herrscht, werde ich es wahrscheinlich Open Source machen. Ich kenne mich zwar mit Github kaum aus, aber dass krieg ich schon irgendwie hin. Leider werde ich erst nächstes Wochenende dazu kommen. Bis dahin bin ich schlecht erreichbar.

      Danke für eure Unterstützung!
      Alle Angaben sind ohne Gewähr, jedoch mit Pistole. Glücksspiel, Drogen und leckeres Essen können süchtig machen.

      43232069737420636f6f6c21
      Mal sehen. Ich bin jetzt bis Freitagnachmittag im Internat und kann nicht an meinen PC. Bis dahin komme ich an meine Projektdaten nicht ran.
      @ErfinderDesRades noch nicht, aber wir sind ja erst am Anfang.
      Alle Angaben sind ohne Gewähr, jedoch mit Pistole. Glücksspiel, Drogen und leckeres Essen können süchtig machen.

      43232069737420636f6f6c21

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „masterm“ ()

      Ich hab mal die aktuellste Version des Tokenizers, den ich bei meinen Projekten verwende:
      C#

      C#-Quellcode

      1. using System;
      2. using System.Collections.Generic;
      3. using System.IO;
      4. using System.Linq;
      5. using System.Text;
      6. using System.Threading.Tasks;
      7. namespace SimpleScript.Tokenizer
      8. {
      9. public class Tokenizer
      10. {
      11. public Tokenizer(string code)
      12. {
      13. this.IgnoreWhitespace = false;
      14. this.SymbolCharacters = "=+-/,.*~!@#$%^&(){}[]:;<>?|\\".ToList();
      15. this.DecimalSeperator = '.';
      16. this.currentLine = 1;
      17. this.currentColumn = 1;
      18. this.currentPosTotal = 0;
      19. this.inputCode = code;
      20. }
      21. private const char EndOfFile = (char)0;
      22. protected string inputCode { get; private set; }
      23. protected int tokenStartLine { get; set; }
      24. protected int tokenStartColumn { get; set; }
      25. protected int tokenStartPosTotal { get; set; }
      26. protected int currentLine { get; set; }
      27. protected int currentColumn { get; set; }
      28. protected int currentPosTotal { get; set; }
      29. public bool IgnoreWhitespace { get; set; }
      30. public List<char> SymbolCharacters { get; set; }
      31. public char DecimalSeperator { get; set; }
      32. public bool TryGetToken(out Token token)
      33. {
      34. char cCurrent = this.LookAhead();
      35. switch (cCurrent)
      36. {
      37. case EndOfFile:
      38. this.StartToken();
      39. token = this.CreateToken(TokenType.EndOfFile);
      40. return false;
      41. case ' ':
      42. case '\t':
      43. if (this.IgnoreWhitespace)
      44. {
      45. this.MoveForward();
      46. return this.TryGetToken(out token);
      47. }
      48. token = this.ReadWhitespace();
      49. break;
      50. case '\r':
      51. case '\n':
      52. token = this.ReadNewLine();
      53. break;
      54. case '"':
      55. token = this.ReadQuotedString();
      56. break;
      57. default:
      58. if (char.IsNumber(cCurrent) || cCurrent == '-')
      59. {
      60. token = this.ReadNumber();
      61. }
      62. else if (char.IsLetter(cCurrent) || cCurrent == '_')
      63. {
      64. token = this.ReadWord();
      65. }
      66. else
      67. {
      68. this.StartToken();
      69. this.MoveForward();
      70. token = this.CreateToken(this.SymbolCharacters.Contains(cCurrent) ? TokenType.Symbol : TokenType.Unknown);
      71. }
      72. break;
      73. }
      74. return true;
      75. }
      76. public IEnumerable<Token> GetTokens()
      77. {
      78. Token currentToken;
      79. while (TryGetToken(out currentToken))
      80. {
      81. yield return currentToken;
      82. }
      83. yield return currentToken;
      84. yield break;
      85. }
      86. protected char LookAhead(int count = 1)
      87. {
      88. if (this.currentPosTotal + count - 1 >= this.inputCode.Length)
      89. {
      90. return EndOfFile;
      91. }
      92. return this.inputCode[this.currentPosTotal + count - 1];
      93. }
      94. protected void MoveForward()
      95. {
      96. this.currentPosTotal++;
      97. this.currentColumn++;
      98. }
      99. protected Token CreateToken(string value, TokenType type = TokenType.Unknown)
      100. {
      101. return new Token(this.currentLine, this.currentColumn, value, type);
      102. }
      103. protected Token CreateToken(TokenType type = TokenType.Unknown)
      104. {
      105. return new Token(this.tokenStartLine, this.tokenStartColumn, this.inputCode.Substring(this.tokenStartPosTotal, this.currentPosTotal - this.tokenStartPosTotal), type);
      106. }
      107. protected void StartToken()
      108. {
      109. this.tokenStartColumn = this.currentColumn;
      110. this.tokenStartLine = this.currentLine;
      111. this.tokenStartPosTotal = this.currentPosTotal;
      112. }
      113. protected Token ReadNewLine()
      114. {
      115. this.StartToken();
      116. if (this.LookAhead() == '\r' && this.LookAhead(2) == '\n')
      117. this.MoveForward();
      118. this.MoveForward();
      119. this.currentLine++;
      120. this.currentColumn = 1;
      121. return this.CreateToken(TokenType.EndOfLine);
      122. }
      123. protected Token ReadWhitespace()
      124. {
      125. this.StartToken();
      126. this.MoveForward();
      127. char cCurrent = this.LookAhead();
      128. while ((cCurrent == '\t' || cCurrent == ' ' ) && cCurrent != EndOfFile)
      129. {
      130. this.MoveForward();
      131. cCurrent = this.LookAhead();
      132. }
      133. return this.CreateToken(TokenType.WhiteSpace);
      134. }
      135. protected Token ReadWord()
      136. {
      137. this.StartToken();
      138. this.MoveForward();
      139. char cCurrent = this.LookAhead();
      140. while (((!char.IsWhiteSpace(cCurrent) && !this.SymbolCharacters.Contains(cCurrent))) && cCurrent != EndOfFile)
      141. {
      142. this.MoveForward();
      143. cCurrent = this.LookAhead();
      144. }
      145. return this.CreateToken(TokenType.Word);
      146. }
      147. protected Token ReadQuotedString()
      148. {
      149. this.StartToken();
      150. this.MoveForward();
      151. char cCurrent = this.LookAhead();
      152. while (cCurrent != EndOfFile)
      153. {
      154. switch (cCurrent)
      155. {
      156. case '\r':
      157. this.MoveForward();
      158. if (this.LookAhead() == '\n') this.MoveForward(); //Handle \r\n (CrLf)
      159. this.currentLine++;
      160. this.currentColumn = 1;
      161. break;
      162. case '\n':
      163. this.MoveForward();
      164. this.currentLine++;
      165. this.currentColumn = 1;
      166. break;
      167. case '"':
      168. this.MoveForward();
      169. if (this.LookAhead() != '"')
      170. {
      171. return this.CreateToken(TokenType.QuotedString);
      172. }
      173. this.MoveForward(); //Escaped Quote (Double Quote like in Visual Basic)
      174. break;
      175. default:
      176. this.MoveForward();
      177. break;
      178. }
      179. cCurrent = this.LookAhead();
      180. }
      181. return this.CreateToken(TokenType.Unknown);
      182. }
      183. protected Token ReadNumber()
      184. {
      185. this.StartToken();
      186. this.MoveForward();
      187. char cCurrent = this.LookAhead();
      188. bool hasDecimalSeperator = false;
      189. if (cCurrent == '-') this.MoveForward();
      190. while ((char.IsNumber(cCurrent) || (!hasDecimalSeperator && (hasDecimalSeperator = (cCurrent == this.DecimalSeperator)))) && cCurrent != EndOfFile)
      191. {
      192. this.MoveForward();
      193. cCurrent = this.LookAhead();
      194. }
      195. return this.CreateToken(TokenType.Number);
      196. }
      197. }
      198. }

      C#-Quellcode

      1. public class Token
      2. {
      3. public Token(int line, int column, string value, TokenType type)
      4. {
      5. this.Line = line;
      6. this.Column = column;
      7. this.Value = value;
      8. this.Type = type;
      9. }
      10. public int Line { get; private set; }
      11. public int Column { get; private set; }
      12. public string Value { get; private set; }
      13. public TokenType Type { get; private set; }
      14. public override string ToString()
      15. {
      16. return string.Format("{{Value: \"{0}\" Type: {1} (Line {2}, Column {3})}}", this.Value, this.Type, this.Line, this.Column);
      17. }
      18. }

      C#-Quellcode

      1. public enum TokenType
      2. {
      3. Unknown,
      4. Word,
      5. Number,
      6. QuotedString,
      7. WhiteSpace,
      8. Symbol,
      9. EndOfLine,
      10. EndOfFile
      11. }

      VB (über Converter)

      VB.NET-Quellcode

      1. Imports System.Collections.Generic
      2. Imports System.IO
      3. Imports System.Linq
      4. Imports System.Text
      5. Imports System.Threading.Tasks
      6. Namespace SimpleScript.Tokenizer
      7. Public Class Tokenizer
      8. Public Sub New(code As String)
      9. Me.IgnoreWhitespace = False
      10. Me.SymbolCharacters = "=+-/,.*~!@#$%^&(){}[]:;<>?|\".ToList()
      11. Me.DecimalSeperator = "."C
      12. Me.currentLine = 1
      13. Me.currentColumn = 1
      14. Me.currentPosTotal = 0
      15. Me.inputCode = code
      16. End Sub
      17. Private Const EndOfFile As Char = ChrW(0)
      18. Protected Property inputCode() As String
      19. Get
      20. Return m_inputCode
      21. End Get
      22. Private Set
      23. m_inputCode = Value
      24. End Set
      25. End Property
      26. Private m_inputCode As String
      27. Protected Property tokenStartLine() As Integer
      28. Get
      29. Return m_tokenStartLine
      30. End Get
      31. Set
      32. m_tokenStartLine = Value
      33. End Set
      34. End Property
      35. Private m_tokenStartLine As Integer
      36. Protected Property tokenStartColumn() As Integer
      37. Get
      38. Return m_tokenStartColumn
      39. End Get
      40. Set
      41. m_tokenStartColumn = Value
      42. End Set
      43. End Property
      44. Private m_tokenStartColumn As Integer
      45. Protected Property tokenStartPosTotal() As Integer
      46. Get
      47. Return m_tokenStartPosTotal
      48. End Get
      49. Set
      50. m_tokenStartPosTotal = Value
      51. End Set
      52. End Property
      53. Private m_tokenStartPosTotal As Integer
      54. Protected Property currentLine() As Integer
      55. Get
      56. Return m_currentLine
      57. End Get
      58. Set
      59. m_currentLine = Value
      60. End Set
      61. End Property
      62. Private m_currentLine As Integer
      63. Protected Property currentColumn() As Integer
      64. Get
      65. Return m_currentColumn
      66. End Get
      67. Set
      68. m_currentColumn = Value
      69. End Set
      70. End Property
      71. Private m_currentColumn As Integer
      72. Protected Property currentPosTotal() As Integer
      73. Get
      74. Return m_currentPosTotal
      75. End Get
      76. Set
      77. m_currentPosTotal = Value
      78. End Set
      79. End Property
      80. Private m_currentPosTotal As Integer
      81. Public Property IgnoreWhitespace() As Boolean
      82. Get
      83. Return m_IgnoreWhitespace
      84. End Get
      85. Set
      86. m_IgnoreWhitespace = Value
      87. End Set
      88. End Property
      89. Private m_IgnoreWhitespace As Boolean
      90. Public Property SymbolCharacters() As List(Of Char)
      91. Get
      92. Return m_SymbolCharacters
      93. End Get
      94. Set
      95. m_SymbolCharacters = Value
      96. End Set
      97. End Property
      98. Private m_SymbolCharacters As List(Of Char)
      99. Public Property DecimalSeperator() As Char
      100. Get
      101. Return m_DecimalSeperator
      102. End Get
      103. Set
      104. m_DecimalSeperator = Value
      105. End Set
      106. End Property
      107. Private m_DecimalSeperator As Char
      108. Public Function TryGetToken(ByRef token As Token) As Boolean
      109. Dim cCurrent As Char = Me.LookAhead()
      110. Select Case cCurrent
      111. Case EndOfFile
      112. Me.StartToken()
      113. token = Me.CreateToken(TokenType.EndOfFile)
      114. Return False
      115. Case " "C, ControlChars.Tab
      116. If Me.IgnoreWhitespace Then
      117. Me.MoveForward()
      118. Return Me.TryGetToken(token)
      119. End If
      120. token = Me.ReadWhitespace()
      121. Exit Select
      122. Case ControlChars.Cr, ControlChars.Lf
      123. token = Me.ReadNewLine()
      124. Exit Select
      125. Case """"C
      126. token = Me.ReadQuotedString()
      127. Exit Select
      128. Case Else
      129. If Char.IsNumber(cCurrent) OrElse cCurrent = "-"C Then
      130. token = Me.ReadNumber()
      131. ElseIf Char.IsLetter(cCurrent) OrElse cCurrent = "_"C Then
      132. token = Me.ReadWord()
      133. Else
      134. Me.StartToken()
      135. Me.MoveForward()
      136. token = Me.CreateToken(If(Me.SymbolCharacters.Contains(cCurrent), TokenType.Symbol, TokenType.Unknown))
      137. End If
      138. Exit Select
      139. End Select
      140. Return True
      141. End Function
      142. Public Function GetTokens() As IEnumerable(Of Token)
      143. Dim currentToken As Token
      144. While TryGetToken(currentToken)
      145. yield Return currentToken
      146. End While
      147. yield Return currentToken
      148. yield Exit Function
      149. End Function
      150. Protected Function LookAhead(Optional count As Integer = 1) As Char
      151. If Me.currentPosTotal + count - 1 >= Me.inputCode.Length Then
      152. Return EndOfFile
      153. End If
      154. Return Me.inputCode(Me.currentPosTotal + count - 1)
      155. End Function
      156. Protected Sub MoveForward()
      157. Me.currentPosTotal += 1
      158. Me.currentColumn += 1
      159. End Sub
      160. Protected Function CreateToken(value As String, Optional type As TokenType = TokenType.Unknown) As Token
      161. Return New Token(Me.currentLine, Me.currentColumn, value, type)
      162. End Function
      163. Protected Function CreateToken(Optional type As TokenType = TokenType.Unknown) As Token
      164. Return New Token(Me.tokenStartLine, Me.tokenStartColumn, Me.inputCode.Substring(Me.tokenStartPosTotal, Me.currentPosTotal - Me.tokenStartPosTotal), type)
      165. End Function
      166. Protected Sub StartToken()
      167. Me.tokenStartColumn = Me.currentColumn
      168. Me.tokenStartLine = Me.currentLine
      169. Me.tokenStartPosTotal = Me.currentPosTotal
      170. End Sub
      171. Protected Function ReadNewLine() As Token
      172. Me.StartToken()
      173. If Me.LookAhead() = ControlChars.Cr AndAlso Me.LookAhead(2) = ControlChars.Lf Then
      174. Me.MoveForward()
      175. End If
      176. Me.MoveForward()
      177. Me.currentLine += 1
      178. Me.currentColumn = 1
      179. Return Me.CreateToken(TokenType.EndOfLine)
      180. End Function
      181. Protected Function ReadWhitespace() As Token
      182. Me.StartToken()
      183. Me.MoveForward()
      184. Dim cCurrent As Char = Me.LookAhead()
      185. While (cCurrent = ControlChars.Tab OrElse cCurrent = " "C) AndAlso cCurrent <> EndOfFile
      186. Me.MoveForward()
      187. cCurrent = Me.LookAhead()
      188. End While
      189. Return Me.CreateToken(TokenType.WhiteSpace)
      190. End Function
      191. Protected Function ReadWord() As Token
      192. Me.StartToken()
      193. Me.MoveForward()
      194. Dim cCurrent As Char = Me.LookAhead()
      195. While ((Not Char.IsWhiteSpace(cCurrent) AndAlso Not Me.SymbolCharacters.Contains(cCurrent))) AndAlso cCurrent <> EndOfFile
      196. Me.MoveForward()
      197. cCurrent = Me.LookAhead()
      198. End While
      199. Return Me.CreateToken(TokenType.Word)
      200. End Function
      201. Protected Function ReadQuotedString() As Token
      202. Me.StartToken()
      203. Me.MoveForward()
      204. Dim cCurrent As Char = Me.LookAhead()
      205. While cCurrent <> EndOfFile
      206. Select Case cCurrent
      207. Case ControlChars.Cr
      208. Me.MoveForward()
      209. If Me.LookAhead() = ControlChars.Lf Then
      210. Me.MoveForward()
      211. End If
      212. 'Handle \r\n (CrLf)
      213. Me.currentLine += 1
      214. Me.currentColumn = 1
      215. Exit Select
      216. Case ControlChars.Lf
      217. Me.MoveForward()
      218. Me.currentLine += 1
      219. Me.currentColumn = 1
      220. Exit Select
      221. Case """"C
      222. Me.MoveForward()
      223. If Me.LookAhead() <> """"C Then
      224. Return Me.CreateToken(TokenType.QuotedString)
      225. End If
      226. Me.MoveForward()
      227. 'Escaped Quote (Double Quote like in Visual Basic)
      228. Exit Select
      229. Case Else
      230. Me.MoveForward()
      231. Exit Select
      232. End Select
      233. cCurrent = Me.LookAhead()
      234. End While
      235. Return Me.CreateToken(TokenType.Unknown)
      236. End Function
      237. Protected Function ReadNumber() As Token
      238. Me.StartToken()
      239. Me.MoveForward()
      240. Dim cCurrent As Char = Me.LookAhead()
      241. Dim hasDecimalSeperator As Boolean = False
      242. If cCurrent = "-"C Then
      243. Me.MoveForward()
      244. End If
      245. While (Char.IsNumber(cCurrent) OrElse (Not hasDecimalSeperator AndAlso (InlineAssignHelper(hasDecimalSeperator, (cCurrent = Me.DecimalSeperator))))) AndAlso cCurrent <> EndOfFile
      246. Me.MoveForward()
      247. cCurrent = Me.LookAhead()
      248. End While
      249. Return Me.CreateToken(TokenType.Number)
      250. End Function
      251. Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T
      252. target = value
      253. Return value
      254. End Function
      255. End Class
      256. End Namespace

      VB.NET-Quellcode

      1. Public Class Token
      2. Public Sub New(line As Integer, column As Integer, value As String, type As TokenType)
      3. Me.Line = line
      4. Me.Column = column
      5. Me.Value = value
      6. Me.Type = type
      7. End Sub
      8. Public Property Line() As Integer
      9. Get
      10. Return m_Line
      11. End Get
      12. Private Set
      13. m_Line = Value
      14. End Set
      15. End Property
      16. Private m_Line As Integer
      17. Public Property Column() As Integer
      18. Get
      19. Return m_Column
      20. End Get
      21. Private Set
      22. m_Column = Value
      23. End Set
      24. End Property
      25. Private m_Column As Integer
      26. Public Property Value() As String
      27. Get
      28. Return m_Value
      29. End Get
      30. Private Set
      31. m_Value = Value
      32. End Set
      33. End Property
      34. Private m_Value As String
      35. Public Property Type() As TokenType
      36. Get
      37. Return m_Type
      38. End Get
      39. Private Set
      40. m_Type = Value
      41. End Set
      42. End Property
      43. Private m_Type As TokenType
      44. Public Overrides Function ToString() As String
      45. Return String.Format("{{Value: ""{0}"" Type: {1} (Line {2}, Column {3})}}", Me.Value, Me.Type, Me.Line, Me.Column)
      46. End Function
      47. End Class

      VB.NET-Quellcode

      1. Public Enum TokenType
      2. Unknown
      3. Word
      4. Number
      5. QuotedString
      6. WhiteSpace
      7. Symbol
      8. EndOfLine
      9. EndOfFile
      10. End Enum

      Der Code ist übrigens stark an den des StringTokenizer angelehnt.

      Hoffentlich hilft dir das bei der Entwicklung einer von der Technik her etwas fortgeschritteneren Version deiner Skriptsprache. An sich finde ich die Idee ja eigentlich ganz gut.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „nafets“ ()

      Find die Idee eigentlich gar nicht so schlecht, jedoch ist der name ein bisschen doof? (Wie wärs was mit ...Script hintendran a la WindowsScript?) Was bestimmt noch cool wäre, wenn man sowas machen könnte:

      Quellcode

      1. text.setPauseText: Press any key...


      würde jedenfalls das gedusel im Code erheblich bessern. Außerdem sowas wie functions einfügen? Ist eigentlich gar nicht so schwer:

      Quellcode

      1. function Bla() {
      2. // code here...
      3. }


      Übersetzter Code:

      C#-Quellcode

      1. void Bla() {
      2. // code here..
      3. }


      müsstest nur function zu void übersetzen.

      EDIT:

      Hab übrigens mal hier was in Python probiert, vielleicht hilft es ja weiter ;):

      Quellcode

      1. #!/usr/bin/env python
      2. import fileinput
      3. if __name__ == '__main__':
      4. for line in fileinput.input('datei.script', inplace=True):
      5. print(line.replace('function', 'void'), end='')

      Software being "Done" is like lawn being "Mowed". (Jim Benson)

      Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „KidRick“ ()

      @KidRick

      Meines Wissens ist sowas nicht mal schnell so zu bewerkstelligen. Dafür braucht man Klassen, die das ganze dann allgemein bzw. dynamisch durchgehen. Es einfach in einen C#-Code zu übersetzen (zu mal das ganze in VB.Net geschrieben ist ^^ ), ist mMn der falsche Ansatz, und ich denke, dass das überhaupt nicht funktioniert.. Außerdem sollte man sich erstmal an elementare Dinge setzen: Variablen und If-Clauses. Ohne die würden Methoden noch garkeinen Sinn machen.

      LG