Csharp/C Sharp/Development Class/Parser

Материал из .Net Framework эксперт
Перейти к: навигация, поиск

This module contains the recursive descent parser that does not use variables

<source lang="csharp"> /* C#: The Complete Reference by Herbert Schildt Publisher: Osborne/McGraw-Hill (March 8, 2002) ISBN: 0072134852

  • /

/*

  This module contains the recursive descent 
  parser that does not use variables. 
  • /

using System;

// Exception class for parser errors. class ParserException : ApplicationException {

 public ParserException(string str) : base(str) { }  

 public override string ToString() { 
   return Message; 
 } 

}

class Parser {

 // Enumerate token types. 
 enum Types { NONE, DELIMITER, VARIABLE, NUMBER }; 
 // Enumerate error types. 
 enum Errors { SYNTAX, UNBALPARENS, NOEXP, DIVBYZERO }; 

 string exp;    // refers to expression string 
 int expIdx;    // current index into the expression 
 string token;  // holds current token 
 Types tokType; // holds token"s type 

 // Parser entry point. 
 public double Evaluate(string expstr) 
 { 
   double result; 
  
   exp = expstr; 
   expIdx = 0;  
 
   try {  
     GetToken(); 
     if(token == "") { 
       SyntaxErr(Errors.NOEXP); // no expression present 
       return 0.0; 
     } 

     EvalExp2(out result); 

     if(token != "") // last token must be null 
       SyntaxErr(Errors.SYNTAX); 

     return result; 
   } catch (ParserException exc) { 
     // Add other error handling here, as desired. 
     Console.WriteLine(exc); 
     return 0.0; 
   } 
 } 
  
 // Add or subtract two terms. 
 void EvalExp2(out double result) 
 { 
   string op; 
   double partialResult; 
  
   EvalExp3(out result); 
   while((op = token) == "+" || op == "-") { 
     GetToken(); 
     EvalExp3(out partialResult); 
     switch(op) { 
       case "-": 
         result = result - partialResult; 
         break; 
       case "+": 
         result = result + partialResult; 
         break; 
     } 
   } 
 } 
  
 // Multiply or divide two factors. 
 void EvalExp3(out double result) 
 { 
   string op; 
   double partialResult = 0.0; 
  
   EvalExp4(out result); 
   while((op = token) == "*" || 
          op == "/" || op == "%") { 
     GetToken(); 
     EvalExp4(out partialResult); 
     switch(op) { 
       case "*": 
         result = result * partialResult; 
         break; 
       case "/": 
         if(partialResult == 0.0) 
           SyntaxErr(Errors.DIVBYZERO); 
         result = result / partialResult; 
         break; 
       case "%": 
         if(partialResult == 0.0) 
           SyntaxErr(Errors.DIVBYZERO); 
         result = (int) result % (int) partialResult; 
         break; 
     } 
   } 
 } 
  
 // Process an exponent. 
 void EvalExp4(out double result) 
 { 
   double partialResult, ex; 
   int t; 
  
   EvalExp5(out result); 
   if(token == "^") { 
     GetToken(); 
     EvalExp4(out partialResult); 
     ex = result; 
     if(partialResult == 0.0) { 
       result = 1.0; 
       return; 
     } 
     for(t=(int)partialResult-1; t > 0; t--) 
       result = result * (double)ex; 
   } 
 } 
  
 // Evaluate a unary + or -. 
 void EvalExp5(out double result) 
 { 
   string  op; 
  
   op = ""; 
   if((tokType == Types.DELIMITER) && 
       token == "+" || token == "-") { 
     op = token; 
     GetToken(); 
   } 
   EvalExp6(out result); 
   if(op == "-") result = -result; 
 } 
  
 // Process a parenthesized expression. 
 void EvalExp6(out double result) 
 { 
   if((token == "(")) { 
     GetToken(); 
     EvalExp2(out result); 
     if(token != ")") 
       SyntaxErr(Errors.UNBALPARENS); 
     GetToken(); 
   } 
   else Atom(out result); 
 } 
  
 // Get the value of a number. 
 void Atom(out double result) 
 { 
   switch(tokType) { 
     case Types.NUMBER: 
       try { 
         result = Double.Parse(token); 
       } catch (FormatException) { 
         result = 0.0; 
         SyntaxErr(Errors.SYNTAX); 
       } 
       GetToken(); 
       return; 
     default: 
       result = 0.0; 
       SyntaxErr(Errors.SYNTAX); 
       break; 
   } 
 } 
  
 // Handle a syntax error. 
 void SyntaxErr(Errors error) 
 { 
   string[] err = { 
     "Syntax Error", 
     "Unbalanced Parentheses", 
     "No Expression Present", 
     "Division by Zero" 
   }; 

   throw new ParserException(err[(int)error]); 
 } 
  
 // Obtain the next token. 
 void GetToken() 
 { 
   tokType = Types.NONE; 
   token = ""; 
   
   if(expIdx == exp.Length) return; // at end of expression 
  
   // skip over white space 
   while(expIdx < exp.Length && 
         Char.IsWhiteSpace(exp[expIdx])) ++expIdx; 

   // trailing whitespace ends expression 
   if(expIdx == exp.Length) return; 

   if(IsDelim(exp[expIdx])) { // is operator 
     token += exp[expIdx]; 
     expIdx++; 
     tokType = Types.DELIMITER; 
   } 
   else if(Char.IsLetter(exp[expIdx])) { // is variable 
     while(!IsDelim(exp[expIdx])) { 
       token += exp[expIdx]; 
       expIdx++; 
       if(expIdx >= exp.Length) break; 
     } 
     tokType = Types.VARIABLE; 
   } 
   else if(Char.IsDigit(exp[expIdx])) { // is number 
     while(!IsDelim(exp[expIdx])) { 
       token += exp[expIdx]; 
       expIdx++; 
       if(expIdx >= exp.Length) break; 
     } 
     tokType = Types.NUMBER; 
   } 
 } 
  
 // Return true if c is a delimiter. 
 bool IsDelim(char c) 
 { 
   if((" +-/*%^=()".IndexOf(c) != -1)) 
     return true; 
   return false; 
 } 
  

}

// Demonstrate the parser.

public class ParserDemo {

 public static void Main() 
 { 
   string expr; 
   Parser p = new Parser(); 

   Console.WriteLine("Enter an empty expression to stop."); 

   for(;;) { 
     Console.Write("Enter expression: "); 
     expr = Console.ReadLine(); 
     if(expr == "") break; 
     Console.WriteLine("Result: " + p.Evaluate(expr)); 
   } 
 } 

}


      </source>


This module contains the recursive descent parser that recognizes variables

<source lang="csharp"> /* C#: The Complete Reference by Herbert Schildt Publisher: Osborne/McGraw-Hill (March 8, 2002) ISBN: 0072134852

  • /

/*

  This module contains the recursive descent 
  parser that recognizes variables. 
  • /

using System;

// Exception class for parser errors. class ParserException : ApplicationException {

 public ParserException(string str) : base(str) { }  

 public override string ToString() { 
   return Message; 
 } 

}

class Parser {

 // Enumerate token types. 
 enum Types { NONE, DELIMITER, VARIABLE, NUMBER }; 
 // Enumerate error types. 
 enum Errors { SYNTAX, UNBALPARENS, NOEXP, DIVBYZERO }; 

 string exp;    // refers to expression string 
 int expIdx;    // current index into the expression 
 string token;  // holds current token 
 Types tokType; // holds token"s type 

 // Array for variables. 
 double[] vars = new double[26]; 

 public Parser() { 
   // Initialize the variables to zero. 
   for(int i=0; i < vars.Length; i++)  
      vars[i] = 0.0; 
 } 

 // Parser entry point. 
 public double Evaluate(string expstr) 
 { 
   double result; 
  
   exp = expstr; 
   expIdx = 0;  

   try {  
     GetToken(); 
     if(token == "") { 
       SyntaxErr(Errors.NOEXP); // no expression present 
       return 0.0; 
     } 

     EvalExp1(out result); // now, call EvalExp1() to start 

     if(token != "") // last token must be null 
       SyntaxErr(Errors.SYNTAX); 

     return result; 
   } catch (ParserException exc) { 
     // Add other error handling here, as desired. 
     Console.WriteLine(exc); 
     return 0.0; 
   } 
 } 
  
 // Process an assignment. 
 void EvalExp1(out double result) 
 { 
   int varIdx; 
   Types ttokType; 
   string temptoken; 

   if(tokType == Types.VARIABLE) { 
     // save old token 
     temptoken = String.Copy(token); 
     ttokType = tokType; 

     // Compute the index of the variable. 
     varIdx = Char.ToUpper(token[0]) - "A"; 

     GetToken(); 
     if(token != "=") { 
       PutBack(); // return current token 
       // restore old token -- not an assignment 
       token = String.Copy(temptoken); 
       tokType = ttokType; 
     } 
     else { 
       GetToken(); // get next part of exp 
       EvalExp2(out result); 
       vars[varIdx] = result; 
       return; 
     } 
   } 

   EvalExp2(out result); 
 } 

 // Add or subtract two terms. 
 void EvalExp2(out double result) 
 { 
   string op; 
   double partialResult; 
  
   EvalExp3(out result); 
   while((op = token) == "+" || op == "-") { 
     GetToken(); 
     EvalExp3(out partialResult); 
     switch(op) { 
       case "-": 
         result = result - partialResult; 
         break; 
       case "+": 
         result = result + partialResult; 
         break; 
     } 
   } 
 } 
  
 // Multiply or divide two factors. 
 void EvalExp3(out double result) 
 { 
   string op; 
   double partialResult = 0.0; 
  
   EvalExp4(out result); 
   while((op = token) == "*" || 
          op == "/" || op == "%") { 
     GetToken(); 
     EvalExp4(out partialResult); 
     switch(op) { 
       case "*": 
         result = result * partialResult; 
         break; 
       case "/": 
         if(partialResult == 0.0) 
           SyntaxErr(Errors.DIVBYZERO); 
         result = result / partialResult; 
         break; 
       case "%": 
         if(partialResult == 0.0) 
           SyntaxErr(Errors.DIVBYZERO); 
         result = (int) result % (int) partialResult; 
         break; 
     } 
   } 
 } 
  
 // Process an exponent. 
 void EvalExp4(out double result) 
 { 
   double partialResult, ex; 
   int t; 
  
   EvalExp5(out result); 
   if(token == "^") { 
     GetToken(); 
     EvalExp4(out partialResult); 
     ex = result; 
     if(partialResult == 0.0) { 
       result = 1.0; 
       return; 
     } 
     for(t=(int)partialResult-1; t > 0; t--) 
       result = result * (double)ex; 
   } 
 } 
  
 // Evaluate a unary + or -. 
 void EvalExp5(out double result) 
 { 
   string  op; 
  
   op = ""; 
   if((tokType == Types.DELIMITER) && 
       token == "+" || token == "-") { 
     op = token; 
     GetToken(); 
   } 
   EvalExp6(out result); 
   if(op == "-") result = -result; 
 } 
  
 // Process a parenthesized expression. 
 void EvalExp6(out double result) 
 { 
   if((token == "(")) { 
     GetToken(); 
     EvalExp2(out result); 
     if(token != ")") 
       SyntaxErr(Errors.UNBALPARENS); 
     GetToken(); 
   } 
   else Atom(out result); 
 } 
  
 // Get the value of a number or variable. 
 void Atom(out double result) 
 { 
   switch(tokType) { 
     case Types.NUMBER: 
       try { 
         result = Double.Parse(token); 
       } catch (FormatException) { 
         result = 0.0; 
         SyntaxErr(Errors.SYNTAX); 
       } 
       GetToken(); 
       return; 
     case Types.VARIABLE: 
       result = FindVar(token); 
       GetToken(); 
       return; 
     default: 
       result = 0.0; 
       SyntaxErr(Errors.SYNTAX); 
       break; 
   } 
 } 
  
  // Return the value of a variable. 
 double FindVar(string vname) 
 { 
   if(!Char.IsLetter(vname[0])){ 
     SyntaxErr(Errors.SYNTAX); 
     return 0.0; 
   } 
   return vars[Char.ToUpper(vname[0])-"A"]; 
 } 

 // Return a token to the input stream. 
 void PutBack()   
 { 
   for(int i=0; i < token.Length; i++) expIdx--; 
 } 

 // Handle a syntax error. 
 void SyntaxErr(Errors error) 
 { 
   string[] err = { 
     "Syntax Error", 
     "Unbalanced Parentheses", 
     "No Expression Present", 
     "Division by Zero" 
   }; 

   throw new ParserException(err[(int)error]); 
 } 
  
 // Obtain the next token. 
 void GetToken() 
 { 
   tokType = Types.NONE; 
   token = ""; 
   
   if(expIdx == exp.Length) return; // at end of expression 
  
   // skip over white space 
   while(expIdx < exp.Length && 
         Char.IsWhiteSpace(exp[expIdx])) ++expIdx; 

   // trailing whitespace ends expression 
   if(expIdx == exp.Length) return; 

   if(IsDelim(exp[expIdx])) { // is operator 
     token += exp[expIdx]; 
     expIdx++; 
     tokType = Types.DELIMITER; 
   } 
   else if(Char.IsLetter(exp[expIdx])) { // is variable 
     while(!IsDelim(exp[expIdx])) { 
       token += exp[expIdx]; 
       expIdx++; 
       if(expIdx >= exp.Length) break; 
     } 
     tokType = Types.VARIABLE; 
   } 
   else if(Char.IsDigit(exp[expIdx])) { // is number 
     while(!IsDelim(exp[expIdx])) { 
       token += exp[expIdx]; 
       expIdx++; 
       if(expIdx >= exp.Length) break; 
     } 
     tokType = Types.NUMBER; 
   } 
 } 
  
 // Return true if c is a delimiter. 
 bool IsDelim(char c) 
 { 
   if((" +-/*%^=()".IndexOf(c) != -1)) 
     return true; 
   return false; 
 }   

}

// Demonstrate the parser.

public class ParserDemo1 {

 public static void Main() 
 { 
   string expr; 
   Parser p = new Parser(); 

   Console.WriteLine("Enter an empty expression to stop."); 

   for(;;) { 
     Console.Write("Enter expression: "); 
     expr = Console.ReadLine(); 
     if(expr == "") break; 
     Console.WriteLine("Result: " + p.Evaluate(expr)); 
   } 
 } 

}


      </source>