Source/NFX.Erlang/Internal/ErlParser.cs
/// <summary>
/// Compile a string fmt into an Erlang term
/// </summary>
Compile a string fmt into an Erlang term
Compile a string fmt into an Erlang term
internal static IErlObject Parse(
        string fmt, ref int pos, ref int argc, params object[] args)
    {
      var items = new List<IErlObject>();
      IErlObject result = null;
      pos = skipWSAndComments(fmt, pos);
      if (pos < fmt.Length)
      {
        switch (fmt[pos++])
        {
          case '{':
            if (State.Ok != pTuple(fmt, ref pos, ref items, ref argc, args))
              throw new ErlException(StringConsts.ERL_PARSING_AT_ERROR, "tuple", pos);
            result = new ErlTuple(items, false);
            break;
          case '[':
            if (fmt[pos] == ']')
            {
              result = new ErlList();
              pos++;
              break;
            }
            else if (State.Ok == pList(fmt, ref pos, ref items, ref argc, args))
            {
              result = new ErlList(items, false);
              break;
            }
            throw new ErlException(StringConsts.ERL_PARSING_AT_ERROR, "list", pos);
          case '<':
            if (pos < fmt.Length - 1 && fmt[pos] == '<')
            {
              var i = ++pos;
              var str = fmt[i] == '"';
              if (str) pos++;
              for (; i < fmt.Length && fmt[i - 1] != '>' && fmt[i] != '>'; ++i);
              if (i == fmt.Length)
                break;
              var end   = ++i - (str ? 3 : 2);
              var len   = end - pos + 1;
              byte[] bytes;
              if (str)
              {
                var cnt = Encoding.UTF8.GetByteCount(fmt.ToCharArray(), pos, len);
                bytes = new byte[cnt];
                Encoding.UTF8.GetBytes(fmt, pos, len, bytes, 0);
              }
              else
              {
                var beg = pos - 2;
                bytes   = fmt.Substring(pos, len)
                             .Split(new char[] {',', ' '},
                                    StringSplitOptions.RemoveEmptyEntries)
                             .Select(s =>
                             {
                               var n = int.Parse(s);
                               if (n < 0 || n > 255)
                                 throw new ErlException
                                  ("Invalid binary in format string: {0}".Args(fmt.Substring(beg, len+4)));
                               return (byte)n;
                             })
                             .ToArray();
              }
              result = new ErlBinary(bytes, 0, bytes.Length);
              pos = i+1;
            }
            break;
          case '$': 
            result = new ErlByte(Convert.ToByte(fmt[pos++]));
            break;
          case '~':
            if (State.Ok != pFormat(fmt, ref pos, ref items, ref argc, args))
              throw new ErlException(StringConsts.ERL_PARSING_AT_ERROR, "term", pos);
            result = items[0];
            break;
          default:
            char c = fmt[--pos];
            if (char.IsLower(c))
            {         
              string s = pAtom(fmt, ref pos);
              result = createAtom(s);
            }
            else if (char.IsUpper(c) || c == '_')
            {
              result = pVariable(fmt, ref pos);
            }
            else if (char.IsDigit(c) || c == '-')
            {    
              string s = pDigit(fmt, ref pos);
              if (s.IndexOf('.') < 0)
                result = new ErlLong(long.Parse(s, CultureInfo.InvariantCulture));
              else
                result = new ErlDouble(double.Parse(s, CultureInfo.InvariantCulture));
            }
            else if (c == '"')
            {      
              string s = pString(fmt, ref pos);
              result = new ErlString(s);
            }
            else if (c == '\'')
            {     
              string s = pQuotedAtom(fmt, ref pos);
              result = createAtom(s);
            }
            break;
        }
      }
      if (result == null)
        throw new ErlException(StringConsts.ERL_INVALID_VALUE_ERROR.Args(fmt));
      return result;
    }
internal static IErlObject Parse ( string fmt , ref int pos , ref int argc , params object [ ] args ) { var items = new List < IErlObject > ( ) ; IErlObject result = null ; pos = skipWSAndComments ( fmt , pos ) ; if ( pos < fmt . Length ) { switch ( fmt [ pos ++ ] ) { case ' ' : if ( State . Ok != pTuple ( fmt , ref pos , ref items , ref argc , args ) ) throw new ErlException ( StringConsts . ERL_PARSING_AT_ERROR , " " , pos ) ; result = new ErlTuple ( items , false ) ; break ; case ' ' : if ( fmt [ pos ] == ' ' ) { result = new ErlList ( ) ; pos ++ ; break ; } else if ( State . Ok == pList ( fmt , ref pos , ref items , ref argc , args ) ) { result = new ErlList ( items , false ) ; break ; } throw new ErlException ( StringConsts . ERL_PARSING_AT_ERROR , " " , pos ) ; case ' ' : if ( pos < fmt . Length - 1 && fmt [ pos ] == ' ' ) { var i = ++ pos ; var str = fmt [ i ] == ' ' ; if ( str ) pos ++ ; for ( ; i < fmt . Length && fmt [ i - 1 ] != ' ' && fmt [ i ] != ' ' ; ++ i ) ; if ( i == fmt . Length ) break ; var end = ++ i - ( str ? 3 : 2 ) ; var len = end - pos + 1 ; byte [ ] bytes ; if ( str ) { var cnt = Encoding . UTF8 . GetByteCount ( fmt . ToCharArray ( ) , pos , len ) ; bytes = new byte [ cnt ] ; Encoding . UTF8 . GetBytes ( fmt , pos , len , bytes , 0 ) ; } else { var beg = pos - 2 ; bytes = fmt . Substring ( pos , len ) . Split ( new char [ ] { ' ' , ' ' } , StringSplitOptions . RemoveEmptyEntries ) . Select ( s => { var n = int . Parse ( s ) ; if ( n < 0 || n > 255 ) throw new ErlException ( " " . Args ( fmt . Substring ( beg , len + 4 ) ) ) ; return ( byte ) n ; } ) . ToArray ( ) ; } result = new ErlBinary ( bytes , 0 , bytes . Length ) ; pos = i + 1 ; } break ; case ' ' : result = new ErlByte ( Convert . ToByte ( fmt [ pos ++ ] ) ) ; break ; case ' ' : if ( State . Ok != pFormat ( fmt , ref pos , ref items , ref argc , args ) ) throw new ErlException ( StringConsts . ERL_PARSING_AT_ERROR , " " , pos ) ; result = items [ 0 ] ; break ; default : char c = fmt [ -- pos ] ; if ( char . IsLower ( c ) ) { string s = pAtom ( fmt , ref pos ) ; result = createAtom ( s ) ; } else if ( char . IsUpper ( c ) || c == ' ' ) { result = pVariable ( fmt , ref pos ) ; } else if ( char . IsDigit ( c ) || c == ' ' ) { string s = pDigit ( fmt , ref pos ) ; if ( s . IndexOf ( ' ' ) < 0 ) result = new ErlLong ( long . Parse ( s , CultureInfo . InvariantCulture ) ) ; else result = new ErlDouble ( double . Parse ( s , CultureInfo . InvariantCulture ) ) ; } else if ( c == ' ' ) { string s = pString ( fmt , ref pos ) ; result = new ErlString ( s ) ; } else if ( c == ' \' ' ) { string s = pQuotedAtom ( fmt , ref pos ) ; result = createAtom ( s ) ; } break ; } } if ( result == null ) throw new ErlException ( StringConsts . ERL_INVALID_VALUE_ERROR . Args ( fmt ) ) ; return result ; }
Compile a string fmt into an Erlang term
Compile a string fmt into an Erlang term
/* char-value? */ /* atom  ? */ /* integer/float ? */ /* string ? */ /* quoted atom ? */
fmt
string
int
ref