Gå til innhold

Anbefalte innlegg

  • 3 måneder senere...
Videoannonse
Annonse

Funker ikke under Windows 7 eller Vista med UAC skrudd på ettersom programmet ikke har tilgang til å skrive til C: og derfor avslutter ganske fort :)

 

Jeg foreslår at du heller skriver til My Documents eller lignende med følgende funksjon:

System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)

Lenke til kommentar
  • 1 måned senere...
  • 2 uker senere...
  • 1 måned senere...

I Eclipse IDE-en til Java er det mulig å flytte hele kodelinjer opp eller ned ved å bruke ALT+piltaster opp og ned.

 

Noen som vet om det finnes tilsvarende funksjonalitet i Visual Studio 2010?

Fant det ikke i listen over keyboard shortcuts, men det er jo evig mange der og muligheter for å overse noe.

 

Takk:)

Lenke til kommentar
  • 3 måneder senere...

Tokenizer for C-aktig språk:

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DvParser
{

public interface ITokenizer
{
	IEnumerable<Token> Read();
}

/// <summary>
/// Represents a token in the text document
/// </summary>
public class Token
{
	/// <summary>
	/// Token string
	/// </summary>
	public string Value { get; private set; }
	/// <summary>
	/// Line number in source file
	/// </summary>
	public int LineNumber { get; private set; }
	/// <summary>
	/// Character position on line in source file
	/// </summary>
	public int CharacterPosition { get; private set; }
	/// <summary>
	/// Source filename
	/// </summary>
	public string Filename { get; private set; }
	/// <summary>
	/// Pattern that his token matched
	/// </summary>
	public PatternMatched Pattern { get; private set; }

	public Token(string value, int line, int pos, string filename, PatternMatched pattern)
	{
		Value = value;
		LineNumber = line;
		CharacterPosition = pos;
		Filename = filename;
		Pattern = pattern;
	}

	public bool IsIdentifier()
	{
		return Pattern == PatternMatched.Identifier;
	}

	public bool IsIdentifier(string value)
	{
		return Pattern == PatternMatched.Identifier && Value == value;
	}

	public bool IsOperator()
	{
		return Pattern == PatternMatched.Operator;
	}

	public bool IsOperator(string op)
	{
		return Pattern == PatternMatched.Operator && op == Value;
	}

	public override string ToString()
	{
		return Value;
	}
}

/// <summary>
/// Represents each pattern that can match
/// </summary>
public enum PatternMatched
{
	NoMatch,
	String,
	Identifier,
	Comment,
	Whitespace,
	Operator,
	Integer,
	FloatingPoint,
	Character,
}

/// <summary>
/// Tokenizes a C-style text document
/// </summary>
public class Tokenizer : ITokenizer
{
	/// <summary>
	/// Source text this object tokenizes
	/// </summary>
	public string SourceText { get; private set; }
	/// <summary>
	/// Filename to tokenize
	/// </summary>
	public string Filename { get; private set; }

	public int CurrentLine { get; private set; }
	public int CurrentPos { get; private set; }
	public int CurrentIndex { get; private set; }
	public string CurrentToken { get { return Token.ToString(); } }

	// Constructs the token
	private StringBuilder Token;

	private int TokenLine;
	private int TokenPos;
	PatternMatched TokenPattern;

	// Used to store positions in the text
	private Stack<int> BacktrackStack;

	private char CurrentChar { get { return CurrentIndex >= SourceText.Length ? '\0' : SourceText[CurrentIndex]; } }

	private bool EndOfFile { get { return CurrentIndex >= SourceText.Length; } }

	/// <summary>
	/// Gets an enumerable source of operators defined for the tokenizer
	/// </summary>
	private IEnumerable<string> Operators
	{
		get
		{
			return new System.Collections.ObjectModel.ReadOnlyCollection<string>(
				new string[]
				{
					"->", ".", "::",
					">>", "<<",
					"==", "!=",  "||", "&&", "<=", ">=", "<", ">",
					"|", "&", "^", "~", "!",
					 "+", "-", "*", "/", "%", "=",
					 "{", "}", "(", ")", "[", "]", 
					 ";", ":", "?", ","
				});
		}
	}

	/// <summary>
	/// Stores the starting position for the token to be matched
	/// </summary>
	/// <param name="pattern"></param>
	private void StartToken(PatternMatched pattern)
	{
		Token.Clear();
		TokenLine = CurrentLine;
		TokenPos = CurrentPos;
		TokenPattern = pattern;
	}

	/// <summary>
	/// Tries to match an operator defined in the 'Operators' array
	/// </summary>
	/// <returns>True if operator matched</returns>
	private bool Operator()
	{
		StartToken(PatternMatched.Operator);
		foreach (var op in Operators)
		{
			Token.Clear();
			if (Match(op))
				return true;
		}
		return false;
	}

	/// <summary>
	/// Builds a token object using current data
	/// </summary>
	/// <param name="pattern"></param>
	/// <returns></returns>
	private Token BuildToken()
	{
		try
		{
			return new Token(
				Token.ToString(),
				TokenLine,
				TokenPos,
				Filename,
				TokenPattern);
		}
		finally
		{
			Token.Clear();
		}
	}

	private bool Identifier()
	{
		StartToken(PatternMatched.Identifier);
		// Check if first character is a letter, excluding integers
		if (char.IsLetter(CurrentChar) || CurrentChar == '_')
		{
			Consume();
			ZeroOrMore(c => char.IsLetterOrDigit(c) || c == '_');
			return true;
		}
		else
			return false;
	}
	/// <summary>
	/// Matches a character in C, such as 'a'
	/// </summary>
	/// <returns></returns>
	private bool Character()
	{
		StartToken(PatternMatched.Character);
		return String('\'');
	}

	private bool String()
	{
		StartToken(PatternMatched.String);
		return String('"');
	}

	/// <summary>
	/// Consumes a string surrounded by type
	/// </summary>
	/// <param name="type">Character surrounding string</param>
	/// <returns></returns>
	private bool String(char type)
	{
		StartToken(PatternMatched.String);
		// Check if first character is "
		if (CurrentChar == type)
		{
			Consume();

			bool is_escaped = false;
			bool end = false;
			while (!EndOfFile && !end)
			{
				// We want to consume escaped "
				// So one backslash will escape the string, but two will escape the
				// backslash.
				if (CurrentChar == '\\')
					is_escaped = !is_escaped;
				else if (CurrentChar == type && !is_escaped)
					end = true;
				Consume();
			}
			return true;
		}
		else
			return false;
	}

	/// <summary>
	/// Consumes exactly count characters
	/// </summary>
	/// <param name="f">Character selection predicate</param>
	/// <param name="count">Number of characters to consume</param>
	/// <returns>True if count characters has been consumed</returns>
	private bool Exactly(Predicate<char> f, int count)
	{
		Push();
		for (int i = 0; i < count; i++)
		{
			if (!EndOfFile && f(CurrentChar))
				Consume();
			else
			{
				Fail();
				return false;
			}
		}
		Pop();
		return true;
	}

	/// <summary>
	/// Matches an integer or hexadecimal
	/// </summary>
	/// <returns></returns>
	private bool Integer()
	{
		StartToken(PatternMatched.Integer);
		// If integer is prefixed with 0x, it is a hexadesimal.
		if (Match("0x"))
			return OnceOrMore(c => char.IsNumber(c) || c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F');
		else
		{
			Push();
			// Check if integer is negative
			if (CurrentChar == '-')
				Consume();
			// Consume integer
			if (OnceOrMore(c => char.IsNumber(c)))
			{
				Pop();
				return true;
			}
			else
			{
				Fail();
				return false;
			}
		}
	}

	/// <summary>
	/// Matches a string
	/// </summary>
	/// <param name="value">String to match</param>
	/// <returns>True if string matched</returns>
	private bool Match(string value)
	{
		Push();
		for (int i = 0; i < value.Length; i++)
		{
			if (EndOfFile || CurrentChar != value[i])
			{
				Fail();
				return false;
			}
			else
				Consume();
		}
		Pop();
		return true;
	}

	/// <summary>
	/// Matches whitespace
	/// </summary>
	/// <returns></returns>
	private bool WhiteSpace()
	{
		StartToken(PatternMatched.Whitespace);
		return OnceOrMore(c => char.IsWhiteSpace(c));
	}

	/// <summary>
	/// Matches comments, either // or /* */
	/// </summary>
	/// <returns></returns>
	private bool Comment()
	{
		StartToken(PatternMatched.Comment);
		if (Exactly(c => c == '/', 2))
		{
			ZeroOrMore(c => c != '\n' && c  != '\r');
			return true;
		}
		else if (Match("/*"))
		{
			while (!Match("*/"))
				Consume();
			return true;
		}
		else
			return false;
	}

	/// <summary>
	/// Matches a floating point which can be postfixed with exponential value
	/// </summary>
	/// <returns></returns>
	private bool FloatingPoint()
	{
		StartToken(PatternMatched.FloatingPoint);
		bool success = false;
		Push();

		// Check if floating point is negative
		if (CurrentChar == '-')
			Consume();

		// Floating point doesn't need to start with numbers,
		// so check if first character is decimal seperator
		// This will match regex \.\d+
		if (CurrentChar == '.')
		{
			Consume();
			success = OnceOrMore(c => char.IsNumber(c));
		}
		else if (OnceOrMore(c => char.IsNumber(c)))
		{

			// This will match regex \d+\.\d+
			if (!EndOfFile && CurrentChar == '.')
			{
				Consume();
				success = OnceOrMore(c => char.IsNumber(c));
			}
				// If the integer is postfixed with e, we might still have a floating point
			else if (CurrentChar == 'e')
				success = true;					
		}
		// Check if exponent postfix applies
		if ((success) && !EndOfFile && CurrentChar == 'e')
		{
			// Consume exponent
			Consume();
			if (CurrentChar == '-')
				Consume();
			success = OnceOrMore(c => char.IsNumber(c));
		}

		if (success)
			Pop();
		else
			Fail();
		return success;

	}

	/// <summary>
	/// Matches predicate f once or more
	/// </summary>
	/// <param name="f"></param>
	/// <returns></returns>
	private bool OnceOrMore(Predicate<char> f)
	{
		if (!EndOfFile && f(CurrentChar))
		{
			Consume();
			while (!EndOfFile && f(CurrentChar))
				Consume();
			return true;
		}
		return false;
	}

	/// <summary>
	/// Matches predicate f zero or more times
	/// Naturally, this will always return true, since zero characters
	/// is acceptable.
	/// </summary>
	/// <param name="f"></param>
	/// <returns></returns>
	private bool ZeroOrMore(Predicate<char> f)
	{
		while (!EndOfFile && f(CurrentChar))
			Consume();
		return true;
	}

	/// <summary>
	/// Consumes one character
	/// </summary>
	private void Consume()
	{
		Token.Append(CurrentChar);
		MoveNext();
	}

	/// <summary>
	/// Moves to next character
	/// </summary>
	/// <returns>Next character, or zero </returns>
	private char MoveNext()
	{
		// Check if next character would get the tokenizer out of bounds
		if (CurrentIndex >= SourceText.Length - 1)
		{
			CurrentIndex = SourceText.Length;
			return '0';
		}
		else
		{
			// If the character is a newline, increment current line and reset position
			// This enables the tokenizer to know what line and character a token is located in
			if (CurrentChar == '\n')
			{
				++CurrentLine;
				CurrentPos = 0;
			}
			else
				++CurrentPos;

			++CurrentIndex;

			return SourceText[CurrentIndex];

		}
	}

	/// <summary>
	/// Pushes the current index to stack
	/// </summary>
	public void Push()
	{
		BacktrackStack.Push(CurrentIndex);
	}

	/// <summary>
	/// Pops an index of the stack, and sets the position to the popped value
	/// </summary>
	public void Fail()
	{
		CurrentIndex = BacktrackStack.Pop();
	}

	/// <summary>
	/// Pops the stack without changing the state of the tokenizer
	/// This will be called when pattern has been matched.
	/// </summary>
	public void Pop()
	{
		BacktrackStack.Pop();
	}

	public Tokenizer(string text, string filename)
	{
		CurrentLine = 1;
		BacktrackStack = new Stack<int>();
		CurrentIndex = 0;
		SourceText = text;
		Filename = filename;
		Token = new StringBuilder();
	}

	public Tokenizer(string filename)
		: this(null, filename)
	{
		SourceText = System.IO.File.ReadAllText(filename);
	}

	public IEnumerable<Token> Read()
	{
		int invalid_line = 0;
		int invalid_pos = 0;
		StringBuilder invalid_token = new StringBuilder();
		while (!EndOfFile)
		{
			if (Comment() // Pattern match comments
				|| Identifier() // Pattern match identifier
				|| String() // etc.
				|| Character()
				|| WhiteSpace()
				|| FloatingPoint()
				|| Operator()
				|| Integer()
				)
			{
				if (invalid_token.Length > 0)
				{
					// Characters without match has been detected
					// Return it as a token
					yield return new Token(invalid_token.ToString(), invalid_line, invalid_pos, Filename, PatternMatched.NoMatch);
					invalid_token.Clear();
				}
				yield return BuildToken();
			}
			else
			{
				// Aggregate all non-matches
				if (invalid_token.Length == 0)
				{
					invalid_line = CurrentLine;
					invalid_pos = CurrentPos;
				}
				invalid_token.Append(CurrentChar);
				MoveNext();
			}
		}
	}
}
}

 

 

edit: fikset noen småfeil.

Endret av GeirGrusom
Lenke til kommentar
  • 2 uker senere...

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...