summaryrefslogtreecommitdiff
path: root/libs/cassowary/cassowary/ClReader.h
blob: 4eef907759d1ec5fb4cb8960bf60a7de457dee69 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClReader.h
// Original implementation contributed by Steve Wolfman
// Subsequently largely revised by Greg J. Badros

#ifndef CREADER_H
#define CREADER_H

#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif

#include <string>
#include <map>
#include <algorithm>
#include <iostream>
#include "ClErrors.h"
#include "ClVariable.h"
#include "ClStrength.h"
#include "ClLinearExpression_fwd.h"

using std::string;
using std::istream;

class ClConstraint;

class ClVarLookupFunction : public std::unary_function<const string &,ClVariable *> {
public:
  virtual ~ClVarLookupFunction () {};
  virtual ClVariable *operator()(const string &) const { return &clvNil; }
};


// Attempts to read a constraint of input stream in
// Returns constraint (freshly allocated, client responsibility to deallocate)
// if succesful. Otherwise, returns 0.
ClConstraint *PcnParseConstraint(istream &xi, const ClVarLookupFunction &lookup_func,
                                 const ClStrength &strength = ClsRequired());

class ClVarLookupInMap : public ClVarLookupFunction {
public:
  ClVarLookupInMap(StringToVarMap *pmapVars, bool fAutoCreate) 
      : _pmapVars(pmapVars), _fAutoCreate(fAutoCreate) { }

  virtual ~ClVarLookupInMap () {};

  ClVariable *operator()(const string &str) const
    { 
      if (!_pmapVars)
        return &clvNil;
      StringToVarMap &_mapVars = *_pmapVars;
      StringToVarMap::iterator it = _mapVars.find(str);
      if (it != _mapVars.end()) {
        return &it->second;
      } else if (_fAutoCreate) {
        // save the old symbol table, if any
        StringToVarMap *pmapOld = ClVariable::VarMap();
	// and set it to this one temporarily
        ClVariable::SetVarMap(&_mapVars);
	ClVariable *pclv = new ClVariable(str);
        // now switch it back
        ClVariable::SetVarMap(pmapOld);
        return pclv;
      } else {
        return &clvNil;
      }
    }
private:
  StringToVarMap *_pmapVars;
  bool _fAutoCreate;
};


/* the "yyerror" function */
void clerror(const char *sz);

struct ClParseData {
  ClParseData(istream &xi, const ClVarLookupFunction &lookup_func)
      : _xi(xi), _lookup_func(lookup_func) { }

  ClConstraint *Pcn() { return _pcn; }

  ClVarSet _readOnlyVarsSoFar;
      
  istream & _xi;
  ClConstraint * _pcn;
  const ClVarLookupFunction &_lookup_func;
};


inline 
const ClStrength
&ClsFromSz(const char *sz)
{
  const ClStrength *pcls = &ClsRequired();
  double n1, n2, n3;
  if (strcmp("required",sz) == 0)
    ; /* initialized to ClsRequired, above */
  else if (strcasecmp("strong",sz) == 0) { pcls = &ClsStrong(); }
  else if (strcasecmp("medium",sz) == 0) { pcls = &ClsMedium(); }
  else if (strcasecmp("weak",sz) == 0) { pcls = &ClsWeak(); }
  else if (sscanf(sz,"(%lf,%lf,%lf)",&n1,&n2,&n3) == 3) {
    pcls = new ClStrength("parsed",n1,n2,n3);
  } else {
    throw ExCLParseErrorMisc("Error parsing strength");
  }
  return *pcls;
}


#endif